75

この記事は最終更新日から3年以上が経過しています。

@SKYS

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

概要

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

参考リンク

ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
SKYS

コメント

私の環境に問題...?

Windows & OpenCV の問題ですー。
Unicode Path/Filename for imread and imwrite

0

情報ありがとうございます.承知しました.

0

凄く助かりました!素晴らしいコードありがとうございます。

0

超助かりました!:thumbsup:

0
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
記事投稿イベント開催中
Azure IoTに関する記事を投稿しよう!
~
Qiita 10周年記念イベント - 10年前の自分に伝えたい、勉強しておきたかった技術
~