Reputation: 1430
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:
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?
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.
Upvotes: 8
Views: 15561
Reputation: 1481
After quite some debugging, found an equivalent implementation between cv2 and NumPy:
import numpy as np
import cv2
mask = np.array([[0,1,1],[0,1,1]])
coords = cv2.findNonZero(mask)
coords_numpy = np.argwhere(mask)
coords_numpy[:, [0, 1]] = coords_numpy[:, [1, 0]]
coords_numpy = np.expand_dims(coords_numpy, axis=1)
Upvotes: 0
Reputation: 41775
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:
numpy returns (row,col) = (y,x)
, and OpenCV returns (x,y) = (col,row)
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.
Upvotes: 15