изображение из массива uint16 с последовательного порта

Вопрос или проблема

Я получаю значения uint16 (RGB565) из последовательного порта. Массив содержит 76800 значений uint16 из изображения 320×240. Прямо сейчас я просто отправляю тестовое изображение с полосой, и получаю это изображение:

введите описание изображения здесь

которое, похоже, генерируется несколько раз с помощью скрипта python, который выглядит так:

def TakePicture():
    xdim = 320
    ydim = 240
    i=0
    RGB_list.pop(0)
    im = Image.new("RGB",(xdim,ydim))
    for k in range(76800):
        value1=int(RGB_list[k])
        RGB_values.append(value1)
    for y in range(ydim):
        for x in range(xdim):
            px = RGB_values[i]
            i = i+1
            im.putpixel((x,y),((px&0xF800) >> 8, (px&0x07E0) >> 3, (px&0x001F) << 3))  
    im.save('image.png')  
    im.show()    

def main():
    try:
        serialPort=serial.Serial(port="/dev/ttyUSB1", baudrate=115200,bytesize=8,parity=serial.PARITY_NONE,stopbits=1,timeout=0)
    except:
        print("невозможно открыть порт")
    while(1):
        if(serialPort.in_waiting>0):
            incoming=serialPort.readline().decode('ascii','ignore')
            incoming=incoming.rstrip()
            if('ET' not in incoming):
                if(not incoming):
                    incoming='0'
                print(incoming)
                RGB_list.append(incoming)
            else:
                with open('serial_python.txt','w',newline="",encoding='utf-8') as txtfile:
                    writer=csv.writer(txtfile)
                    for i in RGB_list:
                        writer.writerow([i])
                TakePicture()

Я использую PIL, чтобы взять каждое значение из массива и сгенерировать пиксель, но почему это не работает? Я получаю эти значения через последовательный порт и преобразую эти значения в целые числа, заполняя другой массив, чтобы впоследствии сгенерировать каждый пиксель.

Сначала я думал, что это связано с кодировкой, но потом понял, что, похоже, это связано с тем, как генерируется изображение. Я нашел что-то по этому поводу на форуме, и многие использовали np массивы.

Ответ или решение

Для решения вашей проблемы отображения изображения, получаемого из массива uint16 через последовательный порт, важно внимательно рассмотреть вашу текущую реализацию и выделить возможные проблемы. Давайте рассмотрим шаги, необходимые для правильного извлечения RGB значений из формата RGB565 и построения изображения.

Проблема и её решение

Ваш массив имеет размеры 320×240 пикселей, что означает, что он содержит 76800 значений uint16. Каждый элемент массива представляет собой цвет пикселя в формате RGB565, который использует 16 бит для кодирования цвета: 5 бит для красного, 6 бит для зелёного и 5 бит для синего.

Ваша текущая реализация в функции TakePicture() производит преобразование некорректно. Давайте разберёмся, как это исправить.

Поправка кода

Ваш исходный код использует метод putpixel из библиотеки Pillow, однако сам алгоритм преобразования из RGB565 в RGB888 имеет некоторые проблемы. Давайте внесем изменения для корректного преобразования значений.

from PIL import Image
import serial
import csv

RGB_list = []  # Список для хранения значений из последовательного порта

def TakePicture():
    xdim = 320
    ydim = 240
    im = Image.new("RGB", (xdim, ydim))

    i = 0
    for y in range(ydim):
        for x in range(xdim):
            # Чтение значения из RGB_list и преобразование
            px = int(RGB_list[i])
            i += 1
            # Преобразование RGB565 в RGB888
            r = (px & 0xF800) >> 8
            g = (px & 0x07E0) >> 3
            b = (px & 0x001F) << 3
            # Убедимся, что значения RGB находятся в диапазоне [0, 255]
            im.putpixel((x, y), (r, g, b))

    im.save('image.png')
    im.show()

def main():
    try:
        serialPort = serial.Serial(port="/dev/ttyUSB1", baudrate=115200, bytesize=8, parity=serial.PARITY_NONE, stopbits=1, timeout=0)
    except Exception as e:
        print("Не удалось открыть порт:", e)

    while True:
        if serialPort.in_waiting > 0:
            incoming = serialPort.readline().decode('ascii', 'ignore').rstrip()
            if 'ET' not in incoming and incoming:
                RGB_list.append(incoming)
            elif 'ET' in incoming:
                # Запись в файл
                with open('serial_python.txt', 'w', newline="", encoding='utf-8') as txtfile:
                    writer = csv.writer(txtfile)
                    for i in RGB_list:
                        writer.writerow([i])
                TakePicture()  # Генерация изображения

if __name__ == "__main__":
    main()

Объяснение изменений

  1. Преобразование из RGB565 в RGB888: Ваша первоначальная логика, применяемая для формирования RGB-пикселей, использовала неверные операции и битовые сдвиги. Я уточнил данный процесс, чтобы он соответствовал стандартному алгоритму преобразования RGB565 в RGB888.

  2. Проверка значений пикселей: Важно убедиться, что значения RGB находятся в диапазоне от 0 до 255. Ваши значения r, g и b должны быть корректно обработаны, чтобы избежать цветовых искажений.

  3. Упрощение логики: Код был оптимизирован для повышения читаемости и устранения лишних операций, что улучшит производительность.

Заключение

Использование данного обновления улучшит качество генерируемого изображения. Убедитесь, что в процессе передачи данных по последовательному порту корректно обрабатываются любые потенциальные ошибки и что данные поступают в ожидаемом формате.

Если после этих изменений изображение по-прежнему отображается некорректно, рекомендуется проверить исходные данные, передаваемые через последовательный порт, на наличие возможных ошибок.

Оцените материал
Добавить комментарий

Капча загружается...