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

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

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

Я пытался использовать формат "L". 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 Ответ

0 голосов
/ 15 января 2020

Хотя ваш метод упаковки данных с планарным перемежением в данные с пиксельным перемежением будет работать, вы почти наверняка обнаружите, что метод 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 раз быстрее.

enter image description here

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

...