本文介绍了opencv-计算来自canny的非方向性边缘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以帮助我如何使用opencv cannyedge检测来计算非定向边缘的数量吗?我有一个来自opencv的cannyEdge图像,我想有一个基于边缘方向的直方图,在那里我可以算出他的定向边缘和非定向边缘的数量.

can anyone help me how to count the number of non directional edge using opencv cannyedge detection? I have a cannyEdge image from opencv and I would like to have an histogram based on edge directions and there by i can count he number of directional and non directional edges.

推荐答案

我认为您将边缘检测与梯度检测混淆了. Canny提供了基于梯度幅度的边缘贴图(通常使用Sobel运算符,但也可以使用其他方法),因为Canny仅返回阈值梯度幅度信息,因此无法为您提供方向信息.

I think you are confusing edge detection with gradient detection. Canny provides an edge map based on the gradient magnitude (normally using a Sobel operator, but it can use others) because Canny only returns the thresholded gradient magnitude information it cannot provide you with the orientation information.

我应该澄清一下,Canny算法的确将梯度方向用于非最大抑制步骤.但是,Canny的OpenCV实现会向您隐藏此方向信息,并且仅返回边缘量级图.

EDIT : I should clarify that the Canny algorithm does use gradient orientation for the non-maximum suppression step. However, the OpenCV implementation of Canny hides this orientation information from you, and only returns an edge magnitude map.

获取梯度的大小和方向的基本算法如下:

The basic algorithm to get magnitude and orientation of the gradient is as follows:

  1. 在X方向(Sx)上计算Sobel.
  2. 沿Y方向(Sy)计算Sobel.
  3. 计算梯度幅度sqrt(Sx*Sx + Sy*Sy).
  4. 使用arctan(Sy / Sx)计算梯度方向.
  1. Compute Sobel in the X direction (Sx).
  2. Compute Sobel in the Y direction (Sy).
  3. Compute the gradient magnitude sqrt(Sx*Sx + Sy*Sy).
  4. Compute the gradient orientation with arctan(Sy / Sx).

可以使用以下OpenCV函数实现此算法: Sobel 幅度相位.

This algorithm can be implemented using the following OpenCV functions: Sobel, magnitude, and phase.

下面是一个计算梯度幅度和相位以及显示梯度方向的粗略颜色映射的示例:

Below is a sample that computes the gradient magnitude and phase as well as shows a coarse color mapping of the gradient orientations:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <vector>

using namespace cv;
using namespace std;

Mat mat2gray(const cv::Mat& src)
{
    Mat dst;
    normalize(src, dst, 0.0, 255.0, cv::NORM_MINMAX, CV_8U);

    return dst;
}

Mat orientationMap(const cv::Mat& mag, const cv::Mat& ori, double thresh = 1.0)
{
    Mat oriMap = Mat::zeros(ori.size(), CV_8UC3);
    Vec3b red(0, 0, 255);
    Vec3b cyan(255, 255, 0);
    Vec3b green(0, 255, 0);
    Vec3b yellow(0, 255, 255);
    for(int i = 0; i < mag.rows*mag.cols; i++)
    {
        float* magPixel = reinterpret_cast<float*>(mag.data + i*sizeof(float));
        if(*magPixel > thresh)
        {
            float* oriPixel = reinterpret_cast<float*>(ori.data + i*sizeof(float));
            Vec3b* mapPixel = reinterpret_cast<Vec3b*>(oriMap.data + i*3*sizeof(char));
            if(*oriPixel < 90.0)
                *mapPixel = red;
            else if(*oriPixel >= 90.0 && *oriPixel < 180.0)
                *mapPixel = cyan;
            else if(*oriPixel >= 180.0 && *oriPixel < 270.0)
                *mapPixel = green;
            else if(*oriPixel >= 270.0 && *oriPixel < 360.0)
                *mapPixel = yellow;
        }
    }

    return oriMap;
}

int main(int argc, char* argv[])
{
    Mat image = Mat::zeros(Size(320, 240), CV_8UC1);
    circle(image, Point(160, 120), 80, Scalar(255, 255, 255), -1, CV_AA);

    imshow("original", image);

    Mat Sx;
    Sobel(image, Sx, CV_32F, 1, 0, 3);

    Mat Sy;
    Sobel(image, Sy, CV_32F, 0, 1, 3);

    Mat mag, ori;
    magnitude(Sx, Sy, mag);
    phase(Sx, Sy, ori, true);

    Mat oriMap = orientationMap(mag, ori, 1.0);

    imshow("magnitude", mat2gray(mag));
    imshow("orientation", mat2gray(ori));
    imshow("orientation map", oriMap);
    waitKey();

    return 0;
}

使用圆形图像:

Using a circle image:

这将产生以下幅值和方向图像:

This results in the following magnitude and orientation images:

最后,这是渐变方向图:

Finally, here is the gradient orientation map:

更新:阿比德实际上​​在评论这里的含义是什么?"中提出了一个很大的问题,我认为需要进一步讨论.我假设phase函数不会从正y轴向下的正常图像处理角度切换坐标系,而正x轴则正确.假定此假设,将导致下图显示圆周围的梯度方向矢量:

UPDATE : Abid actually asked a great question in the comments "what is meant by orientation here?", which I thought needed some further discussion. I am assuming that the phase function doesn't switch coordinate frames from the normal image processing standpoint of positive y-axis is down, and positive x-axis is right. Given this assumption that leads to following image showing the gradient orientation vectors around the circle:

这很难适应,因为轴是从数学课中通常使用的轴上翻转过来的.所以,梯度方向是法线矢量与梯度表面在增加方向上所成的角度改变.

This can be difficult to get used to since the axes are flipped from what we are normally used to in math class... So, gradient orientation is the angle made by the normal vector to the gradient surface in the direction of increasing change.

希望您发现这有帮助!

这篇关于opencv-计算来自canny的非方向性边缘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 21:43