在 C++ 中计算图像骨架的最快方法

Posted

技术标签:

【中文标题】在 C++ 中计算图像骨架的最快方法【英文标题】:Fastest way to calculate skeleton of image in C++ 【发布时间】:2018-04-23 14:57:06 【问题描述】:

我正在使用 OpenCV (C++) 并希望以最快的方式找到图像的骨架。

输入图像hand_bw为:

到目前为止,这就是我所拥有的:

cv::Mat skel(hand_bw.size(), CV_8UC1, cv::Scalar(0));
cv::Mat temp(hand_bw.size(), CV_8UC1);
cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
bool done; 
int i = 0;
do

    cv::morphologyEx(hand_bw, temp, cv::MORPH_OPEN, element);
    cv::bitwise_not(temp, temp);
    cv::bitwise_and(hand_bw, temp, temp);
    cv::bitwise_or(skel, temp, skel);
    cv::erode(hand_bw, hand_bw, element);
    double max;
    cv::minMaxLoc(hand_bw, 0, &max);
    done = (max == 0);
    i = i+1;
 while (!done);
cv::imshow("Skeleton", skel); 

对应的输出是:

在 C++(可能是动态编程)中实现此结果的最快方法是什么?时间是我的主要限制。

【问题讨论】:

我从来没有遇到过不能更快的 C++ 程序。所以“是”。一般来说? “让它去”是一个糟糕的 SO 问题。 我不确定您如何使用它,但我几乎 100% 确定还有另一种 OpenCV 方法可以执行该操作。无论如何,您是否尝试过重构该代码以使用 OpenCV 的透明 API? 你能发布输出帧吗? 这是一个研究问题。有关于此的论文,尽管通常是针对 3D 场景的。研究“快速近似凸分解” @Meghana OpenCV 的透明 API 是一个非常易于使用的 API,它使昂贵的操作(如您的)能够使用硬件(如 GPU)使其更快。这是一个简单的教程:learnopencv.com/opencv-transparent-api 【参考方案1】:

您可以通过侵蚀连续层并记住“边缘”(即在上一次迭代中被擦除的像素)来获得有效的解决方案。因此,不是每次都处理整个图像,而是处理一个小得多的子集,使算法运行的时间与图像区域准成比例。

当执行腐蚀通道时,您保留像素以便擦除它们会修改局部连通性。

【讨论】:

您能否详细说明存储“边缘”的信息有什么帮助?被腐蚀的部分不存在了,下一次腐蚀必须在整个对象上再次处理,对吧? @Meghana:在任何过程中,只需要处理具有异质邻域的白色像素。因此,您保留这些列表并在每次删除时更新列表。

以上是关于在 C++ 中计算图像骨架的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

图像的骨架提取

如何使用 python 库在骨架图像中找到循环?

python数字图像处理(19):骨架提取与分水岭算法

Opencv 膨胀和骨架(c++)

OpenPose 基于骨架模型的动作识别

饿了么开源的骨架屏插件原理分析