OpenCV:创建线条骨架的问题

信息处理 计算机视觉 opencv 形态操作 形态学
2022-02-14 08:19:26

我需要从一张纸的照片中得到线条。在重新思考时,我遇到了这个,其中一个答案提到了这个博客条目
现在我在使用这种方法时遇到了麻烦。我已按如下方式实现它(使用 OpenCV 的 c++ 接口:

// the image has to be grayscale
if (image.channels() != 1)
{
    cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
}

// we need to enhance the lighting before we can threshold the photography
cv::equalizeHist(image, image);
// a binary image is needed
cv::threshold(image, image, threshold, 255, cv::THRESH_BINARY);
cv::imwrite("thresholdedImage.jpg", image);

// the resulting skeleton
cv::Mat skeleton(image.size(), CV_8UC1, cv::Scalar(0,0,0));
// needed if in-place processing is not possible
cv::Mat temp(image.size(), CV_8UC1);
// eroded image is saved here
cv::Mat eroded;
// needed for morphological transforms (erodation, dilation)
cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3,3));

bool done = true;
int i = 0;
while(done)
{
    // eroding + dilating = opening
    cv::erode(image, eroded, element);
    cv::dilate(eroded, temp, element);
    cv::subtract(image, temp, temp);
    cv::bitwise_or(skeleton, temp, skeleton);
    eroded.copyTo(image);

    done = (cv::countNonZero(image) == 0);
    ++i;
}

为了概念验证,我决定使用计算机制作的绘图进行测试,以消除早期阶段的照明问题。这可以在这里看到: 使用 GIMP 创建 阈值是正确的,但不幸的是骨架看起来很奇怪: 在此处输入图像描述 我已经绘制了 100 次迭代后的骨架,它看起来像这样: 在此处输入图像描述
你有什么建议吗?

2个回答

您实际上是在绘制背景(较亮区域)的骨架。

改变

cv::threshold(image, image, threshold, 255, cv::THRESH_BINARY);

在你的代码中

cv::threshold(image, image, threshold, 255, cv::THRESH_BINARY_INV); 

你应该能够得到正确的骨架。

您可以在这里参考一些不同的实现,它们提供了可接受的结果。