회사에서 데이터 증강에 대한 방법을 강구하던 중 opencv를 사용할 일이 많은데 한글 경로 사용 중 문제를 일으키는 일이 잦아 관련된 문제를 해결한 방법에 대해서 포스팅 해보려고 합니다.
1. OpenCV란?
OpenCV(Open Source Computer Vision Library)는 컴퓨터 비전과 이미지 처리를 위한 대표적인 오픈소스 라이브러리입니다. 1999년 인텔(Intel)의 Gary Bradski가 처음 개발했고, 인텔 내부 프로젝트로 시작해 이후 오픈소스로 공개되었습니다. 인텔에서 개발하였고 CUDA 지원 및 딥러닝과의 결합을 통해 다양한 플랫폼에서 사용되고 컴퓨터 비전 분야 딥러닝과의 연계를 계속 강화하고 있습니다.
https://opencv.org/
Home
OpenCV provides a real-time optimized Computer Vision library, tools, and hardware. It also supports model execution for Machine Learning (ML) and Artificial Intelligence (AI).
opencv.org
2. cv2.imread(), cv2.imwrite()의 한글 경로 문제
Windows에서 OpenCV의 cv2.imread()와 cv2.imwrite() 함수는 내부적으로 C/C++ 기반의 파일 입출력 방식을 사용합니다. 이 방식은 UTF-8
로 인코딩된 한글 경로를 제대로 처리하지 못하기 때문에 한글이 포함된 경로에서 읽거나 저장하는 작업이 실패하는 경우가 많습니다.
2-1. cv2.imread() 문제
# 예시
img = cv2.imread(h_path)
h, w = img.shape[:2]
with open(label_path, 'r') as f:
labels = [line.strip().split() for line in f.readlines()]
이 코드에서 그대로 h_path로 한글이 포함된 경로를 읽게 한다면 다음과 같은 로그가 출력되는 것을 볼 수 있습니다.
img = cv2.imread(h_path)
h, w = img.shape[:2]
AttributeError: 'NoneType' object has no attribute 'shape'
cv2.imread()
가 이미지를 불러오지 못해서 img=None
이 되었고, 그 상태에서 .shape
를 호출하려다가 에러가 난 것입니다.
cv::findDecoder imread_('C:\Users\hgk24\OneDrive\諛뷀깢 ?
"바탕 화면"이라는 글자가 깨지면서 발생한 문제인데 경로상에 한글이 들어가서 그렇습니다.
그래서 cv2.imread() 대신 cv2.imdecode()를 사용하는 함수를 직접 만들어서 사용합니다.
2-2. 🎯 대체 함수 사용
import cv2
import numpy as np
def imread_unicode(path):
data = np.fromfile(path, dtype=np.uint8)
return cv2.imdecode(data, cv2.IMREAD_COLOR)
imread_unicode() 함수를 사용하면 한글 경로가 있어도 깨짐 없이 경로 읽기가 가능합니다.
# 예시
img = imread_unicode(h_path) # cv2.imread() 대체
h, w = img.shape[:2]
with open(label_path, 'r') as f:
labels = [line.strip().split() for line in f.readlines()]
2-3. cv2.imwrite() 문제
cv2.imwrite() 함수도 cv2.imread() 함수처럼 내부적으로 파일이름이 UTF-8이 아니면 실패하거나 None 처리될 수 있습니다. 그래서 폴더 경로를 영문명으로 변경해주거나 영어이름으로 된 임시 디렉토리를 만들어서 파일을 저장 후 옮겨주는 방법을 사용할 수 있는데 그렇게 하지말고 함수를 만들어 사용하면 이러한 불편함을 피할 수 있습니다.
아래와 같이 작성되어 있는 경우(예시) 새로운 함수를 추가하여 변경해 줍니다.
# 예시
if new_labels:
out_img = os.path.join(output_img_dir, f"aug_{idx}.jpg")
out_lbl = os.path.join(output_lbl_dir, f"aug_{idx}.txt")
cv2.imwrite(out_img, pasted)
with open(out_lbl, 'w') as f:
f.write('\n'.join(new_labels))
idx += 1
2-4. 🎯 대체 함수 사용
cv2.imencode() + np.frombuffer() + np.tofile()
를 조합하여 만든 imwrite_unicode()
함수를 사용합니다.
def imwrite_unicode(path, image):
ext = os.path.splitext(path)[1]
success, encoded_img = cv2.imencode(ext, image)
if success:
with open(path, mode='wb') as f:
encoded_img.tofile(f)
return True
return False
# 예시
if new_labels:
out_img = os.path.join(output_img_dir, f"aug_{idx}.jpg")
out_lbl = os.path.join(output_lbl_dir, f"aug_{idx}.txt")
print(f"[{idx}] ✅ saved {len(new_labels)} objects at {out_img}")
imwrite_unicode(out_img, pasted) # cv2.imwrite() 대체
with open(out_lbl, 'w') as f:
f.write('\n'.join(new_labels))
idx += 1
위와 같이 사용하여 cv2.imwrite()를 대체하면 됩니다.
이렇게 cv2.imread(), cv2.imwrite() 사용 대신 한글 경로를 사용 할 수 있는 대체 함수에 대해서 알아보았습니다.
'[컴퓨터비전]' 카테고리의 다른 글
[컴퓨터비전] YOLOv8 기본 증강 ON/OFF (1) | 2025.06.06 |
---|---|
[컴퓨터비전] editable mode 설정해서 git clone한 Ultralytics 라이브러리 커스텀하기 (0) | 2025.05.11 |
[컴퓨터비전] YOLOv8 객체 탐지 모델 학습 따라하기 (0) | 2025.04.18 |