Question:
In opencv using findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, Point(0, 0));
I find the contours.
So, the letter О
two contours, and the inner contour is painted over.
How can I eliminate outer contours from closed shapes while maintaining the shape's dimensions?
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
Mat threshold_output = getBinaryImage(src_gray);
findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, Point(0, 0));
vector<vector<Point> > contours_poly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Point2f>center(contours.size());
vector<float>radius(contours.size());
cout << "contours.size()" << contours.size();
for (size_t i = 1; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), contours_poly[i], 1, true);
boundRect[i] = boundingRect(Mat(contours_poly[i]));
}
Mat drawing(threshold_output.size(), CV_8UC3, Scalar(255, 255, 255));
If you use CV_RETR_EXTERNAL
, then the outermost contour, which is along the border of the picture, will be the first and last. If you do not paint over the contours, then the letter о
between the two contours is empty. Well, or find one general outline, except for the outline of the picture.
Answer:
Judging by
If you use CV_RETR_EXTERNAL, then the outermost contour, which is along the border of the picture, will be the first and last.
… it turns out that the background in the original image is not black. It is not right. The findContours()
function (like many others in OpenCV) is hardcore based on the fact that the background in the binary image should be completely black (value equal to 0
), and the object or objects should be a different color (any value from 1
up to 255
inclusive). Usually a pair is used: 0
and 255
.
In order to invert the matrix, for example, to make a black letter "o" on a white background into a white letter on a black background, you can apply a simple operation:
// Исходное изображение: чёрная буква на белом фоне.
cv::Mat src_mat = ...;
// А здесь получится белая буква на чёрном фоне,
// т.е. то, что надо для использования в findContours().
cv::Mat inv_mat = ~src_mat;
The binary image in OpenCV is mostly a convention, since the unsigned char
type is used anyway. In fact, this is a grayscale image, and what the real value of the pixels is – 0-1
, 0-255
or whatever – is left to the mercy of the programmer. Therefore, after loading a picture from a file, it makes sense to binarize it forcibly, since it is often difficult to guarantee "by eye" that the image contains the required values, and instead of 0
, a separate pixel does not contain, say, the value 1
.
For binarization in OpenCV, you can use the threshold()
function. It has many parameters, described in detail (including with pictures) in the documentation, so there is probably no point in dwelling on it in detail. I will only note that my previous example with inverting matrix values can also be implemented using the designated function, plus, in fact, binarization. Two birds with one stone, so to speak.