我正在玩一台使用Micro-Manager 1.4的显微镜相机。使用Python界面,我设法访问相机,更改曝光时间等,我可以捕获单个图像。
然而,每个图像作为NumPy数组返回,其中每个像素表示为单个整数,例如, “7765869”。据我所知,这在Java中被称为“BufferedImage”,它意味着RGB值被编码为:
BufferedImage = R * 2^16 + G * 2^8 + B
我的问题是:我怎样才能使用例如Numpy或OpenCV,将这种数组转换为更方便的数组,其中每个像素是uint8值的RGB三元组?毋庸置疑,转换应该尽可能高效。
答案 0 :(得分:7)
最简单的是让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()
来真正摆脱零列,而不是简单地忽略它,尽管这个当然会触发上面代码避免的数据副本。
答案 1 :(得分:2)
一种方法是
Red = BufferedImage / 2**16
Green = (BufferedImage % 2**16) / 2**8
Blue = (BufferedImage % 2**8)
然而,我怀疑它是最优雅的(Pythonic?)还是最快的方式。
答案 2 :(得分: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
这对我来说更具可读性并清楚发生了什么
答案 3 :(得分:0)
最快的方法可能是保持这种状态:
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]))