Я работаю над сенсорным Python-приложением, основанным на графическом интерфейсе PyQt4. Датчик генерирует 16-битные измерения ... 256 16-разрядных «пикселей» на «линию». Квадратное «изображение» получается путем получения 256 строк, в результате чего получается массив (256 256) Numpy из 16-разрядных чисел. Я просто хочу отобразить это как изображение в оттенках серого. Контур датчика работает в QThread и испускает сигнал QImage. Сигнал подключается к слоту, который отображает данные в главном графическом интерфейсе, упаковывая его в 32-разрядное изображение RGB. Конечно, чтобы упаковать 16-битные оттенки серого в 32-битное RGB-изображение, я вынужден масштабировать 16-битные пиксели до 8-бит, и значительное количество динамического диапазона теряется. Предоставляется MWE, которая показывает мою текущую стратегию (это, очевидно, не мое приложение с большим количеством резьбовых датчиков ... оно просто извлекает существенные части). Обратите внимание, что я новичок Python, и я делаю все возможное, чтобы не отставать от ...Преобразование 16-битных оттенков серого в QImage
#!/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()
В частности, мои вопросы:
Есть ли лучший способ? Решение должно оставаться «легким» (т. Е. PyQt4 QImage/QPixmap). Я не могу использовать Matplotlib или что-нибудь тяжелое, поскольку он слишком медленный. Чем ближе к родному Python/Numpy, тем лучше. Я понимаю, что это, в конечном счете, ограничение класса QImage, но я надеялся, что есть умное решение, которое я просто не вижу, что позволяет мне поддерживать текущий сигнал/слот «проводки», который у меня есть.
В результате экспериментов я обнаружил, что мне нужно объявить все массивы, которые в конечном итоге будут обработаны, чтобы закончить QImage как np.uint32 (хотя, похоже, работает и np.int32). Это не работает, если я просто объявляю предпоследний массив как uint32/int32. Я не понимаю, почему.
Я играл с изменяющейся яркостью с
Y' = 0.2126 * R + 0.7152 * G + 0.0722 * B
и другими аналогичными преобразованиями. Вероятно, «полировка турки» здесь, но я думал, что включу это, потому что другие ответы на SX, похоже, указывают на то, что это важно. Несмотря на потерю динамического диапазона, кажется, что просто назначить одно и то же значение R, G, B, как в моем MWE.
В соответствии с просьбой в комментариях ниже, здесь гистограмма некоторых выборочных данных от датчика, чтобы проиллюстрировать динамический диапазон:
Можете ли вы показать гистограмму данных с датчика? Возможно, он не использует весь диапазон 16 бит. Например, вы можете сделать максимальное значение «белым» на «img_16bit/(img_16bit.max()/255.0)». Вы также можете найти максимальное и минимальное значение данных датчика и сопоставить их с 255 и 0. – HYRY
@HYRY, добавлена гистограмма, показывающая, что я использую полный диапазон 16-бит ... – ph0t0n
Итак, большая часть данных находится в диапазоне 25000 - 45000, возможно, скопируйте данные в этот диапазон и сопоставьте их с 0 - 255. получить лучший результат. – HYRY