首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用于边缘贴图(不是轮廓)的OpenCV - approxPolyDP

用于边缘贴图(不是轮廓)的OpenCV - approxPolyDP
EN

Stack Overflow用户
提问于 2014-03-03 03:46:31
回答 1查看 18.2K关注 0票数 15

我已经成功地在轮廓上应用了方法cv::approxPolyDP (cv::findContours.),以便用更简单的多边形表示轮廓,并隐式地进行一些去噪。

我想在从RGBD相机获取的边缘贴图上做同样的事情(通常非常嘈杂),但到目前为止没有太多成功,我在网上找不到相关的例子。我需要这个的原因是,通过边缘映射,人们还可以使用手指之间的边缘,通过手指遮挡创建的边缘或在手掌中创建的边缘。

这种方法是否适用于一般的边缘贴图,而不是轮廓?

谁能给我举个例子?

附件中的一些图片:

轮廓的成功示例:

边缘贴图的有问题的情况:

很可能我以错误的方式绘制东西,但仅绘制该方法返回的像素显示,最终结果中可能没有表示较大的区域(根据epsilon-参数,这不会有太大变化)。

我还附上了一个深度图像,类似于我在上面描述的实验管道中使用的图像。该深度图像不是由深度相机获取的,而是通过使用OpenGL读取图形处理器的深度缓冲区来合成的。

仅供参考,这也是直接从深度相机获取的深度图像的边缘图(使用原始图像,未应用平滑等)

(从深度相机拍摄的手,手掌朝上,手指朝手掌“合拢”)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-03 10:14:49

您的approxPolyDP问题是由于输入到approxPolyDP中的格式造成的。

解释

approxPolyDP期望其输入是Point的向量。这些点定义将由approxPolyDP处理的多边形曲线。曲线可以是开放的,也可以是闭合的,这可以通过一个标志来控制。

列表中点的顺序很重要。就像手工绘制多边形一样,矢量中的每个后续点都必须是多边形的下一个顶点,无论是顺时针还是逆时针。

如果点列表按光栅顺序存储(先按Y排序,然后按X排序),则point[k]point[k+1]不一定属于同一曲线。这就是问题的原因。

OpenCV - How to extract edges form result of Canny Function?中用插图解释了这个问题。引用Mikhail的话:"Canny不会将像素连接到链或段中。“

Canny生成的“栅格顺序”的图示。

approxPolyDP所期望的“轮廓顺序”的图示

需要什么

你需要的是一个“边缘像素链”的列表。每个链必须包含彼此相邻的边缘像素,就像有人用铅笔画出物体的轮廓一样,铅笔尖不会离开纸。

这不是边缘检测方法(如Canny )返回的结果。需要进一步的处理来将边缘映射转换为相邻(连续)边缘像素链。

建议的解决方案

(1)使用二进制threshold findContours而不是边缘检测作为的输入

如果存在将手与背景分开的阈值,并且该值适用于整个手(而不仅仅是手的一部分),则可以使用此选项。

(2)扫描边缘映射,并通过检查每个边缘像素的邻居来构建相邻像素列表。

这类似于connected-components算法,不同之处在于不是查找blob (只需要知道每个像素的成员身份),而是尝试查找像素链,这样您就可以分辨出链上的前一个和下一个边缘像素。

(3)使用另一种边缘检测算法,例如边缘绘制。

详情请访问:http://ceng.anadolu.edu.tr/cv/EdgeDrawing/

不幸的是,这不是OpenCV提供的开箱即用的功能,因此您可能必须在其他地方找到实现。

选项#1的示例代码。

代码语言:javascript
运行
复制
#include <stdint.h>
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat matInput = imread("~/Data/mA9EE.png", false);

    // ---- Preprocessing of depth map. (Optional.) ----

    GaussianBlur(matInput, matInput, cv::Size(9, 9), 4.0);

    // ---- Here, we use cv::threshold instead of cv::Canny as explained above ----

    Mat matEdge;

    //Canny(matInput, matEdge, 0.1, 1.0);

    threshold(matInput, matEdge, 192.0, 255.0, THRESH_BINARY_INV);

    // ---- Use findContours to find chains of consecutive edge pixels ----

    vector<vector<Point> > contours;
    findContours(matEdge, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

    // ---- Code below is only used for visualizing the result. ----

    Mat matContour(matEdge.size(), CV_8UC1);

    for (size_t k = 0; k < contours.size(); ++k)
    {
        const vector<Point>& contour = contours[k];
        for (size_t k2 = 0; k2 < contour.size(); ++k2)
        {
            const Point& p = contour[k2];
            matContour.at<uint8_t>(p) = 255;
        }
    }

    imwrite("~/Data/output.png", matContour);
    cout << "Done!" << endl;
    return 0;
}
票数 36
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22132510

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档