はじめに
PythonのOpenCVでファイルを開くときに、パスに日本語が混ざっていると開けません。
対処方法として
-
cv2.imdecode()を使う - ファイルの名前を一時的に変える
- ファイルのコピーを作り、それを開く
- ファイルのシンボリックリンクを作り、それを開く
- Pillowで開いて変換する
等があります。
これらをそれぞれ作ってみます。
1が一番有効だと思いますが、cv2.imreadanimation()で読み込みたい場合にどうすれば良いか困ってしまいました。
その場合は、Pillowで読んで変換しましたが。
2は、データが壊れても問題ないならば使えますが、元データを破壊する恐れがあるので使い道が限られます。
3は、ちょっと無駄が多いです。
4は、管理者権限などが必要なので、状況次第で使えません。
5は、変換を間違えると情報が欠落する恐れがあります。
特に、透過ファイルなどの場合は、問題になるかもしれません。
環境
py -3.13 -VV
Python 3.13.11 (tags/v3.13.11:6278944, Dec 5 2025, 16:26:58) [MSC v.1944 64 bit (AMD64)]
py -3.13 -m pip list
numpy 2.2.6
opencv-contrib-python 4.12.0.88
opencv-python 4.12.0.88
pillow 12.0.0
regex 2025.11.3
コード
import pathlib
import shutil
import uuid
import cv2
import numpy as np
import regex
from PIL import Image
# convert PIL to CV
def pilToCv(image):
work = image.copy()
if image.mode == "P":
work = image.convert("RGBA") if image.info.get("transparency", None) is not None else image.convert("RGB")
newImage = np.array(work, dtype=np.uint8)
if newImage.ndim == 2: # モノクロ
pass
elif newImage.shape[2] == 3: # カラー
newImage = cv2.cvtColor(newImage, cv2.COLOR_RGB2BGR)
elif newImage.shape[2] == 4: # 透過
newImage = cv2.cvtColor(newImage, cv2.COLOR_RGBA2BGRA)
return newImage
ReJapanese = regex.compile(r"[\p{sc=Han}\p{sc=Hiragana}\p{Katakana}]+")
def readImage1(path):
if not path.is_file():
return None
return cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
def readImage2(path):
if not path.is_file():
return None
name = str(path.absolute())
path = path.rename(f"{uuid.uuid4()}.temp")
image = cv2.imread(path, cv2.IMREAD_UNCHANGED)
path.rename(name)
return image
def readImage3(path):
if not path.is_file():
return None
name = str(path)
if ReJapanese.search(name) is not None:
temp = pathlib.Path(f"{uuid.uuid4()}.temp")
name = shutil.copy(path, temp)
image = cv2.imread(name, cv2.IMREAD_UNCHANGED)
temp.unlink()
return image
def readImage4(path):
if not path.is_file():
return None
symlink = pathlib.Path(f"{uuid.uuid4()}.temp")
symlink.symlink_to(path)
image = cv2.imread(symlink, cv2.IMREAD_UNCHANGED)
symlink.unlink()
return image
def readImage5(path):
if not path.is_file():
return None
image = Image.open(path)
return pilToCv(image)
if __name__ == "__main__":
output = pathlib.Path(r".\Output")
output.mkdir(exist_ok=True)
paths = [
pathlib.Path(r".\テスト\1.webp"),
pathlib.Path(r".\テスト\2.png"),
]
for path in paths:
image = readImage1(path)
cv2.imwrite(output.joinpath(f"readImage1_{path.name}"), image)
image = readImage2(path)
cv2.imwrite(output.joinpath(f"readImage2_{path.name}"), image)
image = readImage3(path)
cv2.imwrite(output.joinpath(f"readImage3_{path.name}"), image)
image = readImage4(path)
cv2.imwrite(output.joinpath(f"readImage4_{path.name}"), image)
image = readImage5(path)
cv2.imwrite(output.joinpath(f"readImage5_{path.name}"), image)
cv2.imreadanimation()の代わり
def readAnimation(path):
if not path.is_file():
return None
with path.open("rb") as file:
buf = np.frombuffer(file.read(), dtype=np.uint8).reshape(1, -1)
success, animation = cv2.imdecodeanimation(buf)
if not success:
return None
return animation