我正在使用OpenCV进行一些检测工作,我需要使用距离变换。除了opencv中的距离变换功能,我给出的图像与我用作源的图像完全相同。谁知道我做错了什么?这是我的代码部分:
cvSetData(depthImage, m_rgbWk, depthImage->widthStep);
//gotten openCV image in "depthImage"
IplImage *single_channel_depthImage = cvCreateImage(cvSize(320, 240), 8, 1);
cvSplit(depthImage, single_channel_depthImage, NULL, NULL, NULL);
//smoothing
IplImage *smoothed_image = cvCreateImage(cvSize(320, 240), 8, 1);
cvSmooth(single_channel_depthImage, smoothed_image, CV_MEDIAN, 9, 9, 0, 0);
//do canny edge detector
IplImage *edges_image = cvCreateImage(cvSize(320, 240), 8, 1);
cvCanny(smoothed_image, edges_image, 100, 200);
//invert values
IplImage *inverted_edges_image = cvCreateImage(cvSize(320, 240), 8, 1);
cvNot(edges_image, inverted_edges_image);
//calculate the distance transform
IplImage *distance_image = cvCreateImage(cvSize(320, 240), IPL_DEPTH_32F, 1);
cvZero(distance_image);
cvDistTransform(inverted_edges_image, distance_image, CV_DIST_L2, CV_DIST_MASK_PRECISE, NULL, NULL);
简而言之,我从kinect渲染图像,将其转换为单通道图像,平滑它,运行canny边缘检测器,反转值,然后进行距离变换。但是,变换后的图像看起来与输入图像完全相同。怎么了?
谢谢!
答案 0 :(得分:23)
我相信这里的关键是他们看起来一样。这是我编写的一个小程序来显示差异:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat before = imread("qrcode.png", 0);
Mat dist;
distanceTransform(before, dist, CV_DIST_L2, 3);
imshow("before", before);
imshow("non-normalized", dist);
normalize(dist, dist, 0.0, 1.0, NORM_MINMAX);
imshow("normalized", dist);
waitKey();
return 0;
}
在非标准化图像中,您会看到:
它看起来并没有真正改变任何东西,但距离步长与整个值范围[0,255]相比非常小(由于imshow
转换图像来自32位浮动到8位显示),我们无法看到差异,所以让它标准化......
现在我们得到这个:
值本身应该是正确的,但在显示时,您需要对图像进行标准化以查看差异。
编辑:
这是来自dist
矩阵左上角的一个小的10x10样本,显示这些值实际上是不同的:
[10.954346, 10.540054, 10.125763, 9.7114716, 9.2971802, 8.8828888, 8.4685974, 8.054306, 7.6400146, 7.6400146;
10.540054, 9.5850525, 9.1707611, 8.7564697, 8.3421783, 7.927887, 7.5135956, 7.0993042, 6.6850128, 6.6850128;
10.125763, 9.1707611, 8.2157593, 7.8014679, 7.3871765, 6.9728851, 6.5585938, 6.1443024, 5.730011, 5.730011;
9.7114716, 8.7564697, 7.8014679, 6.8464661, 6.4321747, 6.0178833, 5.6035919, 5.1893005, 4.7750092, 4.7750092;
9.2971802, 8.3421783, 7.3871765, 6.4321747, 5.4771729, 5.0628815, 4.6485901, 4.2342987, 3.8200073, 3.8200073;
8.8828888, 7.927887, 6.9728851, 6.0178833, 5.0628815, 4.1078796, 3.6935883, 3.2792969, 2.8650055, 2.8650055;
8.4685974, 7.5135956, 6.5585938, 5.6035919, 4.6485901, 3.6935883, 2.7385864, 2.324295, 1.9100037, 1.9100037;
8.054306, 7.0993042, 6.1443024, 5.1893005, 4.2342987, 3.2792969, 2.324295, 1.3692932, 0.95500183, 0.95500183;
7.6400146, 6.6850128, 5.730011, 4.7750092, 3.8200073, 2.8650055, 1.9100037, 0.95500183, 0, 0;
7.6400146, 6.6850128, 5.730011, 4.7750092, 3.8200073, 2.8650055, 1.9100037, 0.95500183, 0, 0]
答案 1 :(得分:3)
我只想出这个。
OpenCV distanceTransform
计算每个像素的最近零像素的距离 源图像。
所以它希望你的边缘图像是负面的。
您需要做的就是否定您的边缘图像:
edges = 255 - edges;
答案 2 :(得分:1)
您可以在规范化功能之前使用此代码打印此值:
for(int x=0; x<10;x++)
{
cout<<endl;
for(int y=0; y<10;y++)
cout<<std::setw(10)<<dist.at<float>(x, y);
}
答案 3 :(得分:0)
normalize(Mat_dist, Mat_norm, 0, 255, NORM_MINMAX, CV_8U);
如果要可视化结果,则需要将归一化比例缩放到0 ... 255,而不是0 ... 1,否则所有内容看起来都将变成黑色。在缩放到0 ... 1的图像上使用imshow();
可以工作,但可能在接下来的处理步骤中出现问题。就我而言至少如此。