ソースに絡まるエスカルゴ

貧弱プログラマの外部記憶装置です。

【python/OpenCV】OpenCVのimread関数で扱うパスに全角を含めてはいけない

 タイトルにもありますが、OpenCVのimread関数で画像を読み込もうとしたらエラーになってずっと割と躓いてしまったので、今回はその備忘録になります。
 詳しくは参考資料に挙げているページ様を参照してください。


 では、始めます。


1:OpenCVのimread関数の引数のパスに全角が入っているとエラーになる
 まずはエラーを再現するために、以下のソースコードをコピペして保存してみてください。

・imread_test.py

#-*- coding:utf-8 -*-
import os, sys
import cv2

my_dir_path = os.path.abspath(os.path.dirname(sys.argv[0]))
my_file_path = my_dir_path + "\\テスト.png"

print(my_file_path) # パスの表示

frame = cv2.imread(my_file_path) # 画像取得

 保存出来たらソースファイルと同じ階層に「テスト.png」という画像を作成して保存します。

 そしてソースコードを実行すると以下のようなエラーになります。

$ python imread_test.py
C:\xxxx\テスト.png
[ WARN:0@0.015] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('C:\xxxx\テスト.png'): can't open/read file: check file path/integrity

 Windowsの場合だと文字化けしているかもしれませんが、同じようにエラーになるかと思います。

 読み込むファイルパスのどこかに一つでも「全角文字」があると発生するので、絶対に全角が入らないパスが来るという前提以外はimread関数で画像を読み込むのはやめた方が良いようです。

 ちなみにファイルを保存する時に使う関数「imwrite」ではエラーが出ないことがありますが、全角文字部分が文字化けして正しく動かない場合があります。


2:imread関数を使わずに画像を読み込む・保存する
 ではどうやって画像を読み込み、保存するかという話ですが、Pillowで画像を開きNumPyへ変換してその後OpenCVの画像形式に変更します。保存はこの逆の手順を行います。

 具体的には以下のようにします。

・pillow_numpy.py

#-*- coding:utf-8 -*-
import os, sys

import cv2
import numpy as np
from PIL import Image

my_dir_path = os.path.abspath(os.path.dirname(sys.argv[0]))
my_file_path = my_dir_path + "\\テスト.png"
print(my_file_path) # パスの表示

# Pillowで画像を開いてNumpyへ変換
img_org = np.array(Image.open(my_file_path))

# OpenCVの形式に変換
cv2_img = cv2.cvtColor(img_org, cv2.COLOR_BGR2RGB)

# 全角を含むファイル名で保存
pil_img = Image.fromarray(cv2.cvtColor(cv2_img, cv2.COLOR_BGR2RGB))
pil_img.save(my_dir_path + "\\てすと.png")

 上記を実行すると今度はエラーなく画像が読み込まれ、保存ファイル名も指定した全角文字のものになります。

 この他にも色々と手順はあるので、詳しくは参考資料に挙げているページ様を参照してください。


 以上がOpenCVで画像を読み込んだり保存したりする際の注意点になります。

 今までたまたま意図せず全角文字が入らない状態で使っていたので気づきませんでしたが、パスに全角が入っているとエラーになるというのはなかなかのトラップだと思いました。
 外国では全角を使わないところが多いので、パスに全角が入る場合があるというのに対応してないのかもしれないですね…。


・参考資料