mpeaton / pyopencv

Automatically exported from code.google.com/p/pyopencv
0 stars 0 forks source link

convert MatND <-> ndarray #18

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
>>> What steps will reproduce the problem?
1. run following program
-------------------------
import pyopencv as cv
import numpy as np

m = np.arange(0, 20).astype(np.uint8)
m.shape = 4,5

n = cv.asMatND(m)

p = n.ndarray

print m
print "------------"
print p

>>> What is the expected output? What do you see instead?
I think the two print should output the same array, but here is the output:

[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
------------
[[ 0  4  8 12 16]
 [ 1  5  9 13 17]
 [ 2  6 10 14 18]
 [ 3  7 11 15 19]]

the different of strides cause the problem:

the strides of m is (5, 1), but the strides of p is (1, 4)

>>> What version of the product are you using? On what operating system?

Windows XP, Version: 2.1.0.wr1.0.2

>>> Please provide any additional information below.

Original issue reported on code.google.com by ruoyu0...@gmail.com on 9 Jun 2010 at 9:21

GoogleCodeExporter commented 9 years ago
Thanks, ruoyu0088. The bug is confirmed.

The current issue is that MatND only supports contiguous arrays stored in the 
little-endian format (i.e. the stride increases from the left most dimension to 
the right most dimension). This means the provided ndarray must also be 
contiguous and stored in the little-endian format. By specifying "m.shape = 4, 
5", you specify that the array is contiguous _but_ the arrangement of the items 
are not in the little-endian format. However, the current conversion code only 
checks for contiguity and not for the little-endian format, hence the bug. When 
I have time, I will add code to raise an error when this case happens.

Cheers,
Minh-Tri

Original comment by pmtri80@gmail.com on 9 Jun 2010 at 9:51

GoogleCodeExporter commented 9 years ago
Oh, wait. Please ignore my previous message. I think I'm wrong. :)

Minh-Tri

Original comment by pmtri80@gmail.com on 9 Jun 2010 at 9:54

GoogleCodeExporter commented 9 years ago
Hi ruoyu0088,

After digging PyOpenCV's code and OpenCV's code, I found what had gone wrong. 
The problem is, OpenCV's code is inconsistent in choosing between the 
little-endian format and the big-endian format to represent a CvMatND. 
- At cxmat.hpp:3707, when a Mat is converted into a MatND, the big-endian 
format is used.
- At cxarray.cpp:249, when a CvMatND is created from an array, the 
little-endian format is used.

Right now, PyOpenCV assumes that OpenCV uses the big-endian format to arrange 
the array elements. Thus, if you create a Mat instance 'mat' and then use 
'cv.MatND(mat)' to obtain an equivalent MatND instance, it should work. 
However, if you create an ndarray and then use 'cv.asMatND()' to obtain a MatND 
view, it would not work.

I'm a bit too busy this month. But I will try to nail this issue down as soon 
as I can.

Cheers,
Minh-Tri

Original comment by pmtri80@gmail.com on 9 Jun 2010 at 10:36

GoogleCodeExporter commented 9 years ago
FYI, I have fixed the bug in the main trunk. However, the current version in 
the main trunk is a transition version. There are a few changes that make some 
functions incompatible with previous versions. But these changes are necessary 
for the future.

Minh-Tri

Original comment by pmtri80@gmail.com on 16 Jul 2010 at 2:34