7

我正在使用 Micro-Manager 1.4 为显微镜使用相机。使用 Python 界面,我设法访问相机、更改曝光时间等,并且可以捕获单个图像。

但是,每个图像都作为 NumPy 数组返回,其中每个像素都表示为单个整数,例如“7765869”。据我在网上找到,这在 Java 中被称为“BufferedImage”,这意味着 RGB 值被编码为:

BufferedImage = R * 2^16 + G * 2^8 + B

我的问题是:我如何使用 Numpy 或 OpenCV 将这种数组转换为更方便的数组,其中每个像素都是 uint8 值的 RGB 三元组?不用说,转换应该尽可能高效。

4

4 回答 4

8

最简单的方法是让 numpy 为您进行转换。您的 numpy 数组可能是np.uint32. 如果你把它看成一个 的数组np.uint8,你会得到一个 RGB0 格式的图像,即每个像素的 R、G 和 B 的值,加上一个空的np.uint8后续。重塑和丢弃该零值很容易:

>>> img = np.array([7765869, 16777215], dtype=np.uint32)
>>> img.view(np.uint8)
array([109, 127, 118,   0, 255, 255, 255,   0], dtype=uint8)
>>> img.view(np.uint8).reshape(img.shape+(4,))[..., :3]
array([[109, 127, 118],
       [255, 255, 255]], dtype=uint8)

最好的事情是没有数据的计算或复制,只是对原始图像内容的重新解释:我认为没有比这更有效的了!

我记得对于某些操作,OpenCV 需要一个连续的数组,因此您可能必须在.copy()该表达式的末尾添加 a 才能真正摆脱零列,而不是简单地忽略它,尽管这当然会触发数据的副本上面的代码已经避免了。

于 2013-10-17T17:02:51.593 回答
2

一种方法是

Red = BufferedImage / 2**16
Green = (BufferedImage % 2**16) / 2**8
Blue = (BufferedImage % 2**8)

但是,我怀疑这是最优雅的(Pythonic?)或最快的方式。

于 2013-10-17T16:45:28.670 回答
0
rgbs = [((x&0xff0000)>>16,(x&0xff00)>>8,x&0xff) for x in values]

至少我认为...

afaik 上面的公式也可以写成

BufferedRGB = RED<<16 + GREEN << 8 + BLUE 

red,green,blue = 0xFF,0x99,0xAA
red<<16 + green << 8 + blue  #= 0xFF99AA (buffered into one value)

#apply a bitmask to get colors back
red = (0xFF99AA & 0xFF0000) >> 16 # = 0xFF
green = (0xFF99AA & 0xFF00) >> 8  # = 0x99
blue = 0xFF99AA & 0xFF          # = 0xAA

这对我来说更具可读性并且清楚发生了什么

于 2013-10-17T16:42:31.403 回答
0

最快的方法可能是将其保存在 numpy 中:

from numpy import *
x = array([211*2**16 + 11*2**8 + 7])  # test data

b, g, r = bitwise_and(x, 255), bitwise_and(right_shift(x, 8), 255), bitwise_and(right_shift, 16), 255)

print r, g, b
(array([211]), array([11]), array([7]))
于 2013-10-17T16:56:45.260 回答