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