OpenCV – imread で画像の読み込み、imwrite で画像を保存をする方法

目次

概要

OpenCV で cv2.imread() で画像を読み込む、cv2.imwrite() で画像を出力する方法について解説します。

cv2.imread – 画像を読み込む

retval = cv2.imread(filename[, flags])
引数
filename str
ファイル名
flags ImreadModes cv2.IMREAD_COLOR
読み込み方法
返り値
名前 説明
retval 読み込んだ画像

sample.jpg

In [1]:
import cv2
import numpy as np
from IPython.display import Image, display
from matplotlib import pyplot as plt


def imshow(img):
    """ndarray 配列をインラインで Notebook 上に表示する。
    """
    ret, encoded = cv2.imencode(".jpg", img)
    display(Image(encoded))


# 画像を読み込む。
img = cv2.imread("sample.jpg")

画像の読み込みに失敗した場合

なんらかの理由で読み込みに失敗した場合は、エラーにはならず、None が返ります。 その場合、その後の処理でエラーになってしまうので、cv2.imread() の返り値は None でないことを必ずチェックするようにしましょう。

後続の処理でよくあるエラー例

error: OpenCV(4.2.0) /io/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'
In [2]:
img = cv2.imread("not_found.jpg")
assert img is not None, "読み込みに失敗しました"
AssertionErrorTraceback (most recent call last) <ipython-input-5-fa7e58a9b743> in <module> 1 img = cv2.imread(“not_found.jpg”) —-> 2 assert img is not None, “読み込みに失敗しました” AssertionError: 読み込みに失敗しました

読み込みに失敗した場合のチェック項目

  • ファイルパスが間違っていないかどうか
    • os.path.abspath() で絶対パスを確認し、そこに画像ファイルがあることを確認する
    • ファイルパスが raw 文字列になっているかどうか (Windows の場合)
  • ファイルパスに日本語など2バイト文字が含まれていないかどうか
    • 2バイト文字が含まれる場合、読み込みに失敗する場合があります

読み込みに失敗する要因として、一番多いのはファイルパスが間違っている場合です。相対パスで指定する場合は、カレントパスがどこになっているか、カレントパスを基準に正しく画像があるパスを指定できているかを os モジュールを使って確認しましょう。

以下の場合、カレントパスは /data/notebook/pystyle/opencv/opencv-imread-imwrite になっていて、相対パス sample.jpg を絶対パスに直した /data/notebook/pystyle/opencv/opencv-imread-imwrite/sample.jpg に画像ファイルが存在していなければならないことを意味します。

In [3]:
import os

filepath = "sample.jpg"

print("カレントパス", os.getcwd())
print("filepath が指す絶対パス", os.path.abspath(filepath))
print("ファイルが存在するかどうか", os.path.isfile(filepath))
カレントパス /data/notebook/pystyle/opencv/opencv-imread-imwrite
filepath が指す絶対パス /data/notebook/pystyle/opencv/opencv-imread-imwrite/sample.jpg
ファイルが存在するかどうか True

Windows の場合、ファイルパスの区切り文字 \ はエスケープが必要です。r"<ファイルパス>" として raw 文字列を使いましょう。

filepath = r"C:\Users\hoge\Desktop\sample.jpg"

flags – 読み込み方法を設定する

デフォルトでは、元画像が1チャンネルや4チャンネルであっても、読み込んだ際に3チャンネル画像に変換されます。flags 引数でこの挙動を制御できます。例えば、アルファチャンネル付きの透過 png を読み込む場合は、cv2.IMREAD_UNCHANGED を指定します。

In [4]:
# グレースケール形式で読み込む場合
img = cv2.imread("sample.jpg", flags=cv2.IMREAD_GRAYSCALE)
print(img.shape)  # (225, 300)

# BGR 形式で読み込む場合 (デフォルト)
img = cv2.imread("sample.jpg", flags=cv2.IMREAD_COLOR)
print(img.shape)  # (225, 300, 3)

# 元データのまま読み込む場合
img = cv2.imread("sample.jpg", flags=cv2.IMREAD_UNCHANGED)
print(img.shape)  # (239, 200, 4)
(356, 500)
(356, 500, 3)
(356, 500, 3)

cv2.imwrite – 画像を出力する

retval = cv2.imwrite(filename, img[, params])
引数
filename str
ファイル名
img ndarray
保存する画像
params list of int list()
パラメータ
返り値
名前 説明
retval 出力に成功したかどうか
In [5]:
# 画像を書き込む。
ret = cv2.imwrite("output.jpg", img)
assert ret, "出力に失敗"

cv2.imencode – 画像をエンコードする

画像をファイルに保存する代わりにバイト列に変換する場合は cv2.imencode を使用します。 返り値は成功したかどうかを表す retval とバイト列 buf になります。buf は uint8 型の ndarray です。

In [6]:
# jpg 形式にエンコードする。
retval, buf = cv2.imencode(".png", img)
print(buf.shape, buf.dtype)  # (26736, 1) uint8
(222570, 1) uint8

cv2.imdecode – 画像をデコードする

jpgpng のバイナリデータを表すバイト列をデコードして画像にするには、cv2.imdecode を使用します。バイナリデータを表す uint8 型の1次元の ndarray 配列を渡します。

In [7]:
# jpg 形式からデコードする。
img = cv2.imdecode(buf, cv2.IMREAD_UNCHANGED)
print(img.shape, img.dtype)  # (239, 200, 4) uint8
(356, 500, 3) uint8

コメント

コメントする

目次