【发布时间】:2014-04-30 09:07:26
【问题描述】:
这个问题的根源是:OpenCV IplImage->imageData属性的逐位格式是什么?
背景:我正在使用 Python 的 ctypes 来允许 pythonic 访问使用 OpenCV 的低级 C 库。我已经能够获得几乎所有可从 python 访问的函数,但我被困在这个需要称为 IplImage 的旧 OpenCV 结构的数据的函数上,特别是 imageData 属性。我无法弄清楚 IplImage->imageData 的组织方式与 python 的 cv2.cv.LoadImage 的 iplimage 类型的组织方式,后者表面上与 C 结构具有相同的数据,但它的组织方式似乎不同。
例如,我有一个 2x2 像素的 4 像素图像。左上角像素为 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 api 将其传递到库中。
所以当然我怀疑 C IplImage->imageData 的数据组织方式完全不同,所以我查看调试器并惊讶地发现不仅数据不同,而且我无法理解:here it是,从 cvLoadImage("rgbw.png") 开始,将其分配给名为 'image' 的 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 255
C:(打印前 16 个字节,而不是 12 个,这是我所期望的,见下文)
000 000 255 | 000 255 000 | 000 000 255 | 000 000 255 | 255 255 000 | 000
注意前六个字节在两者中是相同的。但是,发生了什么事?我们还有另外两个红色像素,然后……一个青色像素?另一件事,这个文件大小为 12 字节(4 像素,每个 3 字节)。当我从 C 中打印出 image->imageSize 属性时,我得到 16,而不是 12。所以有些东西很烂,我不明白。很明显,我的 imageData 模型有问题。能解释一下吗?
【问题讨论】:
-
嗯,过时的 cv2.cv api 将不会出现在即将到来的 opencv 版本中。也许您只是学习如何使用 cv2 / numpy ?
-
我正在使用的库使用旧版本,我没有它的源代码。所以我现在必须让它以这种方式工作。无论如何,cv2 Mat 对象有同样的问题:“数据”属性类似于 IlpImage->imageData。
-
我想我明白了!我稍后会发布一个完整的答案,但基本的缺失信息是 imageData 填充每一行,以便它可以被 4 整除。因此,在我上面的示例中,如果删除第 7 和第 8,然后删除第 15 和第 16 C 示例中的字节(这些是每一行的“结束”),您将拥有与 python 示例中相同的内容。
标签: python c++ c opencv iplimage