Ask Your Question

Revision history [back]

Finding nearest non-zero pixel

I've got a binary image noObjectMask (CV_8UC1) and a given point objectCenter (cv::Point). If the objectCenter is a zer-value pixel, I need to find the nearest non-zero pixel starting from the given point.

The number of non-zero points in the whole image can be large (even up to 50%), so calculating distances for each point returned from cv::findNonZero seems to be non-optimal. As the highest probability is that the pixel will be in the close neighborhood, I currently use:

# my prototype script in Python, but the final version will be implemented in C++
if noObjectMask[objectCenter[1],objectCenter[0]] == 0:
        # if the objectCenter is zero-value pixel, subtract sequentially its neighborhood ROIs
        # until the ROI contains at least one non-zero pixel
        for r in range(noObjectMask.shape[1]/2):
            rectL = objectCenter[1]-r-1
            rectR = objectCenter[1]+r
            rectT = objectCenter[0]-r-1
            rectB = objectCenter[0]+r
            # Pythonic way of subtracting ROI: noObjectMask(cv::Rect(...))
            rect = noObjectMask[rectL:rectR, rectT:rectB]
            if cv2.countNonZero(rect)>0: break
        nonZeroNeighbours = cv2.findNonZero(rect)
        # calculating the distances between objectCenter and each of nonZeroNeighbours
        # and choosing the closest one

This works okay, as in my images the non-zero pixels are typically in the closest neighborhood (r<=10px), but the processing time increases dramatically with the distance of the closest pixel. Each repetition of countNonZero repeats counting of the previous pixels. This could be improved by incrementing the radius r by more than one, but this still looks a bit clumsy to me.

How to improve the procedure? And ideas? -Thanks!

Finding nearest non-zero pixel

I've got a binary image noObjectMask (CV_8UC1) and a given point objectCenter (cv::Point). If the objectCenter is a zer-value pixel, I need to find the nearest non-zero pixel starting from the given point.

The number of non-zero points in the whole image can be large (even up to 50%), so calculating distances for each point returned from cv::findNonZero seems to be non-optimal. As the highest probability is that the pixel will be in the close neighborhood, I currently use:

# my prototype script in Python, but the final version will be implemented in C++
if noObjectMask[objectCenter[1],objectCenter[0]] == 0:
        # if the objectCenter is zero-value pixel, subtract sequentially its neighborhood ROIs
        # increasing its size (r), until the ROI contains at least one non-zero pixel
        for r in range(noObjectMask.shape[1]/2):
            rectL = objectCenter[1]-r-1
            rectR = objectCenter[1]+r
            rectT = objectCenter[0]-r-1
            rectB = objectCenter[0]+r
            # Pythonic way of subtracting ROI: noObjectMask(cv::Rect(...))
            rect = noObjectMask[rectL:rectR, rectT:rectB]
            if cv2.countNonZero(rect)>0: break
        nonZeroNeighbours = cv2.findNonZero(rect)
        # calculating the distances between objectCenter and each of nonZeroNeighbours
        # and choosing the closest one

This works okay, as in my images the non-zero pixels are typically in the closest neighborhood (r<=10px), but the processing time increases dramatically with the distance of the closest pixel. Each repetition of countNonZero repeats counting of the previous pixels. This could be improved by incrementing the radius r by more than one, but this still looks a bit clumsy to me.

How to improve the procedure? And ideas? -Thanks!