gpt4 book ai didi

python - 将 16 位灰度转换为 QImage

转载 作者:太空宇宙 更新时间:2023-11-03 11:32:20 25 4
gpt4 key购买 nike

我正在开发基于 PyQt4 GUI 的基于传感器的 Python 应用程序。传感器正在生成 16 位测量值……每“行”有 256 个 16 位“像素”。通过获取 256 行获取正方形“图像”,从而生成 (256,256) 个 16 位数字的 Numpy 数组。我只想将其显示为灰度图像。传感器循环在 QThread 中运行并发出 QImage 信号。该信号连接到一个插槽,该插槽通过将数据打包成 32 位 RGB 图像来在主 GUI 中呈现数据。当然,为了将 16 位灰度像素打包成 32 位 RGB 图像,我不得不将 16 位像素缩放为 8 位,并且丢失了大量的动态范围。提供的 MWE 显示了我当前的策略(这显然不是我更大的基于线程传感器的应用程序……它只是提取了突出部分)。请注意,我是一名 Python 初学者,我正在尽最大努力跟上......

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Grayscale to RGB32 QPixmap tests
"""

import sys
import numpy as np
from PyQt4 import QtGui, QtCore

class PixmapTest(QtGui.QWidget):

def __init__(self):
super(PixmapTest, self).__init__()
self.initUI()

def initUI(self):
imglayout = QtGui.QHBoxLayout(self)

img_16bit = np.random.randint(0,65535,size=(256,256)).astype(np.uint32)
img_16bit_to_8bit = (img_16bit / 65535.0 * 255).astype(np.uint32)
packed_img_array = (255 << 24 | (img_16bit_to_8bit) << 16 | (img_16bit_to_8bit) << 8 | (img_16bit_to_8bit)).flatten()
img = QtGui.QImage(packed_img_array, 256, 256, QtGui.QImage.Format_RGB32)
pixmap = QtGui.QPixmap(img.scaledToWidth(img.width()*2))

imglabel = QtGui.QLabel(self)
imglabel.setPixmap(pixmap)

imglayout.addWidget(imglabel)
self.setLayout(imglayout)

self.move(300, 200)
self.setWindowTitle('QPixmap Test')
self.show()

def main():

app = QtGui.QApplication(sys.argv)
form = PixmapTest()
sys.exit(app.exec_())


if __name__ == '__main__':
main()

具体来说,我的问题是:

  1. 有没有更好的方法?该解决方案必须保持“轻量级”(即 PyQt4 QImage/QPixmap)。我不能使用 Matplotlib 或任何重量级的东西,因为它太慢了。越接近原生 Python/Numpy 越好。我意识到这最终是 QImage 类的一个限制,但我希望有一个我只是没有看到的聪明解决方案可以让我保持当前的信号/插槽“接线”。

  2. 通过实验,我发现我必须声明所有最终被处理以在 QImage 中结束的数组为 np.uint32(尽管 np.int32 似乎也可以)。如果我只是将倒数第二个数组声明为 uint32/int32,那将不起作用。我不明白为什么。

  3. 我试过使用 Y' = 0.2126 * R + 0.7152 * G + 0.0722 * B 和其他类似转换来改变亮度。可能在这里“抛光粪便”,但我想我会包括这个,因为 SX 上的其他答案似乎表明这很重要。尽管动态范围有所损失,但将与我的 MWE 中相同的值简单地分配给 R、G、B 似乎可行。

根据下面评论中的要求,这是来自传感器的一些样本数据的直方图,用于说明动态范围:

histogram of actual sensor data

最佳答案

这里我使用了一些函数数据来演示:

y, x = np.mgrid[-10:10:256j, -10:10:256j]
data = ((np.sin(y**2 + x**2) + 2) * 1000).astype(np.uint16)

img_8bit = (data / 256.0).astype(np.uint8) # use the high 8bit
img_8bit = ((data - data.min()) / (data.ptp() / 255.0)).astype(np.uint8) # map the data range to 0 - 255
img = QtGui.QImage(img_8bit.repeat(4), 256, 256, QtGui.QImage.Format_RGB32)

当使用高8bit时,看起来像:

enter image description here

当将最小值和最大值映射到 (0, 255) 时,它看起来像:

enter image description here

要将 8 位图像转换为 32 位,只需调用 img_8bit.repeat(4),这会将每个字节重复 4 次,因此内存可以看作是一个 uint32 缓冲区。由于您通过 Format_RGB32 而不是 Format_ARGB32 创建了 QImage,因此未使用最高有效字节。

关于python - 将 16 位灰度转换为 QImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15672743/

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