gpt4 book ai didi

python - 你如何将 Python cv2.cv.LoadImage 编码到 C IplImage->imageData 结构中

转载 作者:行者123 更新时间:2023-11-28 07:00:24 24 4
gpt4 key购买 nike

这个问题的根源是:OpenCV IplImage->imageData 属性的逐位格式是什么?

背景:我使用 Python 的 ctypes 允许 pythonic 访问使用 OpenCV 的低级 C 库。我已经能够获得几乎所有可从 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 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 中的模型有问题。你能解释一下吗?

最佳答案

我使用的 python 代码缺少一些必需的逻辑。此逻辑不适用于 Python 接口(interface),并且在 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 API 的正确信息。请注意,如果您对数据使用 numpy_array.tostring() 方法并希望使用它来填充 Mat 对象,这将是相同的。希望这对某人有帮助。

关于python - 你如何将 Python cv2.cv.LoadImage 编码到 C IplImage->imageData 结构中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22585184/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com