我正在使用文本块侵蚀图像,然后使用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 );
}
在这里运行样品后,我得到了回复:
如何修改我的代码,以便我可以删除任何不大于n
的rect,这样我只能保留完整的文本块,我还需要删除围绕整个卡片的最大轮廓。< / p>
答案 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();
}));