Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pixel-indexing in OpenCV's distance transform

I want to use the function distanceTransform() to find the minimum distance of non-zero pixels to zeros pixels, but also the position of that closest zero pixel. I call the second version of the function with the labelType flag set to DIST_LABEL_PIXEL. Everything works fine and I get the distances to and indices of the closest zero pixels.

Now I want to convert the indices back to pixel locations and I thought the indexing would be like idx=(row*cols+col) or something like this but I had to find out that OpenCV is just counting the zero pixels and using this count as the index. So if I get 123 as the index of the closest pixel this means that the 123th zero pixel is the closest.

  1. How is OpenCV counting them? Probably in a row-wise manner?

  2. Is there an efficient way of mapping the indices back to the locations? Obviously I could recount them and keep track of the counts and positions, if I know how OpenCV counts them, but this seems stupid and not very efficient.

  3. Is there a good reason to use the indexing they used? I mean, are there any advantages over using an absolute indexing?

Thanks in advance.

EDIT:

If you want to see what I mean, you can run this:

Mat mask = Mat::ones(100, 100, CV_8U);
mask.at<uchar>(50, 50) = 0;

Mat dist, labels;
distanceTransform(mask, dist, labels, CV_DIST_L2, CV_DIST_MASK_PRECISE, DIST_LABEL_PIXEL);

cout << labels.at<int>(0,0) << endl;

You will see that all the labels are 1 because there is only one zero pixel, but how am I supposed to find the location (50,50) with that information?

like image 360
thomas Avatar asked Oct 17 '14 09:10

thomas


2 Answers

The zero pixels also get labelled - they will have the same label as the non-zero pixels to which they are closest.

So you will have a 2D array of labels, the same size as your source image. If you examine all of the zero pixels in the source image, you can then find the associated label from the 2D array returned. This can then allow you to find which non-zero pixels are associated with each zero pixel by matching the labels.

If you see what I mean.

like image 133
Roger Rowland Avatar answered Nov 08 '22 18:11

Roger Rowland


In python you can use numpy to associate the labels and the coordinates:

import cv2
import numpy as np

# create an image with two 0-lines
a = np.ones((100,100), dtype=np.uint8)
a[50,:] = 0
a[:,70] = 0

dt,lbl = cv2.distanceTransformWithLabels(a, cv2.DIST_L2, 3, labelType=cv2.DIST_LABEL_PIXEL)

# coordinates of 0-value pixels
xy = np.where(a==0)

# print label id and coordinate
for i in range(len(np.unique(lbl))):
    print(i,xy[0][i], xy[1][i])
like image 23
Christian Rauch Avatar answered Nov 08 '22 19:11

Christian Rauch