【问题标题】:directional edge detection in OpenCVOpenCV中的定向边缘检测
【发布时间】:2014-05-29 09:42:20
【问题描述】:

我想检测具有特定角度/方向的边缘。

改编自 SO 中的一篇文章,我想出使用 OpenCV 幅度、相位和 Sobel 函数来过滤掉不需要的边缘点。然后用幅值图(以相位图为条件)输出边缘点。

但是,结果与 Canny 边缘函数不相似。过滤掉带有不需要的角度的边缘很好,但检测到的边缘是点的斑点,而不是细线边缘

在使用 findContours 后,左边缘图像也被绘制出来了,但这几乎没有帮助

1) 还应该添加什么来模拟 Canny 处理?

2) 至于定向边缘检测的目的,这种方法是否比使用典型 Sobel 内核以外的定向内核更健壮?

谢谢!

编辑 01:

忘记输入我的代码link

【问题讨论】:

  • 公认的答案是正确的,但可能已经过时了。不知道是什么时候添加的,但是现在OpenCV中有LSD和霍夫线检测方法。另外,更多信息请参考:stackoverflow.com/questions/43050075/…

标签: opencv computer-vision edge-detection


【解决方案1】:

或者,您可以尝试 lsd,(http://www.ipol.im/pub/art/2012/gjmr-lsd/)。它将线输出为两个点对,因此也可以进行定向过滤。

还有另一个线段实现@http://sourceforge.net/projects/lswms/ 虽然上面的 lsd 链接效果更好

如果您想要单个像素边缘,则需要进行骨架化/细化

编辑

在编译时将lsd.c 重命名为lsd.cpp。我使用了 url 中附加的 1.6 版。下面的代码和结果。您也可以调整阈值以抑制小段。

#include "opencv2/opencv.hpp"
using namespace cv;
#include "lsd.h"
void lsd_call(Mat& im)
{
    Mat gray;
    cvtColor(im,gray,CV_BGR2GRAY);
    Mat imgdouble;
    gray.convertTo(imgdouble,CV_64FC1);
    double * image;
    double * out;
    int x,y,i,j,n;
    out = lsd(&n,(double*)imgdouble.data,imgdouble.cols,imgdouble.rows);
    Mat lines = im.clone();
    Mat lines_binary = Mat::zeros(gray.size(),CV_8UC1);
    for(i=0;i<n;i++)
    {
        double x1,y1,x2,y2,w;
        x1 = out[7*i+0];
        y1 = out[7*i+1];
        x2 = out[7*i+2];
        y2 = out[7*i+3];
        w = out[7*i+4];
        double length = sqrt(pow(x1-x2,2)+pow(y1-y2,2));
        double angle =  atan2(y2 - y1, x2 - x1) * 180 / CV_PI;

        if(angle<180 && angle>90)
        {
            line(lines,Point2d(out[7*i+0],out[7*i+1]),Point2d(out[7*i+2],out[7*i+3]),Scalar    (0,0,255));
            line(lines_binary,Point2d(out[7*i+0],out[7*i+1]),Point2d(out[7*i+2],out[7*i+3])    ,Scalar(255));
        }
        if(length>75)
        {
            //line(todraw,Point2d(out[7*i+0],out[7*i+1]),Point2d(out[7*i+2],out[7*i+3]),    Scalar(0,0,255),out[7*i+4]);
        }
    }
    imshow("lines",lines);
    imshow("lines_binary",lines_binary);
    imwrite("c:/data/lines.jpg",lines);
    imwrite("c:/data/linesbinary.jpg",lines_binary);
    free( (void *) out );

}
int main(int argc,char** argv )
{
    Mat im = imread("c:/data/lines.png");
    lsd_call(im);
    waitKey(0);
}

【讨论】:

  • 不错的答案!即使实施这种方法也需要一些时间。谢谢!
  • 你好,代码已经在链接中提供,集成到opencv中并不难。我已经在答案中展示了如何做到这一点。在我看来,lsd 在很多情况下都给我带来了不错的效果。也许您至少应该尝试一下。
  • 不知道是什么时候加入opencv的,但是现在OpenCV中有LSD和Hough Lines检测方法。另外,欲了解更多信息,请参阅:stackoverflow.com/questions/43050075/…
【解决方案2】:

1) 由于沿邻居的非最大值抑制,Canny 边缘检测器会产生细边缘。 为了模仿这一点,您需要选择沿该方向具有最大边缘响应的边缘像素。所以可以通过这种方式防止点的斑点。

您可能已经猜到,网格中较弱的图像可以通过您定义的阈值进行抑制。

2) 遗憾的是,我无法给出明确的答案。对于给定的天使,内核可能受到限制 离散化。因此,对于许多不同的角度,这种方法“应该”更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 2012-08-12
    相关资源
    最近更新 更多