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

查看:563
本文介绍了在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);
}

此程序将检测摄像机拍摄的所有轮廓和将打印轮廓。我的问题是如何只过滤一个对象/轮廓,所以我可以得到更精确的(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 suggest:

我建议:


  • 用于过滤线(直线或曲线):您必须决定自己认为线和形状。假设您将所有厚度 5像素或更多的对象视为对象,而小于5像素的对象则是线。使用5x5正方形或3像素大小的菱形作为结构化元素形态开口会处理此问题。

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.

通常用于过滤小对象:如果对象具有任意形状,纯粹的形态开放将不会执行:您必须代数开头。特殊类型的代数开口是区域开口:去除图像中具有小于给定阈值的(像素)面积的所有连接分量的操作。如果您对无趣对象的大小上限,或有趣的对象的大小 >,则应将该值用作阈值。

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.

用于过滤掉所有对象,除了最大:这听起来像删除连接的组件从最小的一个到最大的应该工作。请尝试标记连接的组件。在二进制(黑白图像)上,该图像变换通过创建灰度图像,将背景标记为0(黑色),并且每个分量具有不同的增加的灰度值来工作。最后,每个对象的像素由不同的值标记。您现在可以简单地查看灰度级直方图,并找到具有最多像素的灰度值。

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.

最后,当只剩下一个对象的像素时,就进行Canny轮廓检测。

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

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

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