dim*_*_tz 14 c++ opencv image-processing gesture-recognition
我已经成功地在轮廓(cv :: findContours)上应用了方法cv :: approxPolyDP,以便用更简单的多边形表示轮廓并隐式地做一些去噪.
我想在从RGBD相机(通常非常嘈杂)获取的边缘地图上做同样的事情,但到目前为止还没有太大的成功,我在网上找不到相关的例子.我需要这个的原因是,通过边缘图,人们还可以使用手指之间的边缘,手指遮挡产生的边缘或手掌中创建的边缘.
此方法是否适用于轮廓以外的一般边缘贴图?
有人能指出我的例子吗?
附上一些图片:
轮廓的成功示例:
边缘图的问题案例:
很可能我以错误的方式绘制东西,但只绘制方法返回的像素表明最终结果中可能没有表示大的区域(根据epsilon参数,这并没有太大变化).
我还附上了一张深度图像,类似于我在上面描述的实验管道中使用的图像.这个深度图像不是由深度相机获取的,而是通过使用OpenGL读取gpu的深度缓冲区来合成生成的.
仅供参考,这也是直接从深度相机获取的深度图像的边缘图(使用原始图像,不应用平滑等)
(从深度相机看到的手,手掌朝上,手指"朝向手掌"关闭)
rwo*_*ong 34
您的问题approxPolyDP
是由于输入格式化approxPolyDP
.
approxPolyDP
期望它的输入是Point
s 的向量.这些点定义了将由其处理的多边形曲线approxPolyDP
.曲线可以是打开或关闭的,可以通过标志来控制.
列表中点的排序很重要.就像用手追踪多边形一样,矢量中的每个后续点必须是多边形的下一个顶点,顺时针或逆时针.
如果点列表以光栅顺序存储(按Y然后X排序),那么point[k]
并且point[k+1]
不一定属于同一曲线.这是问题的原因.
这个问题用OpenCV中的插图解释- 如何从Canny函数的结果中提取边缘?.来自米哈伊尔的报价:"Canny不会将像素连接成链或段."
Canny
.approxPolyDP
你需要的是"边缘像素链"列表.每条链必须包含彼此相邻的边缘像素,就像有人用铅笔描绘出物体的轮廓一样,没有铅笔的尖端离开纸张.
这不是从边缘检测方法返回的内容,例如Canny
.需要进一步处理以将边缘图转换成相邻(连续)边缘像素的链.
(1)使用二进制threshold
代替边缘检测作为输入findContours
如果存在将手与背景分开的阈值,并且该值适用于整个手(不仅仅是手的一部分),则这将适用.
(2)扫描边缘图,并通过检查每个边缘像素的邻居来构建相邻像素的列表.
这类似于连通分量算法,除了找到一个blob(你只需要知道每个像素的成员资格),你试图找到像素链,这样你就可以告诉链上的前一个和下一个边缘像素.
(3)使用替代边缘检测算法,例如边缘绘图.
有关详细信息,请访问http://ceng.anadolu.edu.tr/cv/EdgeDrawing/
不幸的是,这不是OpenCV开箱即用的,因此您可能必须在其他地方找到实现.
#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;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
16783 次 |
最近记录: |