16장. AI 데이터 정제와 데이터 증강
너무 어둡거나 밝은 사진
마트에서 과일을 고를 때, 조금 덜 익은 바나나는 사 와서 며칠 두면 먹을 수 있지만 까맣게 짓무른 바나나는 버립니다. 사진의 밝기 문제도 둘로 나뉩니다. 조금 어두운 사진은 5장에서 배운 보정으로 살릴 수 있지만, 거의 새까맣거나 하얗게 날아간 사진은 모양 정보가 지워져 살릴 것이 없습니다.
그림의 세 상자가 이 장의 판정입니다. 4장 프로젝트의 판정표에서 "어두움"과 "밝음" 두 줄을 그대로 가져오고, 어두운 사진을 다시 둘로 나눴습니다. 평균이 40 미만이면 버리고, 40 이상 80 미만이면 5장의 정규화로 고칩니다. 여기서 덜 익은 바나나가 고칠 사진이고, 짓무른 바나나가 버릴 사진입니다.
왼쪽 귤 사진은 평균 23.9 로 거의 검은색입니다. 둘째 라임 사진은 평균 62.7 로 어둡지만, 셋째처럼 cv2.normalize 로 늘리면 평균 141.6 이 되어 다른 사진과 비슷해집니다. 맨 오른쪽 라임은 평균 228.5 로 하얗게 날아가 과일의 테두리가 거의 보이지 않습니다.
이 장의 밝기 판정표
| 순서 | 판정 | 조건 | 처리 |
|---|---|---|---|
| 1 | 아주 어두움 | 평균 밝기 40 미만 | 버림 |
| 2 | 어두움 | 평균 밝기 80 미만이거나 아주 어두운 칸(50 미만) 비율 0.4 초과 | 정규화로 고침 |
| 3 | 밝음 | 평균 밝기 175 초과이거나 아주 밝은 칸(205 초과) 비율 0.4 초과 | 버림 |
| 4 | 정상 | 위의 어디에도 맞지 않음 | 그대로 |
4장의 판정표에는 "대비 낮음(표준편차 35 미만)" 줄도 있었습니다. 이 장의 과일 사진은 바탕이 고른 식탁보라 정상 사진도 표준편차가 30 안팎으로 나와서, 그 줄은 쓰지 않았습니다. 기준값은 다른 데이터에서 그대로 가져오지 말고, 지금 데이터의 숫자를 한 번 훑어본 뒤 정합니다.
짧은 예시
import cv2
for name in ["tangerine_10.png", "lime_10.png", "lime_11.png", "lime_01.png"]:
# 실습과 같게 컬러로 읽어 cvtColor 로 흑백을 만든다
gray = cv2.cvtColor(cv2.imread(f"ch16_raw/{name}"), cv2.COLOR_BGR2GRAY)
mean = round(float(gray.mean()), 1)
bright = round(float((gray > 205).mean()), 3) # 아주 밝은 칸 비율(4차시)
print(name, mean, bright)
# 결과: tangerine_10.png 23.9 0.0
# lime_10.png 62.7 0.0
# lime_11.png 228.5 1.0
# lime_01.png 168.6 0.123
# 조금 어두운 사진은 정규화(5차시)로 가장 어두운 칸을 0, 가장 밝은 칸을 255 로 늘린다
dim = cv2.imread("ch16_raw/lime_10.png")
fixed = cv2.normalize(dim, None, 0, 255, cv2.NORM_MINMAX)
print(round(float(cv2.cvtColor(fixed, cv2.COLOR_BGR2GRAY).mean()), 1)) # 결과: 141.6NORM_MINMAX 는 normalize min-max 로, 가장 작은 값과 가장 큰 값을 정한 범위의 양 끝에 맞춰 늘립니다. 5장에서 본 정규화입니다.
주의할 점
- 하얗게 날아간 사진은 고치기 어렵습니다. 255 로 꽉 찬 칸은 원래 밝기가 240 이었는지 300 이었는지 알 수 없어서, 어둡게 만들어도 회색 덩어리가 될 뿐입니다.
- 원래 어두운 장면(밤 풍경)을 모으는 데이터라면 어둡다는 이유로 버리면 안 됩니다. 판정표는 "이 묶음에서 이상한 사진"을 고르는 도구이고, 기준은 데이터의 쓰임에 맞춰 정합니다.