Edited at

Python OpenCV の cv2.imread 及び cv2.imwrite で日本語を含むファイルパスを取り扱う際の問題への対処について

More than 1 year has passed since last update.


概要

Python OpenCV で日本語を含むファイルパスを扱う際の以下2点の問題への対処方法の案.


  1. cv2.imread でファイルパスに日本語を含む画像を読み込もうとすると失敗する.

  2. cv2.imwrite を実行した際にファイルパスに含まれる日本語が化ける.

私の環境に問題...?

→ umyu様に「Windows & OpenCV の問題」とコメントいただきました.

アスキー文字にしか対応していないみたい.

Unicode Path/Filename for imread and imwrite · Issue


Currently, the imread and imwrite method only supports std::string as an input. This isn't working with non-ascii directories/paths. Therefore, the a software depends on OpenCV can not guaranty working on all maschines.



実行環境


  • Windows 10 64bit

  • Python 3.6.3 :: Anaconda custom (64-bit)

  • OpenCV 3.3.0


対策案


cv2.imread への対策案

cv2.imread を np.fromfile + cv2.imdecode に分解して実行する.

import numpy as np

import cv2
def imread(filename, flags=cv2.IMREAD_COLOR, dtype=np.uint8):
try:
n = np.fromfile(filename, dtype)
img = cv2.imdecode(n, flags)
return img
except Exception as e:
print(e)
return None


cv2.imwrite への対策案

cv2.imwrite を cv2.imencode + np.ndarray.tofile に分解して実行する.

import numpy as np

import cv2
import os
def imwrite(filename, img, params=None):
try:
ext = os.path.splitext(filename)[1]
result, n = cv2.imencode(ext, img, params)

if result:
with open(filename, mode='w+b') as f:
n.tofile(f)
return True
else:
return False
except Exception as e:
print(e)
return False


#%% imread

# 通常imread,英語パス -> OK
path_english = r"C:\temp\Jelly beans.tiff"
img = cv2.imread(path_english)
type(img) # numpy.ndarray
img.size # 196608

# rename & copy file
import shutil
path_japanese = r"C:\temp\ジェリー ビーンズ.tiff"
shutil.copy(path_english, path_japanese)

# 通常imread,日本語パス -> NG
img = cv2.imread(path_japanese)
type(img) # NoneType

# 対策imread,日本語パス -> OK
img = imread(path_japanese)
type(img) # numpy.ndarray
img.size # 196608

#%% imwrite
# 通常imwrite,英語パス -> OK
path_english2 = r"C:\temp\Jelly beans.jpg"
cv2.imwrite(path_english2, img)

import os
os.path.exists(path_english2) # True

# 通常imwrite,日本語パス -> NG
path_japanese2 = r"C:\temp\Jelly ビーンズ.jpg"
cv2.imwrite(path_japanese2, img)

os.path.exists(path_japanese2) # False

import glob
glob.glob(r"C:\temp\*")
# ['C:\\temp\\Jelly beans.tiff',
# 'C:\\temp\\Jelly beans.jpg',
# 'C:\\temp\\Jelly 繝薙・繝ウ繧コ.jpg', # ← 文字化け
# 'C:\\temp\\ジェリー ビーンズ.tiff']

# 対策imwrite,日本語パス -> OK
imwrite(path_japanese2, img)
os.path.exists(path_japanese2) # True


参考リンク