删除区域<边界矩形< n OpenCV

时间:2014-04-10 01:00:30

标签: c++ opencv bounding-box

我正在使用文本块侵蚀图像,然后使用findContours()查找所有文本块,然后绘制其边界矩形。然而,有时候图像中的噪声会产生非常小的影响,这些影响要么在更大的矩形中,要么在没有文本的地方。

我正在使用此代码查找轮廓并绘制它们。

double element_size = 20;
RNG rng(12345);
Mat element = getStructuringElement( cv::MORPH_ELLIPSE,cv::Size( 2*element_size + 1, 2*element_size+1 ),cv::Point( element_size, element_size ) );
erode(quad, quad, element);
vector<vector<cv::Point> > contours;
vector<Vec4i> hierarchy;
quad.convertTo(quad, CV_8UC1);
findContours( quad, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );

vector<vector<cv::Point> > contours_poly( contours.size() );
vector<cv::Rect> boundRect( 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]) );
}

Mat drawing = Mat::zeros( quad.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
    Scalar color = Scalar(0,255, 0 );
    rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );
}

在这里运行样品后,我得到了回复:

enter image description here

如何修改我的代码,以便我可以删除任何不大于n的rect,这样我只能保留完整的文本块,我还需要删除围绕整个卡片的最大轮廓。< / p>

2 个答案:

答案 0 :(得分:3)

Yo可以使用contourArea来消除轮廓,在找到边界矩形之前使用下面的代码,这将删除面积小于阈值的所有轮廓。

double min_area=100; // area threshold

 for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
 {
   double area=contourArea( contours[i],false);  //  Find the area of contour
   if(area<min_area)
    contours.erase(contours.begin() + i);
 }

修改: -

对于任何打算使用上述代码的人,请参阅以下评论。

答案 1 :(得分:2)

要从cv::Rect中删除vector元素的更安全方法,您可以使用erase-remove idiom删除低于特定区域阈值的元素。这个方法 比按索引逐个删除元素更安全,就像Haris的回答一样,因为你不会冒险跑掉矢量的末尾。

boundRect.erase(std::remove_if(boundRect.begin(), boundRect.end(),
                               [] (cv::Rect r)
                               {
                                   const int min_area = 100;
                                   return r.area() < min_area;
                               }), boundRect.end());

这里我使用C ++ 11 lambda进行比较。如果你没有C ++ 11,那么很容易创建一个仿函数类。

至于删除最大轮廓,可以使用标准库中的另一个函数max_element(再次使用lambda进行比较):

boundRect.erase(std::max_element(boundRect.begin(), boundRect.end(),
                                 [] (cv::Rect left, cv::Rect right)
                                 {
                                     return left.area() < right.area();
                                 }));