Как правильно отформатировать PIL.Image.frombytes с использованием данных внешней USB-камеры

Мне было трудно читать данные, полученные с USB-камеры, и правильно отображать их. Я преуспел, но я беспокоюсь, что я делаю что-то не так, потому что мое решение является хакерским.

Используемая нами USB-камера ( ui-1640le ) возвращает массив байтов, который я хочу отобразить. Я использовал PIL.Image.frombytes("RGB", (imageWidth, imageHeight), image_bytes) Но полученное изображение было черно-белым и повторялось: Результат изображения

Я пытался использовать формат "L" . PIL.Image.frombytes("L", (imageWidth, imageHeight), image_bytes) чтобы увидеть, что произойдет, и я получил: это PIL.Image.frombytes("L", (imageWidth, imageHeight), image_bytes) изображение . За исключением того, что он был черно-белым, изображение выглядело правильно, и функция считывала только треть данных.

Итак, я обработал данные с помощью этого кода:

# Reorder the bytes structure
x=[]
for i in range(width*height):
    x += [img[i],img[i+width*height],img[i+2*width*height]]
image_bytes = bytes(x)


# Create a PIL Image
im = PIL.Image.frombytes("RGB", (imageWidth, imageHeight), image_bytes)

# Not sure why the image is flipped, but this fixes it
im.rotate(-90).transpose(PIL.Image.FLIP_LEFT_RIGHT).show()

После этого я наконец получаю картинку, как и должно быть: окончательное изображение

Имеет ли это решение смысл читать с камеры, я что-то не так делаю? Есть ли более прямой подход, который я пропускаю?

Всего 1 ответ


Хотя ваш метод упаковки данных с планарным перемежением в данные с пиксельным перемежением будет работать, вы почти наверняка обнаружите, что метод Numpy во много десятков раз быстрее.

Сначала я синтезирую ваши входные данные:

import numpy as np

# Height, width and bytes per image channel
h,w = 100,256
bpc = h * w

# Now make the first (red) plane = 255, the second (green) plane = 127 and the final (blue) plane = 0
img = bytes(b"xff"*bpc) + bytes(b"x7f"*bpc) + bytes(b"x00"*bpc)

Итак, теперь img должно быть представительным 100x256 оранжевым изображением, которое вы можете получить. Затем я чередую данные и создаю PIL-изображение, например, с помощью Numpy:

from PIL import Image

# Make a Numpy array for each channel's pixels
R = np.frombuffer(img, dtype=np.uint8, count=bpc).reshape((h,w))  
G = np.frombuffer(img, dtype=np.uint8, count=bpc, offset=bpc).reshape((h,w))  
B = np.frombuffer(img, dtype=np.uint8, count=bpc, offset=2*bpc).reshape((h,w))

# Interleave the pixels from RRRRRRGGGGGGBBBBBB to RGBRGBRGBRGBRGB
RGB = np.dstack((R,G,B))

# Make PIL Image from Numpy array
pImage = Image.fromarray(RGB)

Это занимает 30 микросекунд на моей машине, по сравнению с 7 миллисекундами с циклами for , так что примерно в 230 раз быстрее.

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

Ключевые слова : Python, Numpy, PIL, обработка изображений, чередование, чередование, обратное чередование, плоское, по пикселю, по плоскости, пакет, распаковка.


Есть идеи?

10000