user1708997
user1708997

Reputation: 45

Finding furthest away pixel (Open CV)

I've been struggling with a small problem for some time now and just can't figure out what is wrong.

So I have a black 126 x 126 image with a 1 pixel blue border ( [B,G,R] = [255, 0, 0] ). What I want, is the pixel which is furthest away from all blue pixels (such as the border). I understand how this is done. Iterate through every pixel, if it is black then compute distance to every other pixel which is blue looking for the minimum, then select the black pixel with the largest minimum distance to any blue.

Note: I don't need to actually know the true distance, so when doing the sum of the squares for distance I don't square root, I only want to know which distance is larger (less expensive).

First thing I do is loop through every pixel and if it is blue, add the row and column to a vector. I can confirm this part works correctly. Next, I loop through all pixels again and compare every black pixel's distance to every pixel in the blue pixel vector.

Where blue is a vector of Blue objects (has row and column) region is the image

int distance;
int localShortest = 0;
int bestDist = 0;
int posX = 0;
int posY = 0;

for(int i = 0; i < image.rows; i++)
{
    for(int j = 0; j < image.cols; j++)
    {
        //Make sure pixel is black
        if(image.at<cv::Vec3b>(i,j)[0] == 0
            && image.at<cv::Vec3b>(i,j)[1] == 0 
            && image.at<cv::Vec3b>(i,j)[2] == 0)
        {
                for(int k = 0; k < blue.size(); k++)
                {
                    //Distance between pixels
                    distance = (i - blue.at(k).row)*(i - blue.at(k).row) + (j - blue.at(k).col)*(j - blue.at(k).col);

                    if(k == 0)
                    {
                        localShortest = distance;
                    }

                    if(distance < localShortest)
                    {
                        localShortest = distance;
                    }
                }

            if(localShortest > bestDist)
            {
                posX = i;
                posY = j;
                bestDistance = localShortest;

            }
       }
    }
}

This works absolutely fine for a 1 pixel border around the edge. https://dl.dropboxusercontent.com/u/3879939/works.PNG

Similarly, if I add more blue but keep a square ish black region, then it also works. https://dl.dropboxusercontent.com/u/3879939/alsoWorks.PNG

But as soon as I make the image not have a square black portion, but maybe rectangular. Then the 'furthest away' is off. Sometimes it even says a blue pixel is the furthest away from blue, which is just not right.

https://dl.dropboxusercontent.com/u/3879939/off.PNG

Any help much appreciated! Hurting my head a bit.

Upvotes: 1

Views: 1628

Answers (3)

Roger Rowland
Roger Rowland

Reputation: 26259

One possibility, given that you're using OpenCV anyway, is to just use the supplied distance transform function.

For your particular case, you would need to do the following:

  1. Convert your input to a single-channel binary image (e.g. map black to white and blue to black)
  2. Run the cv::distanceTransform function with CV_DIST_L2 (Euclidean distance)
  3. Examine the resulting greyscale image to get the results.

Note that there may be more than one pixel at the maximum distance from the border, so you need to handle this case according to your application.

The brightest pixels in the distance transform will be the ones that you need. For example, here is a white rectangle and its distance transform:

example

Upvotes: 3

ultimA
ultimA

Reputation: 298

In square due to its symmetry the furthest black point (the center) is also the furthest no matter in which direction you look from there. But now try to imagine a very long rectangle with a very short height. There will be multiple points on its horizontal axis, to which the largest minimum distance will be the short distance to both the top and bottom sides, because the left and right sides are far away. In this case the pixel your algorithm finds can be any one on this line, and the result will depend on your pixel scanning order.

Upvotes: 2

HenrySnoopy
HenrySnoopy

Reputation: 327

It's because there is a line(more than one pixel) to meet your condition for a rectangular

Upvotes: 0

Related Questions