Help us understand the problem. What is going on with this article?

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

参考リンク

SKYS
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away