这个问题的根源是: OpenCV IplImage->imageData属性的逐位格式是什么?
背景:我使用Python的ctype来允许使用OpenCV的低级别C库访问pythonic。我已经能够从python获得几乎所有可访问的函数,但我仍然停留在这个函数上,它需要被称为OpenCV的旧IplImage结构的数据,特别是imageData属性。我不知道IplImage->imageData是如何组织的,而python的cv2.cv.LoadImage的iplimage类型,它表面上具有与C结构相同的数据,但它的组织方式似乎不同。
例如,我有一个4像素的图像,是2x2像素。左上角像素为100%红色。右上角像素为100%绿色。左下角像素为100%蓝色,右下角像素为100%白色。
在python中,信息如下所示:
import cv2
img = cv2.cv.LoadImage('rgbw.png')
pixels = []
for ch in img.tostring():
pixels.append(ord(ch))
print pixels
[0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, 255]这对我来说很有意义:前三个值0,0,255代表B:0,G:0,R:255,红色像素。第二个是绿色,第三个是左下角,蓝色,最后一个右下角是白色。
我将其编组到库中,它运行良好,但它似乎没有“看到”imageData中的任何内容(当我使用C将数据直接传递到库时,返回代码意味着“我没有看到任何东西”)。
当然,我怀疑cvLoadImage>imageData有完全不同的数据组织方式,所以我在调试器中发现不仅数据不同,而且我无法理解它:这里是一个cvLoadImage("rgbw.png"),将它分配给一个名为‘IplImage’的IplImage结构。
Breakpoint 1, main (argc=2, argv=0x7fffffffe418) at IplImageInfo.cpp:44
44 printf("imageData %s\n", image->imageData);
(gdb) x/16ub image->imageData
0x618c90: 0 0 255 0 255 0 0 0
0x618c98: 255 0 0 255 255 255 0 0
(gdb)因此,将其逐字节进行比较,添加零以便于比较:
Python:
000 000 255 | 000 255 000 | 255 000 000 | 255 255 255C:(打印前16个字节,而不是12个字节,这正是我所期望的,见下文)
000 000 255 | 000 255 000 | 000 000 255 | 000 000 255 | 255 255 000 | 000注意,前六个字节在这两个字节中都是相同的。但是,到底怎么回事?我们还有两个红色像素然后..。一个青色像素?另外,这个文件的大小是12个字节(4个像素,每个3个字节)。当我从C打印出图像->imageSize属性时,我得到16,而不是12。所以有些东西坏了,我不明白。显然,我的imageData模型有问题。你能解释一下吗?
发布于 2014-03-23 22:58:17
我使用的python代码缺少一些所需的逻辑。这个逻辑不适用于Python接口,在Python中也不知道它是如何在C库中工作的。基本上,IplImage (我也相信Mat;旧IplImage结构的C++继承者)通过添加空(0-值)字节数,将imageData属性中的一行像素除以4。所以我的代码,就是:
import cv2
img = cv2.cv.LoadImage('rgbw.png')
pixels = []
for ch in img.tostring():
pixels.append(ord(ch))
print pixels
[0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, 255]错过了这个逻辑。我解决了以下问题:
import cv2
img = cv2.cv.LoadImage('rgbw.png')
height = img.height
width = img.width
raw_data = img.tostring()
# iplImage->imageData requires rows to be padded with zero bytes at the end
# so they be divisible by 4
pad_bytes_per_row = width % 4
# create the ctypes structure
ubyte_array_type = c_ubyte * (len(raw_data) + (height * pad_bytes_per_row))
ubyte_array = ubyte_array_type()
index = 0
for ch in raw_data:
ubyte_array[index] = ord(ch)
index += 1
if 0 == index % width: # end of row
pad_index = 0
while pad_index < pad_bytes_per_row:
ubyte_array[index] = 0
pad_index += 1
index += 1现在,ubyte_array中填充了opencv的python中的正确信息。注意,如果您对数据使用numpy_array.tostring()方法,并且希望使用该方法填充Mat对象,则这将是相同的。希望这能帮上忙。
https://stackoverflow.com/questions/22585184
复制相似问题