Difference between cv2.findNonZero and Numpy.NonZero
<p>Silly question here.</p>

<p>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.</p>

<p>The example I found on the internet (<a href="http://docs.opencv.org/trunk/d1/d32/tutorial_py_contour_properties.html" rel="nofollow">http://docs.opencv.org/trunk/d1/d32/tutorial_py_contour_properties.html</a>):</p>

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

<p>Which states </p>

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

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

<blockquote>
  <p>Numpy gives coordinates in (row, column) format, while OpenCV gives coordinates in <strong>(y,x)</strong> or <strong>(column, row)</strong> format.</p>
</blockquote>

<p>My questions are:</p>

<ol>
<li><p>Does numpy return <strong>(row,col)</strong>/<strong>(x,y)</strong> and OpenCV <strong>(y,x)</strong> where row=x, col=y? Although IMHO it should be row=y, col=x?</p></li>
<li><p>Which one is more computation efficient? In terms of time &amp; resources.</p></li>
</ol>

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

<p>There is an error in the documentation:</p>

<blockquote>
  <p>Numpy gives coordinates in (row, column) format, while OpenCV gives coordinates in (x,y) format. So basically the answers will be interchanged. <s>Note that, row = x and column = y.</s> <strong>Note that, row = y and column = x.</strong></p>
</blockquote>

<p>So, regarding your questions:</p>

<ol>
<li>numpy returns <code>(row,col) = (y,x)</code>, and OpenCV returns <code>(x,y) = (col,row)</code></li>
<li><p>You need to scan the whole matrix and retrieve some points. I don't think there will be any significant difference in performance (<em>should be tested!</em>). </p>

<p><s>Since you're using Python, probably it's better to use Python facilities, e.g. numpy.</s> </p></li>
</ol>

<p>Runtime test comparing these two versions -</p>

<pre><code>In [86]: mask = (np.random.rand(128,128)&gt;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)&gt;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)&gt;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
</code></pre>

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

python opencv numpy