在 Python 中将单个整数像素数组转换为 RGB 三元组

Posted

技术标签:

【中文标题】在 Python 中将单个整数像素数组转换为 RGB 三元组【英文标题】:Convert array of single integer pixels to RGB triplets in Python 【发布时间】:2013-10-26 06:42:45 【问题描述】:

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

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

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

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

【问题讨论】:

为了扩展这背后的理论,你所拥有的是一个a * x + b * y + c * z == n形式的线性丢番图方程,在我们的例子中是a = 2**16, b = 2**8, c = 1。通常,这些方程的解涉及找到gcd(a, b, c) 并希望它除以n;如果没有,那么就没有解决方案。假设存在一个解决方案,则存在无限多个解决方案。但是,在这种情况下,我们受限于找到解决方案0 <= x, y, z < 256,因此鉴于gcd(a, b, c) | n,将只有一个解决方案。 【参考方案1】:

最简单的方法是让 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() 才能真正摆脱零列,而不是简单地忽略它,尽管这会当然会触发上面代码避免的数据副本。

【讨论】:

完美运行!将“img2”定义为“img.view(np.uint8).reshape(img.shape+(4,))[..., :3]”,然后使用“cv2.imwrite”完美保存图像。谢谢! @Bjarke 您可能需要确保保存的是 RGB 图像,而不是 BGR 图像...这取决于系统的字节序。如果有误,只需在 img2 定义的末尾加上 [::-1],它就会颠倒读取它们的顺序。 非常聪明的解决方案! @tom10 是的,它很聪明,尽管平心而论,这是别人的聪明:我以设计打印机管道为生,这种字节摆弄或多或少是我们 (HP) 产品中的标准程序.【参考方案2】:

最快的方法可能是将其保存在 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]))

【讨论】:

【参考方案3】:
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

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

【讨论】:

【参考方案4】:

一种方法是

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

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

【讨论】:

以上是关于在 Python 中将单个整数像素数组转换为 RGB 三元组的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中将 getRGB(x,y) 整数像素转换为 Color(r,g,b,a)?

在 OpenCV python 中将白色像素转换为黑色

如何在 Swift 中将单个数组转换为嵌套数组? [复制]

如何在 Postgres 中将布尔数组转换为单个布尔值或单个字符串

在java中将整数列表转换为整数数组[重复]

如何在php中将字节数组转换为整数?