为啥opencv会找到轮廓的边界点,无序且不完整?
Posted
技术标签:
【中文标题】为啥opencv会找到轮廓的边界点,无序且不完整?【英文标题】:Why opencv finds the contours' border-points, disordered and uncompleted?为什么opencv会找到轮廓的边界点,无序且不完整? 【发布时间】:2014-07-03 00:41:14 【问题描述】:我想写一个程序,可以用C++的opencv纠正答题卡。
但是当我使用cvFindContours()
时,轮廓的边界点还没有完全找到。
我的意思是,我没有封闭对象。 (我使用cvDilate
和cvErode
,不知道它们的真正功能,但是扩张省略了一些轮廓并腐蚀添加了一些额外的、不需要的轮廓)
更大的问题是我想在每个轮廓中找到一个中心点(将答案的位置与预定义的左侧和向下侧边栏进行比较),但是有些轮廓不是对称的,所以中心点的位置并不完全在中间。
看左边的黑色图片,在第二个轮廓中,检测到了一些底部的点,但没有检测到顶部的点。
cvCvtColor(pic, blackpic, CV_BGR2GRAY);
cvResize(blackpic, src0);
cvSmooth(src0, src0, CV_GAUSSIAN, 3, 3);
cvThreshold(src0, src, 140, 255, CV_THRESH_BINARY);
//Find Contour
CvMemStorage* st = cvCreateMemStorage();
CvSeq* first_contour = NULL;
cvFindContours(src, st, &first_contour, sizeof(CvContour), CV_RETR_LIST);
vector <vector <CvPoint> > cont;
vector <CvPoint> dot;
for (CvSeq* s = first_contour; s != NULL; s = s->h_next)
if (s -> total > C_MIN_SIZE && cvContourArea(s) > C_MIN_AREA)
cont.push_back(vector <CvPoint>()); //convert seq to vector
CvPoint c = cvPoint(0,0);
for (int i = 0; i < s -> total; i++)
CvPoint* p = CV_GET_SEQ_ELEM(CvPoint, s, i);
cont.back().push_back(*p);
CV_IMAGE_ELEM(test, uchar, p -> y, p -> x) = 255; //drawing each contour's point
c.x += p -> x; //find the center point by average
c.y += p -> y;
c.x = floor(c.x / s -> total);
c.y = floor(c.y / s -> total);
dot.push_back(c);
虽然我使用的是 C++,但我使用了 cv::Mat 和 cv::Point(C++ 结构)的 IplImage* 和 CvPoint(opencv 的 c 结构),如果可能,请不要使用 Mat 和 C++ 模式。
我不明白,当我通过cvDrawContours()
绘制轮廓时,轮廓是完全绘制的,但是当我亲自迭代轮廓的点并逐点绘制它们时,似乎大多数都是未检测到!
【问题讨论】:
findContours
有不同的方式来表示轮廓。一种方法(默认)是仅保存“一些”点并通过假设直线在它们之间进行插值。最有可能的是,drawContours 会填充这些线条,但您不会。在 C++ 中保存所有点,使用方法CV_CHAIN_APPROX_NONE
。根据docs.opencv.org/modules/imgproc/doc/… C 语法使用完全相同的参数。
我想,默认情况下所有的点都被存储了。谢谢
+ 为什么你们 *** 的成员只是喜欢具有特殊问题的问题,而您几乎不理解他们的标题? “所有简单的问题都会被否决”我认为这一定是您在 *** 中的首要原则。我搜索,尝试了几个小时,然后感到困惑!所以我有权利提问!但是你认为我的问题不是计算机行业的史诗,所以让我们立即投反对票!
【参考方案1】:
对于您的第一个问题,您可以在 Internet 上找到数以千计的链接来解释 Erode, Dilate 和所有其他基本图像处理支柱,花点时间阅读文档,不要跳过步骤。
第二个问题:
我不确定您对轮廓中心的期望是什么?你认为你会在这些椭圆的中心有一个点吗?不,这永远不会发生,如果是这样,恭喜图像处理历史上的这一大堆!
我建议做的是解决您的问题的简单操作:
-
找到轮廓(就像你现在做的那样)
计算每个轮廓的中心
当您将答案与中心位置进行比较时,不要使用
a == b
进行比较,因为这永远不会发生!相反,使用距离(阈值)的比较来确保您的软件的运行
例子:
bool correct;
CvPoint answer, center;
double distance = sqrt((answer.X - center.X)^2 + (answer.Y - center.Y)^2); // Euclidean distance
// judge using this distance
if (distance <= 5) // here you select the number as you (want) i gave example 5
correct = true; // correct answer :)
祝你好运
【讨论】:
我没有复制代码的下一行,在这些行中,我不是通过 == 来精确比较这些点,而是使用“8 像素”范围比较它们。 感谢您告诉我无法找到确切的中心。以上是关于为啥opencv会找到轮廓的边界点,无序且不完整?的主要内容,如果未能解决你的问题,请参考以下文章