How to correctly format PIL.Image.frombytes using external usb camera data

十年热恋 提交于 2021-01-28 08:28:07

问题


I've had hard time to read data I received from a USB camera and display it correctly. I succeeded, but I worry that I'm doing something wrong because my solution is hacky.

The usb camera I'm using (ui-1640le) returns a byte array that I want to display. I used PIL.Image.frombytes("RGB", (imageWidth, imageHeight), image_bytes) But the image I got was in black and white and repeated itself: Image result

I tried using the "L" format. PIL.Image.frombytes("L", (imageWidth, imageHeight), image_bytes) to see what will happen and I got: this B&W image. Except for being B&W the image looked correct and the function only read third of the data.

So I reverse engineered the data with this code:

# 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()

After that I finally get the picture as it should be: final image

Does this solution make sense to read camera input, am I doing something wrong? Is there a more straight forward approach I'm missing?


回答1:


Whilst your method of packing the planar-interleaved data into pixel-interleaved data will work, you will almost certainly find the Numpy method is many tens of times faster.

First, I'll synthesise your input data:

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)

So, img should now be a representative 100x256 orange image such as you might acquire. I would then interleave the data and make a PIL Image like this with 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)

That takes 30 microseconds on my machine, versus 7 milliseconds with for loops, so some 230x faster.

Keywords: Python, Numpy, PIL, image processing, interleave, interleaved, de-interleave, planar, by pixel, by plane, pack, unpack.



来源:https://stackoverflow.com/questions/59745279/how-to-correctly-format-pil-image-frombytes-using-external-usb-camera-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!