gpt4 book ai didi

c++ - 如何在二元图中识别由线连接的孔

转载 作者:行者123 更新时间:2023-12-01 14:05:26 27 4
gpt4 key购买 nike

我从这个问题的最高投票作者的回答中挑选了一个代码段:

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;

我知道它使用了洪水填充算法来尝试填充孔洞,并且我已经在另一个示例图像上进行了测试:

enter image description here

通过检测所有 9 个孔,它的效果非常好。

但是,我尝试了另一个稍微复杂的图像:

enter image description here

这次不行了,会用白色填满整个图,检测到的洞数是1700个。

我想我在这里可能缺乏形态学知识的重要部分,但我想也许我应该先对失败的图像进行“缩小”,然后再将其插入作者的代码中?

专家们能否与我分享一些想法,因为我在谷歌上找不到非常相似的孔检测图。那么当两个孔与二值图像中的白色路径连接时,孔有什么特别之处?提前致谢!

最佳答案

您的图像有问题,它在图像的 3 个边周围有一条细长的白条。该条还连接到左侧的 4 个白色矩形,这会创建一个额外的封闭轮廓/水平,我猜会混淆“填充”。

我个人不喜欢使用“floodfill”方法来解决在轮廓内找到洞的问题。我更喜欢使用带有 'hierarchy' 选项的 'findcontour' 方法。请看一下here .乍一看,它可能看起来有点复杂,但它提供了我们需要的所有信息。

您正在寻找的孔有两个属性:

  • 它们是子轮廓(一个洞)
  • 它们内部没有其他轮廓(不是父对象)

  • 查找这些漏洞的代码是:
    auto image = cv::imread(in_img_path, cv::ImreadModes::IMREAD_GRAYSCALE);
    cv::threshold(image, image, 128, 255, cv::THRESH_OTSU);
    std::vector<std::vector<cv::Point>> contours, selected_contours;
    std::vector<cv::Vec4i> hierarchy;
    cv::findContours(image, contours, hierarchy, cv::RetrievalModes::RETR_TREE, cv::ContourApproximationModes::CHAIN_APPROX_SIMPLE);
    for (int i = 0; i < contours.size(); i++) {
    if (hierarchy[i][2] == -1 && hierarchy[i][3] != -1) //the contour has no children but has a parent
    selected_contours.emplace_back(std::move(contours[i]));
    }
    cv::Mat drawing_image(image.size(), image.type(), cv::Scalar::all(0));

    for (int i = 0; i < selected_contours.size(); i++) {
    cv::drawContours(drawing_image, selected_contours, i, cv::Scalar(255), 1);
    }

    编辑:
    我试过了,在这种情况下,似乎第一次检查是多余的。以下条件是充分的:
    if (hierarchy[i][3] != -1) // the contour has a parent

    孔数(selected_contours的大小)为:71

    'drawing_image' 将如下所示:
    Image showing found holes

    关于c++ - 如何在二元图中识别由线连接的孔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60463603/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com