骨架的分支点

Branch points of the skeleton

我的代码应该找到骨架的分支点,但它找到的点不是它们。这很可能是因为 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

您应该对代码执行以下操作:

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

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

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

  4. 去掉对p1的第二个赋值,没有效果