Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between cv2.findNonZero and Numpy.NonZero

Silly question here.

I want to find the locations of the pixels from some black and white images and found this two functions from Numpy library and OpenCV.

The example I found on the internet (http://docs.opencv.org/trunk/d1/d32/tutorial_py_contour_properties.html):

    mask = np.zeros(imgray.shape,np.uint8)
    cv2.drawContours(mask,[cnt],0,255,-1)
    pixelpoints = np.transpose(np.nonzero(mask))
    pixelpointsCV2 = cv2.findNonZero(mask)

Which states

Numpy gives coordinates in (row, column) format, while OpenCV gives coordinates in (x,y) format. So basically the answers will be interchanged. Note that, row = x and column = y.

Based on my understanding of english, isn't their explanation wrong? Shouldn't it be:

Numpy gives coordinates in (row, column) format, while OpenCV gives coordinates in (y,x) or (column, row) format.

My questions are:

  1. Does numpy return (row,col)/(x,y) and OpenCV (y,x) where row=x, col=y? Although IMHO it should be row=y, col=x?

  2. Which one is more computation efficient? In terms of time & resources.

Maybe I am not getting this simple thing right due to not being a non-native English speaker.

like image 859
RMS Avatar asked Oct 12 '16 09:10

RMS


People also ask

What is NumPy nonzero?

nonzero() function is used to Compute the indices of the elements that are non-zero. It returns a tuple of arrays, one for each dimension of arr, containing the indices of the non-zero elements in that dimension. The corresponding non-zero values in the array can be obtained with arr[nonzero(arr)] .

How do you find the non-zero element in a NumPy array?

NumPy has the efficient function/method nonzero() to identify the indices of non-zero elements in an ndarray object.


1 Answers

There is an error in the documentation:

Numpy gives coordinates in (row, column) format, while OpenCV gives coordinates in (x,y) format. So basically the answers will be interchanged. Note that, row = x and column = y. Note that, row = y and column = x.

So, regarding your questions:

  1. numpy returns (row,col) = (y,x), and OpenCV returns (x,y) = (col,row)

  2. You need to scan the whole matrix and retrieve some points. I don't think there will be any significant difference in performance (should be tested!).

    Since you're using Python, probably it's better to use Python facilities, e.g. numpy.

Runtime test comparing these two versions -

In [86]: mask = (np.random.rand(128,128)>0.5).astype(np.uint8)

In [87]: %timeit cv2.findNonZero(mask)
10000 loops, best of 3: 97.4 µs per loop

In [88]: %timeit np.nonzero(mask)
1000 loops, best of 3: 297 µs per loop

In [89]: mask = (np.random.rand(512,512)>0.5).astype(np.uint8)

In [90]: %timeit cv2.findNonZero(mask)
1000 loops, best of 3: 1.65 ms per loop

In [91]: %timeit np.nonzero(mask)
100 loops, best of 3: 4.8 ms per loop

In [92]: mask = (np.random.rand(1024,1024)>0.5).astype(np.uint8)

In [93]: %timeit cv2.findNonZero(mask)
100 loops, best of 3: 6.75 ms per loop

In [94]: %timeit np.nonzero(mask)
100 loops, best of 3: 19.4 ms per loop

Thus, it seems using OpenCV results in something around 3x speedup over the NumPy counterpart across varying datasizes.

like image 61
3 revs, 2 users 60% Avatar answered Nov 10 '22 01:11

3 revs, 2 users 60%