OpenCV边界框

时间:2013-02-06 15:47:38

标签: c++ opencv image-processing

我正在使用C ++环境中的OpenCV软件。 目的是检测拳击手套并在手套轮廓周围绘制一个边界框

我遇到的问题是边界框被淹没了多次,实际上是绘制了多个框。我过去几天试图做的是以某种方式消除绘制的盒子数量并且只绘制一个大的边界框。

我正在寻找一些技术来填充整个对象,我相信在这种情况下会有所帮助。

下面我发布了用于实现图像显示结果的代码:

vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
vector<Vec3f> vecCircles;               
vector<Vec3f>::iterator itrCircles;

while(1)
{
    Mat frame;
    cap >> frame; // get a new frame from camera
    /////////////////////
    Mat imgHSV;
    cvtColor( frame, imgHSV, CV_BGR2HSV );
    ////////////////////
    Mat blur_out;
    GaussianBlur(imgHSV, blur_out, Size(1,1),2.0,2.0);
    ////////////////////
    Mat range_out;
    inRange(blur_out, Scalar(100, 100, 100), Scalar(120, 255, 255), range_out);
    ////////////////////
    findContours(range_out, contours, hierarchy, CV_RETR_TREE,  CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

     /// Approximate contours to polygons + get bounding rects and circles
     vector<vector<Point> > contours_poly( contours.size() );
     vector<Rect> boundRect( contours.size() );
     vector<Point2f>center( contours.size() );
     vector<float>radius( contours.size() );

     for( int i = 0; i < contours.size(); i++ )
     { 
         approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
         boundRect[i] = boundingRect( Mat(contours_poly[i]) );
     }

     /// Draw polygonal contour + bonding rects
     Mat drawing = Mat::zeros( range_out.size(), CV_8UC3 );
     for( int i = 0; i< contours.size(); i++ )
     {
         Scalar color = Scalar(255,0,255);
         drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
         rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );          
     }

enter image description here

如果有人可以提出一些提示或提供一些信息来源,我可以找到问题的答案。

编辑(快速更新):

我设法将输出图像逐渐安静地提升到安静的结果。关键是使用erode&amp; amp;扩张以及我的findContours()功能。我将CV_RETR_TREE更改为CV_RETR_EXTERNAL。我还解决了一些其他的小问题,但结果很好:

enter image description here

不知道我是否应该在这里写这个或打开新的线程......但是现在我需要一些关于组件标记和提取参数的帮助,例如中心点和区域。 :)

4 个答案:

答案 0 :(得分:6)

本主题中的

Take a look at my other answer。编译该代码并记住激活已注释掉的代码。

<强>结果

enter image description here

答案 1 :(得分:5)

您当前在每个轮廓周围绘制一个边界框,findContour将在每个连接的白色或黑色组件周围找到一个轮廓,其中有许多在您的图片中。

所以我要做的第一件事是在阈值图像上使用一些形态学操作过滤所有噪声:做一些opening and closing,这两者都是dilation and erosion的组合。

在你的情况下像cvDilate(2次); cvErode(4次); cvDilate(2次)

这应该将所有白色斑点合并为一个光滑的斑点,但中间的黑洞将保留。 您可以按大小找到合适的一个,但使用CV_RETR_EXTERNAL而不是CV_RETR_TREE调用findContours会更容易,然后它将只返回最外面的轮廓。

答案 2 :(得分:1)

在找到轮廓之前,您应该应用erodedilate等形态滤镜。之后,您可以通过计算其size或边界框的高度和高度来查找轮廓并省略小轮廓。最后,您可以使用hierarchy消除其他轮廓内的那些。

答案 3 :(得分:0)

如b_m所述,您需要应用形态学操作。然后,我会做一些事情,比如找到图像中最大的轮廓,然后仅在该轮廓周围绘制边界框。我为我的一个项目创建了以下函数,如果以正确的方式使用,我认为它会帮助你

CvSeq* findLargestContour(CvSeq* contours){

  CvSeq* current_contour = contours;
  double largestArea = 0;
  CvSeq* largest_contour = NULL;

  // check we at least have some contours

  if (contours == NULL){return NULL;}

  while (current_contour != NULL){

      double area = fabs(cvContourArea(current_contour));

      if(area > largestArea){
          largestArea = area;
          largest_contour = current_contour;
      }

      current_contour = current_contour->h_next;
  }

  // return pointer to largest

  return largest_contour;

}