将图像转换为二进制流
我的应用程序有两个部分,一部分是用C++来读取摄像头的画面,使用的是Pleora的EBUS SDK。当我第一次接收到这个视频流时,在把数据转换成图像之前,我可以每次读取16位的数据,这样可以对每个像素进行一些计算,也就是说,每个像素都有一个16位的数据块。
第二部分是一个Django的网页应用,我在这里也能看到这个视频输出,这次是通过ffmpeg、nginx和hls流来实现的。当用户点击视频时,我想获取当前的画面和他们点击的位置,然后在C++部分做的同样的计算。
现在我使用一个html5的画布来捕捉画面,并用canvas.toDataURL()
把画面转换成一个base64编码的图像,然后通过AJAX把这个base64图像、点击的坐标和画面的尺寸传给Python。
在Python中,我试图以某种方式处理这个base64编码的图像,以便每个像素能有16位的数据。目前我做的是:
pos = json.loads(request.GET['pos'])
str_frame = json.loads(request.GET['frame'])
dimensions = json.loads(request.GET['dimensions'])
pixel_index = (dimensions['width'] * pos['y']) + pos['x'] + 1
b64decoded_frame = base64.b64decode(str_frame.encode('utf-8'))
但是在b64decoded_frame
中的索引数量远少于图像中的像素数量,而且整数值也没有预期的那么高。我检查过,图像是完整的,因为我可以把它保存为png格式。
总结一下,我该如何把一个base64图像转换成一个序列化的二进制流,使得每个像素用16位表示。
更新
我忘了提,我使用的是python3.2。
经过进一步的研究,我认为我想要做的是获取某个像素的mono16值。我不确定这是否是我想要的,但如果有人能解释一下如何把图像转换成mono16或者把一个像素转换成mono16,我可以进一步探索,看看这是否真的是解决方案。
1 个回答
0
我选择的解决方案是先把图片转换成8位灰度图像,然后再把想要的像素转换成16位的版本。这个解决方案大致如下:
import base64
import io
from PIL import Image
if request.method == 'GET':
if request.GET['pos'] and request.GET['frame']:
pos = json.loads(request.GET['pos'])
str_frame = json.loads(request.GET['frame'])
# Converts the base64 string into a byte string, we need to encode
# str_frame as utf-8 first otherwise python3.2 complains about unicode
b64decoded_frame = base64.b64decode(str_frame.encode('utf-8'))
# This puts the decoded image into a buffer so that I don't need to save
# it to disk to use it in PIL
byte_stream = io.BytesIO(b64decoded_frame)
# Open the image and convert it to 8-bit greyscale (mono8)
img = Image.open(byte_stream).convert('L')
# Get the 8-bit pixel value
pixel_val = img.getpixel((pos['x'], pos['y']))
# Convert the 8-bit pixel value to 16-bit by holding the rations
# i.e. n8 / (2^8 - 1) == x16 / (2^16 - 1)
pixel_val = int(pixel_val / 255 * 65535)