13

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

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

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

  • 最琐碎的过滤不可用(拒绝非闭合轮廓)

所以我的问题是:是否有可能获得非封闭 Canny 边缘的非封闭轮廓? 或者解决上述两个问题的标准方法是什么?

Canny 是一个非常好的工具,但我需要一种将 2D b/w 图像转换为易于处理的方法。类似于连接组件按组件的步行顺序列出所有像素。所以我可以过滤循环,并将其输入到 approxPolyDP。

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

4

3 回答 3

16

我为问题中的 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);

它也可以反过来工作,即:寻找有孩子的轮廓(hierarchy[i][2] >= 0),但在我的情况下,父检查会产生更好的结果。

于 2013-04-07T20:16:07.687 回答
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 个轮廓,第一个是图像边界(索引为 0 的轮廓),可以轻松跳过。

于 2015-02-15T07:37:08.910 回答
1

我会这样做 1. Canny 进行边缘检测 2. 使用 houghtransform 检测边缘。3. 检测成 90 角的两条边。

于 2013-04-01T22:55:46.470 回答