LoginSignup
6
2

More than 3 years have passed since last update.

Python OpenCV で日本語を含むパス及びファイルが読み取れない問題

Last updated at Posted at 2021-02-26

OpenCVでは日本語のパスに対応していない!?

 cv2.VideoCaptureを普通に実行していると普通に動いたが、pyinstallerでexe化すると文字化けしてエラーが出てしまった。(違いがよくわからないが)調べてみるとOpenCVではANSI文字列以外、つまり日本語のパスに対応していない模様。なのでcv2.imread, cv2.imwrite, cv2.VideoCapture等で日本語を含むパスを指定するには工夫が必要。
  こちらではnumpyを噛ませて解決してましたが、なんか難しそうだしcv2.VideoCaptureでのやり方もよくわからない。こちらでファイルをリネームすればいいというのを採用。

解決方法

対象ファイルのディレクトリに移動して、一時的に対象ファイルの名前を変更して処理する。

コード例(cv2.imread

  1. 対象ファイルがあるディレクトリに移動
  2. 対象ファイルの名前を変更
  3. 対象ファイルを読み取る
  4. 対象ファイルの名前を戻す
import cv2
import os

def imread(path):
    tmp_dir = os.getcwd()
    # 1. 対象ファイルがあるディレクトリに移動
    if len(path.split("/")) > 1:
        file_dir = "/".join(path.split("/")[:-1])
        os.chdir(file_dir)
    # 2. 対象ファイルの名前を変更
    tmp_name = "tmp_name"
    os.rename(path.split("/")[-1], tmp_name)
    # 3. 対象ファイルを読み取る
    img = cv2.imread(tmp_name)
    # 4. 対象ファイルの名前を戻す
    os.rename(tmp_name, path.split("/")[-1])
    # カレントディレクトリをもとに戻す
    os.chdir(tmp_dir)
    return img

 はじめにos.getcwd()でカレントディレクトリを取得、最後に戻す。その後対象ファイルが存在するディレクトリに移動するが、すでにそのディレクトリにいる場合は何もしない。os.chdir(path)でpathディレクトリに移動できる。

コード例(cv2.imwrite

 cv2.imwriteで画像を保存するときは
1. 保存するディレクトリに移動
2. 対象ファイルを保存
3. 対象ファイルの名前を戻す
とするとよい

import cv2
import os

def imwrite(path, img):
    tmp_dir = os.getcwd()
    # 1. 保存するディレクトリに移動
    if len(path.split("/")) > 1:
        file_dir = "/".join(path.split("/")[:-1])
        os.chdir(file_dir)
    # 2. 対象ファイルを保存
    tmp_name = "tmp_name.png"
    cv2.imwrite(tmp_name, img)
    # 3. 対象ファイルの名前を戻す
    if os.path.exists(path.split("/")[-1]):  # ファイルが既にあれば削除
        os.remove(path.split("/")[-1])
    os.rename(tmp_name, path.split("/")[-1])
    # カレントディレクトリをもとに戻す
    os.chdir(tmp_dir)

cv2.imwriteではデフォルトで既存の画像を上書きするのでこちらもその仕様にした。存在するファイルの名前に変更することはできないので、存在する場合は削除してから名前を変更するようにした。

コード例(cv2.VideoCapture

 cv2.VideoCaptureの場合は少し注意が必要。ファイルを読み取った後cap.release()としないと名前を変えることはできないので、処理が終わった後に名前を戻す。それにより関数化ができない。

  1. 対象ファイルがあるディレクトリに移動
  2. 対象ファイルの名前を変更
  3. 対象ファイルを読み取る
  4. 対象ファイルの名前を戻す
import cv2
import os

path = "C:/Users/***/Desktop/フォルダ/画像.bmp"

# 1. 対象ファイルがあるディレクトリに移動
file_dir = "/".join(path.split("/")[:-1])
os.chdir(file_dir)
# 2. 対象ファイルの名前を変更
tmp_name = "tmp_name"
os.rename(path.split("/")[-1], tmp_name)
# 3. 対象ファイルを読み取る
cap = cv2.VideoCapture(tmp_name)
'''
任意の処理
'''
# 4. 対象ファイルの名前を戻す
cap.release()
os.rename(tmp_name, path.split("/")[-1])

cap.release()しないと

PermissionError: [WinError 32] プロセスはファイルにアクセスできません。別のプロセスが使用中です。

というエラーが出るので注意。プログラムで使用中だから

もうちょいくわしく

エラー挙動

 cv2.imreadを日本語を含むパスを指定した場合の挙動を確認

import cv2

path = "C:/Users/sd18080/Desktop/フォルダ/画像.bmp"
img = cv2.imread(path)
print(img)

結果

None

エラーすら表示されない…!
OpenCVではそもそも存在しないファイルを参照しようとしてもエラーが出ないよう。
試しに上記をpath="aaaaa"と適当に存在しないファイルを設定した場合も同様の結果となった。

cv2.VideoCaptureのエラー挙動

cv2.VideoCaptureは存在しないファイルを指定するとエラーが表示される

import cv2

path = "C:/Users/***/Desktop/フォルダ/画像.bmp"
cap = cv2.VideoCapture(path)

これを実行すると

warning: Error opening file (/build/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp:908)
warning: C:\Users\***\Desktop\繝輔か繝ォ繝\逕サ蜒・bmp (/build/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp:909)
[ERROR:0] VIDEOIO(cvCreateFileCapture_Images(filename.c_str())): raised OpenCV exception:

OpenCV(3.4.8) C:\projects\opencv-python\opencv\modules\videoio\src\cap_images.cpp:246: 
error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file):
 C:\Users\***\Desktop\繝輔か繝ォ繝€\逕サ蜒・bmp in function 'cv::icvExtractPattern'

となってどうやら文字コードUTF-8→Shift_JISに文字化けしているみたい。

最後に

 numpyかませる方法がよくわからない、こっちのほうが簡単って思ってまとめました。参考になれば幸いです。
 cv2.VideoCaptureに関しては日本語が入っているときも普通に読み込めることがあって挙動が安定しなくて「?」という感じです。自分はpythonで実行したときには普通に読み込めたがpyinstallerでexe化したものを実行したらエラーが出ました。pyinstallerを実行する時にUnicodeDecodeErrorで'utf-8'がどうちゃらっていうエラーが出ててそれをこちらのようにライブラリを書き換えるという力技をしたせいだと思ったので沼りました。この記事のようにすれば万事解決です。
 cv2.VideoCaptureは日本語でも大丈夫なことがあるということについてなにか分かる人がいれば教えてくれれば幸いです。

参考

[1] Python OpenCV の cv2.imread 及び cv2.imwrite で日本語を含むファイルパスを取り扱う際の問題への対処について - Qiita, 2018, https://qiita.com/SKYS/items/cbde3775e2143cad7455,
[2] Python - imwriteでのファイル名の文字化け|teratail, 2020, https://teratail.com/questions/268813,
[3] pythonスクリプトをexeに変換する(つまづきポイントまとめ) - Qiita, 2018, https://qiita.com/pocket_kyoto/items/80a1ac0e46819d90737f,

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2