/ / Usuń prostokąt obwiedni z obszarem <n OpenCV - c ++, opencv, obwiednia

Usuń prostokąt ograniczający z obszarem <n OpenCV - c ++, opencv, obwiednia

Wygładzam obraz z blokami tekstowymi, a następnie używam findContours() znaleźć wszystkie bloki tekstowe, a następnie rysowaćich ograniczający prostokąt. Czasami jednak na obrazie pojawiają się bardzo małe rektyki powstałe w wyniku szumu, które znajdują się w większym lub w miejscu, w którym nie ma tekstu.

Używam tego kodu, aby znaleźć kontury i je narysować.

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 );
}

Po przykładowym uruchomieniu tutaj otrzymuję:

wprowadź opis obrazu tutaj

Jak mogę zmodyfikować swój kod, aby móc usunąć wszelkie poprawki, które nie są większe niż n więc mogę zachować tylko pełne bloki tekstowe, muszę też usunąć największy kontur otaczający całą kartę.

Odpowiedzi:

2 dla odpowiedzi № 1

Dla bezpieczniejszej metody usuwania cv::Rect elementy z twojego vector, możesz użyć usuń-usuń idiom aby usunąć elementy poniżej pewnego progu powierzchni. Ta metoda to dużo bezpieczniejsze niż usuwanie elementów jeden po drugim według ich indeksu, jak w odpowiedzi Harisa, ponieważ nie ryzykujesz ucieczki z końca wektora.

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

Tutaj używam do porównania lambda C ++ 11. Jeśli nie masz C ++ 11, łatwo jest zamiast tego utworzyć klasę funktorów.

Jeśli chodzi o usunięcie największego konturu, możesz użyć innej funkcji ze standardowej biblioteki, max_element (Ponownie używając do porównania lambda):

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

3 dla odpowiedzi № 2

Yo przydałby się contourArea Aby wyeliminować kontur, użyj poniższego kodu przed znalezieniem prostokąta ograniczającego, spowoduje to usunięcie całego konturu o powierzchni mniejszej niż próg.

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);
}

Edytować:-

Każdy, kto zamierza użyć powyższego kodu, zapoznaj się z komentarzem poniżej.