ブログトップ

OpenCV でバイナリ形式の画像を扱う

Web 上の画像をダウンロードして画像処理する場合など、バイナリ形式の画像データを直接 OpenCV で扱う方法について説明します。

一度バイナリデータをローカルに保存してから cv2.imread() する方法ももちろんありますが、NumPy と OpenCV の関数を駆使すれば、保存にかかる処理を飛ばしてシンプルに画像を扱うことができます。

本記事のポイントは次の2点です。

Web からダウンロードした画像のバイナリデータを扱う

OpenCV と NumPy はインストールされているものとします。

まずは必要なモジュールを import します。

import urllib.request
import numpy as np
import cv2

画像をダウンロードします。urllib.request.Request() の引数は所望の URL に置き換えてください。 body に画像のバイナリデータが格納されます。

req = urllib.request.Request('<画像の URL>')
with urllib.request.urlopen(req) as res:
    body = res.read()

次に np.frombuffer() でバイナリデータを NumPy 配列(ndarray)に変換します。ただしこの段階では、配列の次元数が 1 となっており OpenCV で正常に扱える形ではないので、cv2.imdecode() で次元数と shape を整えます。

arr = np.frombuffer(body, dtype=np.uint8)
img = cv2.imdecode(arr, flags=cv2.IMREAD_COLOR)

shape を確認してみると次のようになります(画像によって結果は異なります)。

print(arr.shape)
# (110882,)
print(img.shape)
# (700, 1000, 3)

なお、cv2.imdecode() の引数 flags についてですが、BGR のカラー画像として扱う場合は flags=cv2.IMREAD_COLOR 、グレースケール画像として扱う場合は flags=cv2.IMREAD_GRAYSCALE を指定します(この flags の指定は cv2.imread() と同様です)。

これで OpenCV で扱える形になりました。試しに cv2.imshow() を使って画像を表示してみます。

cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Web の情報を漁ると Pillow (PIL) を使っている方法も見かけましたが、上記のように NumPy と OpenCV だけで実現できるので、わざわざこれだけのために Pillow をインストールする必要はありません。

全体のコード

import urllib.request
import numpy as np
import cv2

req = urllib.request.Request('<画像の URL>')
with urllib.request.urlopen(req) as res:
    body = res.read()

arr = np.frombuffer(body, dtype=np.uint8)
img = cv2.imdecode(arr, flags=cv2.IMREAD_COLOR)

cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
投稿日: 2020年10月16日