使用OpenCv python库从内存中读取基本64位编码图像

Viv*_*han 15 python base64 encoding opencv numpy

我正在开发一个应用程序,可以从网络摄像头流中进行面部识别.我得到了画布的base64编码数据uri,并希望用它来做这样的事情:

cv2.imshow('image',img)
Run Code Online (Sandbox Code Playgroud)

数据URI看起来像这样:

 data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7
Run Code Online (Sandbox Code Playgroud)

所以,为了清楚起见,我已经显示了图像的样子,因此base64字符串没有被破坏.

<img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7">
Run Code Online (Sandbox Code Playgroud)

官方文档说,是imread接受作为参数的文件路径.从这个 SO答案,如果我这样做:

 import base64
 imgdata = base64.b64decode(imgstring) #I use imgdata as this variable itself in references below
 filename = 'some_image.jpg'
 with open(filename, 'wb') as f:
    f.write(imgdata)
Run Code Online (Sandbox Code Playgroud)

上面的代码片段可以正常工作,并且可以正确生成图像文件.但是,我不认为这么多文件IO操作是可行的,因为我会为流的每一帧执行此操作.我希望能够将图像直接读入内存中创建img对象.

我尝试了两种似乎适用于某些人的解决方案.

  1. 使用PIL 参考:

    pilImage = Image.open(StringIO(imgdata))
    npImage = np.array(pilImage)
    matImage = cv.fromarray(npImage)
    
    Run Code Online (Sandbox Code Playgroud)

    cv没有定义,因为我安装了openCV3,我可以将其作为cv2模块使用.我试过img = cv2.imdecode(npImage,0),这什么都没有.

  2. 从解码的字符串中获取字节并将其转换为numpy数组

    file_bytes = numpy.asarray(bytearray(imgdata), dtype=numpy.uint8)
    img = cv2.imdecode(file_bytes, 0) #Here as well I get returned nothing
    
    Run Code Online (Sandbox Code Playgroud)

文档没有真正提到imdecode函数返回的内容.但是,从我遇到的错误中,我猜它是期望a numpy array或a scalar作为第一个参数.如何在内存中处理该图像,以便我可以做cv2.imshow('image',img)以及之后的各种酷炫的东西.

我希望我能够清楚自己.

Lio*_*ior 20

这对我有用,并且不需要PIL /枕头或任何其他依赖项(cv2除外):

import cv2
import numpy as np

def data_uri_to_cv2_img(uri):
    encoded_data = uri.split(',')[1]
    nparr = np.fromstring(encoded_data.decode('base64'), np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    return img

data_uri = "data:image/jpeg;base64,/9j/4AAQ..."
img = data_uri_to_cv2_img(data_uri)
cv2.imshow(img)
Run Code Online (Sandbox Code Playgroud)

  • 如果返回类型(img)我得到NoneType.似乎cv2.imdecode(nparr,cv2.IMREAD_COLOR)不能按原样工作 (5认同)
  • 你救了我的命 !我(不得不)在AWS上使用Python 2,第一个解决方案一直给我一个错误:/sf/ask/1975841591/ 4合功能cvcvtcolor (2认同)

小智 13

这是我为python 3.7而不使用PIL的解决方案

import base64

def readb64(uri):
   encoded_data = uri.split(',')[1]
   nparr = np.fromstring(base64.b64decode(encoded_data), np.uint8)
   img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
   return img
Run Code Online (Sandbox Code Playgroud)

我希望这个解决方案适用于所有人

  • base64.b64decode 返回一个字节数组,因此我使用 np.frombuffer(...) 而不是 np.fromstring(...) (4认同)

Jon*_*FTW 8

你可以像这样使用cv2和枕头:

import base64
from PIL import Image
import cv2
from StringIO import StringIO
import numpy as np

def readb64(base64_string):
    sbuf = StringIO()
    sbuf.write(base64.b64decode(base64_string))
    pimg = Image.open(sbuf)
    return cv2.cvtColor(np.array(pimg), cv2.COLOR_RGB2BGR)

cvimg = readb64('R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7')
cv2.imshow(cvimg)
Run Code Online (Sandbox Code Playgroud)

  • 你好,我正在运行这段代码,但它抛出:第 9 行,在 readb64 sbuf.write(base64.b64decode(base64_string)) 类型错误:需要字符串参数,得到“字节”如何解决这个问题? (2认同)