Ask Your Question
3

Per pixel labeling in distanceTransform?

asked 2013-01-15 13:09:53 -0600

Lucas Walter gravatar image

updated 2013-01-15 13:11:00 -0600

It would be really convenient if this function worked like

  cv::distanceTransform(mask, dist, labels, distance_type, 3, DIST_LABEL_PIXEL);

and then within a double for loop on y and x

  const int label = labels.at<int>(y,x);
  const int label_x = label % width;
  const int label_y = label / width;

But instead the label is dependent on the non-zero pixels in the mask input (the label only increments when pixels are zero), so I have to manually build up a mapping between labels and pixel coordinates to find out where the labeled pixels actually are- or is there an easier way?

I'd take this to the dev zone but code.opencv.org appears to be down.

In my somewhat old git version of opencv disttransform.cpp:

   else    // it would be nice if DIST_LABEL_PIXEL was here for clarity
   {
   int k = 1;
   for( int i = 0;  i < src->rows; i++ )
   {
      const uchar* srcptr = src->data.ptr + src->step*i;
      int* labelptr = (int*)(labels->data.ptr + labels->step*i);

      for( int j = 0; j < src->cols; j++ )
        // it would be nice to get rid of 
        // this conditional and 
        // always increment labelptr, but then 
        // would the icvDistanceTransformEx_5x5_C1R
        // be messed up?
         if( srcptr[j] == 0 ) 
            labelptr[j] = k++;
      }
  }

  icvDistanceTransformEx_5x5_C1R( src->data.ptr, src->step, temp->data.i, temp->step,
                    dst->data.fl, dst->step, labels->data.i, labels->step, size, _mask );
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
3

answered 2014-10-28 09:59:25 -0600

drtaglia gravatar image

I COMPLETELY agree. Especially as the function doesn't even expose the mapping from the indexes it generates to the pixel coordinates in the source image. The function as it is right now, it's useful for little more than just computing a voronoi (where you don't really care about who was the seed as much as that to identify its watershed).

And now it's 2014 and the opencv website is still down... lol

Anyhow, this will invert your mapping if cannot edit the source

std::vector<cv::Vec2i> label_to_index;
label_to_index.push_back(-1);
    for (int row = 0; row < background.rows; ++row)
        for (int col = 0; col < background.cols; ++col)
            if(background.at<uchar>(row,col)==0)
                label_to_index.push_back(cv::Vec2i(row,col));
edit flag offensive delete link more

Comments

Thanks, nice code, you could maybe just add that it only works with DIST_LABEL_PIXEL activated.

silgon gravatar imagesilgon ( 2016-10-25 04:57:37 -0600 )edit

One little, but vital detail: since the labels are returned as a matrix of 32b ints, you need to do background.at<int>(row,col)==0!

BIOS the Zerg gravatar imageBIOS the Zerg ( 2016-11-22 10:35:31 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2013-01-15 13:09:53 -0600

Seen: 1,981 times

Last updated: Oct 28 '14