【问题标题】:Read a base 64 encoded image from memory using OpenCv python library使用 OpenCv python 库从内存中读取 base 64 编码图像
【发布时间】:2016-02-18 16:56:16
【问题描述】:

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

cv2.imshow('image',img)

数据 URI 如下所示:

 data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7

所以,为了清楚起见,我已经展示了图像的样子,因此 base64 字符串不会被破坏。

<img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7">

official doc 表示,imread 接受文件路径作为参数。从this 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)

上面的代码 sn-p 可以正常工作,并且可以正确生成图像文件。但是,考虑到我会为流的每一帧都这样做,我认为这么多文件 IO 操作是不可行的。我希望能够直接将图像读入内存,创建img 对象。

我尝试了两种似乎对某些人有效的解决方案。

  1. 使用 PIL reference:

    pilImage = Image.open(StringIO(imgdata))
    npImage = np.array(pilImage)
    matImage = cv.fromarray(npImage)
    

    我得到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
    

文档并没有真正提到imdecode 函数返回的内容。但是,根据我遇到的错误,我猜它期望 numpy arrayscalar 作为第一个参数。我如何在内存中处理该图像,以便我可以做cv2.imshow('image',img) 以及之后的各种很酷的事情。

我希望我能说清楚。

【问题讨论】:

  • 检查this
  • 感谢@Miki 的快速回复,但np.fromstring 也无法正常工作。
  • imgstring 将是图片网址,对吧?
  • @Divakar,它是代表该图像的 base64 编码字符串

标签: python opencv numpy encoding base64


【解决方案1】:

这是我对 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

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

【讨论】:

  • base64.b64decode 返回一个字节数组,所以我让它使用 np.frombuffer(...) 而不是 np.fromstring(...)
【解决方案2】:

你可以像这样同时使用 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)

【讨论】:

  • 嗨,我正在运行这段代码,但它正在抛出:第 9 行,在 readb64 中 sbuf.write(base64.b64decode(base64_string)) TypeError: string argument expected, got 'bytes' 如何解决这个问题?
  • @AbhilashRamteke 将 base64_string 更改为 base64_string.encode('ascii')
【解决方案3】:

这对我有用,不需要 PIL/pillow 或任何其他依赖项(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)

【讨论】:

  • 你救了我的命!我(有义务)在 AWS 上使用 Python 2,第一个解决方案一直给我这样的错误:stackoverflow.com/questions/28226308/…
  • 如果返回类型(img)我得到 NoneType。似乎 cv2.imdecode(nparr, cv2.IMREAD_COLOR) 无法正常工作
  • @JoePlatano 那么解决方案是什么?
猜你喜欢
  • 2019-11-12
  • 1970-01-01
  • 1970-01-01
  • 2019-02-16
  • 2012-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多