过滤出一个轮廓在OpenCV的C / C ++ [英] Filter out only one contour in OpenCV C/C++

查看:187
本文介绍了过滤出一个轮廓在OpenCV的C / C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让一个程序来检测使用基于Canny算子滤波器和轮廓发现功能的摄像机/摄像头的任何形状的物体。下面是我的程序:

I'm trying to make a program to detect an object in any shape using a video camera/webcam based on Canny filter and contour finding function. Here is my program:

int main( int argc, char** argv )
{
CvCapture *cam;
CvMoments moments;
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contours = NULL;
CvSeq* contours2 = NULL;
CvPoint2D32f center;
int i;

cam=cvCaptureFromCAM(0);
if(cam==NULL){
    fprintf(stderr,"Cannot find any camera. \n");
    return -1;
}
while(1){
    IplImage *img=cvQueryFrame(cam);
    if(img==NULL){return -1;}
    IplImage *src_gray= cvCreateImage( cvSize(img->width,img->height), 8, 1);
    cvCvtColor( img, src_gray, CV_BGR2GRAY );
    cvSmooth( src_gray,  src_gray, CV_GAUSSIAN, 5, 11);
    cvCanny(src_gray, src_gray, 70, 200, 3);

    cvFindContours( src_gray, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0,0));
    if(contours==NULL){ contours=contours2;}
    contours2=contours;
    cvMoments(contours, &moments, 1);

    double m_00 = cvGetSpatialMoment( &moments, 0, 0 );
    double m_10 = cvGetSpatialMoment( &moments, 1, 0 );
    double m_01 = cvGetSpatialMoment( &moments, 0, 1 );
    float gravityX = (m_10 / m_00)-150;
    float gravityY = (m_01 / m_00)-150;
    if(gravityY>=0&&gravityX>=0){
        printf("center point=(%.f, %.f) \n",gravityX,gravityY); }

    for (; contours != 0; contours = contours->h_next){
        CvScalar color = CV_RGB(250,0,0);
        cvDrawContours(img,contours,color,color,-1,-1, 8, cvPoint(0,0));
    }

    cvShowImage( "Input", img );
    cvShowImage( "Contours", src_gray );
    cvClearMemStorage(storage);
    if(cvWaitKey(33)>=0) break;
}
cvDestroyWindow("Contours");
cvDestroyWindow("Source");
cvReleaseCapture(&cam);
}

此程序将检测由照相机捕获的所有轮廓与轮廓的平均坐标将被打印。我的问题是如何筛选出只有一个对象/轮廓,所以我可以得到更多的precise(X,Y)对象的位置?如果可能的话,任何人都可以告诉我的如何使用(X,Y)来标记物体的中心坐标

This program will detect all contours captured by the camera and the average coordinate of the contours will be printed. My question is how to filter out only one object/contour so I can get more precise (x,y) position of the object? If possible, can anyone show me how to mark the center of the object by using (x,y) coordinates?

在此先感谢。干杯

P / S:很抱歉我不能上传截图尚未但是如果有的帮助,这里是的链接

p/s:Sorry I couldn't upload a screenshot yet but if anything helps, here's the link.

编辑:为了使我的问题更清楚:

To make my question more clear:


  • 例如,如果我只想要过滤出从上面我的截图的广场上,我该怎么办?

  • 欲过滤掉的对象具有最大轮廓区域和最重要的是具有形状(任何形状),而不是一个直链或曲线线

  • 我仍然与光滑和精明的实验值,所以如果有任何人使用我的程序,请更改值检测轮廓的问题。

推荐答案

我觉得是可以解决相当容易的。我会建议一些形态学操作之前的轮廓检测的。另外,我建议筛选出较小的元素,并且在图像中获得最大的元件作为唯一一个静止

I think it can be solved fairly easy. I would suggest some morphological operations before contour detection. Also, I would suggest filtering "out" smaller elements, and getting the biggest element as the only one still in the image.

我建议:


  • 用于滤除(直线或曲线):你必须决定你有什么你自己考虑一个行和形的边界。比方说,你考虑所有厚度的 5像素以上的对象的是对象,而小于5个像素的那些跨为线。使用一个5x5的正方形或3像素大小的钻石形状的的形态开的作为的结构元素的会照顾这。

  • for filtering out lines (straight or curved): you have to decide what do you yourself consider a border between a "line" and a "shape". Let's say you consider all the objects of a thickness 5 pixel or more to be objects, while the ones that are less than 5 pixels across to be lines. An morphological opening that uses a 5x5 square or a 3-pixel sized diamond shape as a structuring element would take care of this.

对于一般过滤掉​​的小物件:如果对象是任意形状的,纯粹的形态开的不会做:你必须做一个的代数开幕的。一种特殊类型的代数的开孔是一个区域开口:即删除具有(像素)的面积比给定的阈值小的图像中的所有连接的组件的操作。如果你有一个的上限的上规模的无趣的对象的,或者的下限的上的有趣的大小,该值应该被用作阈值。你也许可以得到一个更大的形态开一个类似的效果,但它不会那么灵活。

for filtering out small objects in general: if objects are of arbitrary shapes, purely morphological opening won't do: you have to do an algebraic opening. A special type of algebraic openings is an area opening: an operation that removes all the connected components in the image that have (pixel) area smaller than a given threshold. If you have an upper bound on the size of uninteresting objects, or a lower bound on the size of interesting ones, that value should be used as a threshold. You can probably get a similar effect with a larger morphological opening, but it will not be so flexible.

用于滤除所有的,除了最大的对象:这听起来像从最小的一个最大的一个应该工作拆卸连接组件。尝试的标签的连接组件的。上的二进制(黑色和放大器;白色图像),该图像变换的工作方式是创建一个灰度图像,标签的背景为0(黑色),并用一个不同的,增加的灰度值的每个组件。在结束时,每个目标的象素是由一个不同的值标示。现在,您可以简单地看一下灰度直方图,并找到最像素的灰度值。将所有其他的灰度等级为0(黑色),离开了图像中的唯一对象是最大的一个。

for filtering out all the objects except the largest: it sounds like removing connected components from the smallest one to the largest one should work. Try labeling the connected components. On a binary (black & white image), this image transformation works by creating a greyscale image, labeling the background as 0 (black), and each component with a different, increasing grey value. In the end, pixels of each object are marked by a different value. You can now simply look at the gray level histogram, and find the grey value with the most pixels. Set all the other grey levels to 0 (black), and the only object left in the image is the biggest one.

的建议是从最简单的写入到最复杂的。不过,我认为的OpenCV可以帮助任何与这些。形态的腐蚀,膨胀,开启和关闭的在OpenCV的实现。我想你可能需要构建你自己的代数开放运营商(或相结合OpenCV的基本形态打),但我敢肯定的OpenCV可以帮助你都标注连接组件并检查所产生的灰度图像的直方图。

The suggestions are written from the simplest to the most complex ones. Still, I think OpenCV can be of help with any of these. Morphological erosion, dilation, opening and closing are implemented in OpenCV. I think you might need to construct an algebraic opening operator on your own (or play with combining OpenCV basic morphology), but I'm sure OpenCV can help you with both labeling the connected components and examining the histogram of the resulting greyscale image.

在年底,从一个对象只像素离开的时候,你做的康力轮廓检测。

In the end, when only pixels from one object are left, you do the Canny contour detection.

这篇关于过滤出一个轮廓在OpenCV的C / C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