OpenCV 비전 실무16장 · AI 데이터 정제와 데이터 증강8 / 21← 이전목차다음 →MetaContents

16장. AI 데이터 정제와 데이터 증강

크기와 형식 맞추기

도시락 가게는 반찬을 칸이 정해진 용기에 담습니다. 큰 반찬은 잘라 넣고, 작은 반찬은 빈 곳이 남아도 그대로 둡니다. 용기마다 같은 자리에 같은 이름표를 붙이고, 같은 포장지로 쌉니다. 그래야 배달하는 사람이 헷갈리지 않습니다. 학습용 사진도 크기, 이름, 형식을 하나로 맞춥니다.

채널 셋, 레터박스, 이름 규칙, png 저장의 네 단계 흐름도

그림의 네 단계가 맞추는 순서입니다. 흑백과 투명 채널 그림을 컬러로 맞추고, 14장에서 만든 레터박스로 128×128 에 담고, 클래스_번호.png 꼴로 이름을 지어, png 로 저장합니다. 여기서 정해진 칸의 용기가 128×128, 빈 곳이 레터박스의 회색 여백, 이름표가 파일 이름 규칙, 포장지가 png 형식입니다.

맞출 것과 이 장의 약속

맞출 것이 장의 약속까닭
채널3 (BGR)모델에 넣는 배열의 모양이 같아야 한다
크기128×128, 레터박스, 여백 회색 (128, 128, 128)과일이 찌그러지지 않고 잘리지도 않는다(14장)
이름클래스_번호.png, 번호는 세 자리(apple_001.png)이름만 봐도 라벨을 알고, 이름순 정렬이 번호순과 같다
형식png저장할 때 값이 바뀌지 않는다(2장). jpg 는 저장할 때마다 조금씩 바뀐다
폴더train/클래스/, test/클래스/학습용과 시험용을 섞지 않는다

짧은 예시

Python
import cv2

GRAY = (128, 128, 128)   # 여백 색: 모든 사진에 같게 쓴다(14차시)

def letterbox(img, size=128, color=GRAY):
    """긴 변을 size 에 맞춰 비율대로 줄이고, 모자란 칸을 양쪽에 나눠 덧댄다(14차시와 같다)."""
    h, w = img.shape[:2]
    scale = size / max(h, w)
    nw, nh = round(w * scale), round(h * scale)
    small = cv2.resize(img, (nw, nh), interpolation=cv2.INTER_AREA)
    top, left = (size - nh) // 2, (size - nw) // 2
    return cv2.copyMakeBorder(small, top, size - nh - top, left, size - nw - left,
                              cv2.BORDER_CONSTANT, value=color)

img = cv2.imread("ch16_raw/apple_05.png")      # 세로로 긴 사진
print(img.shape, "→", letterbox(img).shape)    # 결과: (240, 180, 3) → (128, 128, 3)

# 이름 규칙: 클래스와 세 자리 번호. :03d 는 "빈 앞자리를 0 으로 채운 세 자리 정수"
print([f"apple_{k:03d}.png" for k in (1, 2, 10)])   # 결과: ['apple_001.png', 'apple_002.png', 'apple_010.png']

apple_05.png 는 가로 180, 세로 240 이라, 긴 변(세로)을 128 에 맞추면 가로가 96 이 되고 양옆에 16칸씩 회색 여백이 붙습니다. 번호를 세 자리로 쓰면 apple_010 이 apple_002 뒤에 옵니다. 그냥 apple_10 으로 쓰면 이름순으로 apple_1 과 apple_2 사이에 끼어 순서가 헷갈립니다.

주의할 점

  • 크기를 맞추는 일은 거르기가 끝난 뒤에 합니다. 흐림 점수는 원래 크기에서 재야 정확하고, 작은 사진을 128 로 키운 뒤에는 "너무 작다"를 알 수 없습니다.
  • 여기서는 사진이 수십 장이라 for 반복으로 충분합니다. 폴더가 여럿이고 사진이 수천 장이면 17장에서 일괄 처리 도구로 다듬습니다.
← 이전 절16장 · 같은 사진 찾기다음 절 →16장 · 데이터 증강이란