Удалите ограничивающий прямоугольник с областью & lt; n OpenCV

Я стираю изображение с текстовыми блоками на нем, затем с помощью 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 поэтому я могу сохранить только полные текстовые блоки, мне также нужно удалить самый большой контур, который окружает всю карту.

0

Решение

Для более безопасного метода удаления cv::Rect элементы из вашего vectorВы могли бы использовать стереть-удалить идиому удалить элементы, которые находятся ниже определенного порога области. Этот метод много безопаснее, чем удаление элементов один за другим по их индексу, как в ответе Хариса, так как вы не рискуете выйти за пределы вектора.

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 для сравнения. Если у вас нет C ++ 11, достаточно просто создать класс функтора.

Что касается удаления наибольшего контура, вы можете использовать другую функцию из стандартной библиотеки, max_element (Опять же для сравнения лямбда):

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

Другие решения

Йо мог бы использовать 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);
}

Редактировать:-

Для любого, кто собирается использовать вышеупомянутый код, пожалуйста, смотрите ниже комментарий.

3