使用C ++ FindContours在视频图像中查找轮廓的问题 [英] Problems with finding contour in a video image using C++ FindContours

查看:225
本文介绍了使用C ++ FindContours在视频图像中查找轮廓的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在正在工作的程序几乎已完成,但我对结果并不满意。通过使用Canny算法,我设法清楚地了解了对象的轮廓,但是程序在识别轮廓和用红线绘制轮廓时存在一些问题。该程序:

  void setwindowSettings(){
namedWindow(Contours,CV_WINDOW_AUTOSIZE);

createTrackbar(LowerC,Contours,& lowerC,255,NULL);
createTrackbar(UpperC,Contours,& upperC,255,NULL);
}

void wait(void)
{
long t = 30000000;
while(t--);
}

int main(void)
{
VideoCapture cap(0); //打开默认摄像头
if(!cap.isOpened())//检查我们是否成功
返回-1;

Mat框架,前景,图像;
double pt1,pt2,area;
Rect rect;
int i;

vector< vector< Point> >轮廓;
vector< vector< Point> > largest_contours;

namedWindow(Capture,CV_WINDOW_AUTOSIZE);
setwindowSettings();

while(1){
cap>>帧; //从相机获取一个新帧
if(frame.empty())
break;
image = frame.clone();

cvtColor(image,foreground,CV_BGR2GRAY);
GaussianBlur(前景,前景,大小(9,11),0,0);
Canny(前景,前景,lowerC,upperC,3);

findContours(前景,轮廓,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);

if(contours.empty())
继续;

double largest_area = 0;

for(i = 0; i< contours.size(); i ++){//得到最大轮廓
area = fabs(contourArea(contours [i]));
if(area> = largest_area){
largest_area = area;
largest_contours.clear();
largest_contours.push_back(contours [i]);
}
}

if(largest_area> = 3000){//如果超出最小最大区域,则绘制最大轮廓
drawContours(image,largest_contours,-1,标量(0,0,255),2);
printf(area =%.f\ n,largest_area);
}

wait();

imshow(捕获,图片);
imshow(轮廓,前景);

如果(waitKey(30)> = 0)中断;
}
//摄像机将在VideoCapture析构函数中自动取消初始化
return 0;
}

计划摘要:


  1. 从相机获取图像

  2. 噪音过滤(转换为灰色→模糊→Canny)

  3. 查找轮廓

  4. 在图像中找到最大的轮廓及其区域,即物体

  5. 在对象周围画一条红线并打印出最大的区域

  6. 冲洗并重复

结果:



<很少我得到了我想要的东西;检测到轮廓,绘制红线( GOOD ONE ):





...通常我得到了这个;未检测到轮廓,不是红线( BAD ONE ):





获得 GOOD ONE 的机会大约是 1/20 这不是很好。此外,当对象周围出现红线时,轮廓屏幕中对象轮廓线将闪烁(参见GOOD ONE图片)。
我正在使用我的一个物体(一个小的黑色方框)来解决这个问题但是请注意,这个物体检测程序的主要目的是来检测物体,无论其形状或颜色如何。



所以我的问题是:


  1. 为什么我还能得到虽然轮廓像白昼一样清晰,但还是很糟糕?

  2. 谁能分享一个更好的想法来改进轮廓检测? (即更好的模糊算法)

  3. 当在物体周围绘制红线时,如何避免轮廓线闪烁?

编辑:我刚刚发现轮廓的线条闪烁不是因为红线围绕它绘制(使用 drawContours 函数),但它发生在<$ c检测到最大轮廓之后$ c> findContours 函数并计算为最大轮廓。



关于no的问题。 3单击此处在这里观看视频,点击它!



提前致谢。



PS:我在Visual C ++ 2010 Exp上使用OpenCV 2.4.3。

解决方案


  1. 由于您使用的是最大轮廓的事实,所以我假设您正在尝试检测出现的最大物体在相机的视野中。我想知道为什么右上方的窗户灯/明亮光源不会产生任何轮廓(可能是由于模糊)。您可以存储背景图像并从对象出现的图像中减去背景图像。通过这种方式,您可以派生对象。您可以在差异图像中应用轮廓查找。 absdiff(frame_now,frame_backgrnd,diff)其中 diff 是差异图像。

  2. 如果物体处于运动中并且您想要检测到您可以使用光流与最大轮廓相结合来检测物体。

  3. 尝试在没有模糊功能的情况下进行处理,然后检测最大的contourArea。

  4. 为了绘制积分,试试这个

      for(int i = 1; i<(int)largest_contours [0] .size(); i ++)
    line(image,largest_contours [0 ] [I-1],largest_contours [0] [I],CV ::标量(0,0,255),2,8,0);



