概要
Python OpenCV で日本語を含むファイルパスを扱う際の以下2点の問題への対処方法の案.
- cv2.imread でファイルパスに日本語を含む画像を読み込もうとすると失敗する.
- 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
参考リンク
- Reading and Writing Images — OpenCV 3.0.0-dev documentation:
- numpy.fromfile — NumPy v1.13 Manual:
- numpy.ndarray.tofile — NumPy v1.13 Manual: