Mina Almasry
Mina Almasry

Reputation: 173

OpenCV distance transform outputting an image that looks exactly like the input image

I am doing some detection work using OpenCV, and I need to use the distance transform. Except the distance transform function in opencv gives me an image that is exactly the same as the image I use as source. Anyone know what I am doing wrong? Here is the portion of my code:

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);

In a nutshell, I grad the image from the kinect, turn it into a one channel image, smooth it, run the canny edge detector, invert the values, and then I do the distance transform. But the transformed image looks exactly the same as the input image. What's wrong?

Thanks!

Upvotes: 11

Views: 18197

Answers (4)

Kemendil
Kemendil

Reputation: 131

Mat formats

  • Input: CV_8U
  • Dist: CV_32F
  • Normalized: CV_8U

normalize(Mat_dist, Mat_norm, 0, 255, NORM_MINMAX, CV_8U);

If you want to visualize the result, you need to scale the normalization to 0 ... 255 and not to 0 ... 1 or everything will seem black. Using imshow(); on a scaled to 0 ... 1 image will work but may cause problmes in the next processing steps. Al least it did in my case.

Upvotes: 1

OfriM
OfriM

Reputation: 121

I just figured this one out. The OpenCV distanceTransform

Calculates the distance to the closest zero pixel for each pixel of the source image.

and so it expects your edges image to be negative.

All you need to do is to negate your edges image:

edges = 255 - edges;

Upvotes: 4

Anton
Anton

Reputation: 11

You can print this values using this code before normalize function:

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);
  }

Upvotes: 1

mevatron
mevatron

Reputation: 14021

I believe the key here is that they look the same. Here is a small program I wrote to show the difference:

#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;
}

In the non-normalized image, you see this:
enter image description here

which doesn't really look like it changed anything, but the distance steps are very small compared to the overall range of values [0, 255] (due to imshow converting the image from 32-bit float to 8-bits for display), we can't see the differences, so let's normalize it...

Now we get this:
enter image description here

The values themselves should be correct, but when displayed you will need to normalize the image to see the difference.

EDIT : Here is a small 10x10 sample from the upper-left corner of the dist matrix show that the values are in fact different:

[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]

Upvotes: 27

Related Questions