web-dev-qa-db-ja.com

OpenCv pythonライブラリを使用して、メモリからbase 64でエンコードされた画像を読み取ります

私は、ウェブカメラストリームから顔認識を行うアプリを開発しています。 canvasの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">_

公式ドキュメント は、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)
_

上記のコードスニペットは機能し、画像ファイルは適切に生成されます。しかし、私はそれほど多くのFile IO操作は、ストリームのすべてのフレームに対してこれを行うことを考えると実行可能であるとは思いません。メモリに直接イメージを読み取れるようにしたいので、 imgオブジェクト。

一部の人に効果があると思われる2つの解決策を試しました。

  1. PILの使用 参照

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

    _cv2_モジュールとして使用できるopenCV3がインストールされているため、cvが定義されていません。私はimg = cv2.imdecode(npImage,0)を試しましたが、これは何も返しません。

  2. デコードされた文字列からバイトを取得し、それを並べ替えの派手な配列に変換する

    _file_bytes = numpy.asarray(bytearray(imgdata), dtype=numpy.uint8)
    img = cv2.imdecode(file_bytes, 0) #Here as well I get returned nothing
    _

ドキュメントでは、imdecode関数の戻り値については触れていません。ただし、発生したエラーから、_numpy array_またはscalarが最初の引数として期待されていると思います。メモリ内のそのイメージのハンドルを取得して、cv2.imshow('image',img)およびその後のあらゆる種類の優れた機能を実行する方法を教えてください。

私は自分自身を明確にすることができたと思います。

18
Vivek Pradhan

次のように、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)
8
Jonno_FTW

これは私にとってはうまくいき、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)
22
Lior

これは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

このソリューションがすべての人に役立つことを願っています

16
Javier Vallejos