The program I'm working right now is almost done but I'm not very satisfy with the result. By using Canny algorithm, I managed to get a very clear of the object's contour but the program has some problem to recognize the contour and draw the contour with a red line. The program:

void setwindowSettings(){
    namedWindow("Contours", CV_WINDOW_AUTOSIZE);

    createTrackbar("LowerC", "Contours", &lowerC, 255, NULL);
    createTrackbar("UpperC", "Contours", &upperC, 255, NULL);
}

void wait(void)
{
    long t=30000000;
    while(t--);
}

int main(void)
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened())  // check if we succeeded
    return -1;

Mat frame,foreground,image;
double pt1, pt2, area;
Rect rect;
int i;

vector<vector<Point> > contours;
vector<vector<Point> > largest_contours;

namedWindow("Capture", CV_WINDOW_AUTOSIZE);
setwindowSettings();

while(1){
    cap >> frame; // get a new frame from camera
    if( frame.empty() )
            break;
    image=frame.clone();

    cvtColor(image,foreground,CV_BGR2GRAY);
    GaussianBlur(foreground,foreground,Size(9,11),0,0);
    Canny(foreground,foreground,lowerC,upperC,3);

    findContours(foreground,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);  

    if(contours.empty())
        continue;

    double largest_area = 0;

    for( i= 0; i < contours.size(); i++){  // get the largest contour
        area = fabs(contourArea(contours[i]));
        if(area >= largest_area){
            largest_area = area;
            largest_contours.clear(); 
            largest_contours.push_back(contours[i]);
        }
    }

    if(largest_area>=3000){   // draw the largest contour if exceeded minimum largest area 
        drawContours(image,largest_contours,-1,Scalar(0,0,255),2);
        printf("area = %.f\n",largest_area);
    }

    wait();

    imshow( "Capture",image );
    imshow("Contours",foreground);

    if(waitKey(30) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}

Program summary:

  1. Get images from camera
  2. Noise filtration (Convert to gray → blur → Canny)
  3. Find contours
  4. Find the largest contour and its area in the image aka the object
  5. Draw a red line around the object and print out the largest area
  6. Rinse and repeat

And the results:

Rarely I got what I want; Contour detected, red line drawn (GOOD ONE):

...and usually I got this; No contour detected, not red line (BAD ONE):

The chances to get the GOOD ONE are about 1/20 which is not very good. Also, the line of the object's contour in Contours screen will blink when the red line appears around the object (see the GOOD ONE picture). I'm using one of my object (A small black square box) for this question but please note that the main objective of this object detection program is to detect the object regardless of its shape or its color.

So my questions are:

  1. Why I still get the BAD ONES despite the contour is as clear as day?
  2. Can anyone share a better idea on how to improve the contour detection? (i.e better blur algorithm)
  3. How to avoid the contour's line from blinking when the red line is drawn around the object?

EDIT: I just discovered that contour's line blinking is not because of the red line drawn around it (either with drawContoursor line function) but it happens after the largest contour is detected by findContours function and calculated as the largest contour.

For question about no. 3 click HERE. VIDEO HERE, CLICK IT!!!

Thanks in advance.

PS: I'm using OpenCV 2.4.3 on Ms Visual C++ 2010 Exp.

解决方案

  1. Since you are using the fact of largest contour so I presume you are trying to detect the largest object appearing in the field of view of the camera.I wonder why the window light/bright light source at top right doesn't create any contour(may be due to blurring). You can store the background image and subtract it from the image where the object appears. This way you can derive the object.You can apply a contour finding in the difference image.absdiff(frame_now,frame_backgrnd,diff) where diff is the difference image.
  2. If the object is in motion and you want to detect you can use optical flow combined with largest contour to detect the object.
  3. Try doing you process without the blurring function and then detect the largest contourArea.
  4. For plotting the points try this

    for(int i = 1;i<(int)largest_contours[0].size();i++)
         line(image,largest_contours[0][i-1],largest_contours[0][i],cv::Scalar(0,0,255),2,8,0);
    

这篇关于使用C ++ FindContours在视频图像中查找轮廓的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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