我从这个问题的投票最多的作者的回答中挑选了一个代码段:
https://answers.opencv.org/question/9863/fill-holes-of-a-binary-image/
将其重新格式化为:
cv::Mat image = cv::imread("image.jpg", 0);
cv::Mat image_thresh;
cv::threshold(image, image_thresh, 125, 255, cv::THRESH_BINARY);
// Loop through the border pixels and if they're black, floodFill from there
cv::Mat mask;
image_thresh.copyTo(mask);
for (int i = 0; i < mask.cols; i++) {
if (mask.at<char>(0, i) == 0) {
cv::floodFill(mask, cv::Point(i, 0), 255, 0, 10, 10);
}
if (mask.at<char>(mask.rows-1, i) == 0) {
cv::floodFill(mask, cv::Point(i, mask.rows-1), 255, 0, 10, 10);
}
}
for (int i = 0; i < mask.rows; i++) {
if (mask.at<char>(i, 0) == 0) {
cv::floodFill(mask, cv::Point(0, i), 255, 0, 10, 10);
}
if (mask.at<char>(i, mask.cols-1) == 0) {
cv::floodFill(mask, cv::Point(mask.cols-1, i), 255, 0, 10, 10);
}
}
// Compare mask with original.
cv::Mat newImage;
image.copyTo(newImage);
for (int row = 0; row < mask.rows; ++row) {
for (int col = 0; col < mask.cols; ++col) {
if (mask.at<char>(row, col) == 0) {
newImage.at<char>(row, col) = 255;
}
}
}
cv::imshow("filled image", mask);
cv::imshow("Final image", newImage);
cv::imwrite("final.jpg", newImage);
cv::waitKey(0);
return 0;
我知道它使用洪水填充算法来尝试填充孔,并且我已经在另一个示例图像上进行了测试:
通过检测所有 9 个孔,它的效果非常好。
但是,我尝试了另一个稍微复杂的图像:
这一次它不起作用,它将用白色填充整个图形,它检测到的孔数为 1700。
我想我可能在这里缺乏大量的形态学知识,但我认为也许我应该先对失败的图像进行“缩小”,然后再将其插入作者的代码中?
专家能否与我分享一些想法,因为我在谷歌上找不到非常相似的孔检测图表。那么当两个孔与二进制图像中的白色路径连接时,孔有什么特别之处?提前谢谢!