I am looking for an algorithm that can do external and internal contour detection on an ideal image containing only two different RGB values.
Below is a typical example of the image (first one) I want to process, next image is one I made myself showing the result I am expecting.
The last one is a result from OpenCV Canny detection made through the demo software available at OpenCV demo Software.
The canny algorithm is not satisfying as it is smoothing too much the shapes (especially corner).
Are there any elegant algorithm that could give the same results as in the second image?
Contour extraction is the easiest thing to do this:
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/StackOverflow/Input/ContourExtraction.png");
cv::Mat mask;
// create a perfect mask: Easy if you know the 2 colors present in your image:
cv::inRange(input, cv::Scalar(100, 0, 0), cv::Scalar(255, 255, 255), mask);
cv::imshow("mask", mask);
std::vector<std::vector<cv::Point> > contours; // contour points
std::vector<cv::Vec4i> hierarchy; // this will give you the information whether it is an internal or external conotour.
// contour extraction: This will alter the input image, so if you need it later use mask.clone() instead
findContours(mask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, cv::Point(0, 0)); // use different CV_CHAIN_APPROX_ if you dont need ALL the points but only the ones that dont lie on a common line
// output images:
cv::Mat contoursExternal = input.clone();
cv::Mat contoursInternal = input.clone();
cv::Mat contoursAll = cv::Mat::zeros(input.size(), CV_8UC1);
// draw contours
for (unsigned int i = 0; i < contours.size(); ++i)
{
cv::drawContours(contoursAll, contours, i, cv::Scalar::all(255), 1);
if (hierarchy[i][3] != -1) cv::drawContours(contoursInternal, contours, i, cv::Scalar::all(255), 1);
else cv::drawContours(contoursExternal, contours, i, cv::Scalar::all(255), 1);
}
cv::imshow("internal", contoursInternal);
cv::imshow("external", contoursExternal);
cv::imshow("all", contoursAll);
cv::imshow("input", input);
cv::waitKey(0);
return 0;
}
giving these results:
External contours:
Internal contours:
result mask: