首页 文章

OpenCV将Canny边缘转换为轮廓

提问于
浏览
8

我有一个OpenCV应用程序来自办公室内部的网络摄像头流(很多细节),我必须找到一个人工标记 . 标记是在白色背景的一个黑角规 . 我使用Canny来查找边缘和cvFindContours进行轮廓加工,然后使用aboutPolyDP和co . 用于过滤和查找候选者,然后使用局部直方图进一步过滤,bla bla bla ...

这或多或少有效,但不完全是我想要的 . FindContours总是返回一个闭环,即使Canny创建一个非闭合线 . 我得到一个轮廓走在线的两侧形成一个环 . 对于Canny图像(我的标记)上的封闭边缘,我得到2个轮廓,一个在内部,另一个在外面 . 我不得不对这个操作有问题:

  • 我为每个标记得到2个轮廓(不是那么严重)

  • 最无关紧要的过滤不可用(拒绝非闭合轮廓)

So my question: is it possible to get non-closed contours for non-closed Canny edges? 或者解决上述2个问题的标准方法是什么?

Canny是一个非常好的工具,但我需要一种方法将2D黑白图像转换为易于处理的东西 . 类似连接组件的东西,列出组件的步行顺序中的所有像素 . 所以我可以过滤循环,并将其提供给approxPolyDP .

更新:我错过了一些重要的细节:标记可以处于任何方向(它不是面向摄像机的正面,没有直角),实际上我正在做的是3D方向估计,基于标记的2D投影 .

3 回答

  • 1

    我找到了问题中2个问题的简洁解决方案 . 技巧是启用2级层次结构生成(在findCountours中)并查找具有父级的轮廓 . 这将返回封闭的Canny边缘的内部轮廓,仅此而已 . 非闭合边缘被自动丢弃,每个标记将具有单个轮廓 .

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(CannyImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0,0) );
    for (unsigned int i=0; i<contours.size(); i++)
        if (hierarchy[i][3] >= 0)   //has parent, inner (hole) contour of a closed edge (looks good)
            drawContours(contourImage, contours, i, Scalar(255, 0, 0), 1, 8);
    

    它也可以反过来,即:查找具有子元素的等高线(层次结构[i] [2]> = 0),但在我的情况下,父检查会产生更好的结果 .

  • 2

    我有同样的问题与重复的轮廓,甚至扩张和侵蚀无法解决它:

    Mat src=imread("E:\\test.bmp"),gry,bin,nor,dil,erd;
    GaussianBlur( src, nor, Size(5,5),0 );  
    cvtColor(nor,gry,CV_BGR2GRAY);  
    Canny(gry,bin,100,150,5,true);
    dilate(bin,dil,Mat());
    erode(dil,erd,Mat());
    Mat tmp=bin.clone();
    vector<vector<Point>> conts;
    vector<Vec4i> hier;
    findContours(tmp,conts,hier,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE);
    

    此图像(test.bmp)包含3个轮廓,但findContours返回6个!我用阈值和问题解决了:

    Mat src=imread("E:\\test.bmp"),gry,bin,nor,dil,erd;
    GaussianBlur( src, nor, Size(5,5),0 );  
    cvtColor(nor,gry,CV_BGR2GRAY);
    threshold(gry,bin,0,255,THRESH_BINARY+THRESH_OTSU);     
    vector<vector<Point>> conts;
    vector<Vec4i> hier;
    findContours(bin,conts,hier,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE);
    

    现在返回4个轮廓,第1个是图像边界(索引为0的轮廓),可以很容易地跳过 .

  • 11

    我将如何做1. Canny用于边缘检测2.使用houghtransform检测边缘 . 3.检测角度为90°的两条边 .

相关问题