【问题标题】:Branch points of the skeleton骨架的分支点
【发布时间】:2021-01-04 08:58:52
【问题描述】:

我的代码应该找到骨架的分支点,但它找到的点不是它们。这很可能是因为IMREAD_COLOR = 1,而不是 0。但如果我将值设置为 0,那么它将完全停止查找和标记点。是因为点的类型 (p1, p2, etc) 不匹配 Mattype 还是其他什么?我该如何解决这个问题?

int main() {
    cv::Mat thresh = cv::imread("binary_skeleton.jpg", 1);
    if (thresh.empty())
        return -1;

    for (int i = 1; i < thresh.rows - 1; i++)
    {
        for (int j = 1; j < thresh.cols - 1; j++)
        {
            uchar p1 = thresh.at<uchar>(i, j);
            if (0 == p1)
            {
                uchar p1 = thresh.at<uchar>(i, j);
                uchar p2 = thresh.at<uchar>(i - 1, j);
                uchar p3 = thresh.at<uchar>(i - 1, j + 1);
                uchar p4 = thresh.at<uchar>(i, j + 1);
                uchar p5 = thresh.at<uchar>(i + 1, j + 1);
                uchar p6 = thresh.at<uchar>(i + 1, j);
                uchar p7 = thresh.at<uchar>(i + 1, j - 1);
                uchar p8 = thresh.at<uchar>(i, j - 1);
                uchar p9 = thresh.at<uchar>(i - 1, j - 1);

                int same = 0;
                if (p9 == p1) { ++same; }
                if (p8 == p1) { ++same; }
                if (p7 == p1) { ++same; }
                if (p6 == p1) { ++same; }
                if (p5 == p1) { ++same; }
                if (p4 == p1) { ++same; }
                if (p3 == p1) { ++same; }
                if (p2 == p1) { ++same; }

                if (same == 2)
                {
                    circle(thresh, Point(j, i), 3, Scalar(255, 120, 0), 1);
                }
            }
        }
    }
    cv::imshow("", thresh);
    cv::waitKey(0);
}

Incorrect image

【问题讨论】:

    标签: c++ opencv image-processing mat


    【解决方案1】:

    你应该对你的代码做一些事情:

    1. 使用cv::imread("binary_skeleton.jpg", cv::IMREAD_GRAYSCALE) 读取图像。您使用的选项强制图像为 RGB,但您使用的图像好像只有一个通道。

    2. 不要比较 if (0 == p1) 来查找设置的像素,而是使用 if (128 &gt; p1)。 JPEG 压缩可以改变像素的值,因此图像不会只有 0 和 255 的值,即使这些值是写入文件的值。这些值会存在一些变化。我们只是简单地设置一半阈值,以确保任何低值都被视为骨架像素。同样,将if (p9 == p1) 替换为if (128 &gt; p9)

    3. 分支点总是有两个以上的邻居集。当设置两个邻居时,它是一条线上的一个点。而不是if (same == 2) 使用if (same &gt; 2)

    4. 把第二个赋值给p1去掉,没有效果。

    【讨论】:

    • 如果我完全按照你写的那样做(除了我们在另一个方向改变符号,因为我们对黑色像素感兴趣),那么我会得到一个奇怪的结果。 p1 &lt; 128 and p9 &lt; 128 etc;如果我改成p1 &gt; 128 and p9 &lt; 128 etc,那么我在骨架上会得到很多标记,但这些仍然不是分支点。
    • @avenueroan:如果您的骨架是白色背景上的黑色像素,那么您需要反转所有比较,而不仅仅是 p1 的比较。但是,如果您的骨架有黑色像素,为什么您在问题中的代码会执行p1==255? // 查看您的结果,以及问题中链接的图像,您可能没有合适的骨架。你如何计算骨架?
    • 我已经颠倒了所有的比较,是的。 // 不好意思,没看到忘记改p1 == 255(changed)。 // 是的,我也想过骨架可能是错误的。我使用了阈值 => this 用 C# 编写的代码 => 保存了图像 => 上传到这里。 // 事实上,我唯一能想到的是骨架是错误的,因为我们可以将cv::threshold(thresh, thresh, 0, 255, cv ::THRESH_BINARY) 应用于我们的代码以使像素为 0 或 255,但这仍然没有帮助。
    • @avenueroan:您在此处链接的答案显示的结果图像不是正确的骨架。有些点与沿线的相邻点是 8 连通的,有些是 4 连通的(也就是说,我们可以在不破坏 8 连通线的情况下移除一些像素)。这些额外的像素和它们的邻居看起来像分支点。我还没有查看代码以了解它为什么不正确。为什么不使用标准的图像处理库?有许多经过良好测试的库具有正确的骨架算法。
    • 我在图像处理方面有相当多的经验,所以在所有库中我只能找到带有 Skeletonize 方法的 scikit,但它只在 Python 中,我需要一个 C++/C # 解决方案。 @CrisLuengo
    猜你喜欢
    • 1970-01-01
    • 2017-08-19
    • 2015-10-30
    • 2012-08-27
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    相关资源
    最近更新 更多