19장. Vision 데이터 파이프라인
단계를 함수로 나누기
식당 주방은 칸이 나뉘어 있습니다. 채소 손질 칸, 굽는 칸, 담는 칸이 따로 있고, 칸 사이에는 같은 크기의 쟁반이 오갑니다. 굽는 사람은 채소를 어떻게 손질했는지 몰라도, 쟁반에 무엇이 올라오는지만 알면 됩니다. 단계를 함수로 나누는 것도 같습니다. 함수 하나가 칸 하나이고, 함수 사이를 오가는 자료가 쟁반입니다.
그림의 네 카드가 이 장에서 단계 함수를 만들 때 지키는 약속입니다. 첫째, 거르기 함수는 거르기만 하고 그림을 고치지 않습니다. 둘째, 모든 단계는 "항목 사전의 목록"을 받아 같은 꼴의 목록을 돌려줍니다. 셋째, 항목을 빼면 왜 뺐는지 기록에 남깁니다. 넷째, 단계 함수들을 목록에 넣고 for 로 차례로 부릅니다. 여기서 주방의 칸이 단계 함수, 쟁반이 항목 사전, 주문표에 적는 메모가 처리 기록입니다. 비유와 다른 점은, 주방은 손님마다 쟁반을 따로 보내지만 이 장의 함수는 쟁반 전부(목록)를 한꺼번에 받는다는 것입니다.
항목 사전에 담는 것
| 열쇠 | 넣는 단계 | 값의 예 | 쓰는 곳 |
|---|---|---|---|
file | 수집 | "belt_004.png" | 기록과 보고의 이름 |
source | 수집 | "ch19_incoming/belt_004.png" | 그림 읽기 |
img | 거르기 | 그림 배열 (240, 320, 3) | 다듬기, 추론 |
mean, blur | 거르기 | 43.4, 46.2 | 다듬기의 판단, 보고 |
scale | 다듬기 | 1.0 또는 0.5 | 상자를 원래 좌표로 되돌리기 |
notes | 다듬기 | "감마 0.7" | 보고 |
짧은 예시
import numpy as np
# 가짜 항목 세 개: 보통 밝기, 아주 어두움, 읽지 못함(None)
items = [
{"file": "a.png", "img": np.full((240, 320, 3), 70, np.uint8)},
{"file": "b.png", "img": np.full((240, 320, 3), 20, np.uint8)},
{"file": "c.png", "img": None},
]
def stage_read(items, log):
"""읽지 못한 항목을 뺀다. 뺀 까닭은 log 에 적는다."""
kept = []
for it in items:
if it["img"] is None:
log.append((it["file"], "읽기", "깨짐"))
else:
kept.append(it)
return kept
def stage_dark(items, log):
"""평균 밝기가 30 보다 낮은 항목을 뺀다."""
kept = []
for it in items:
mean = float(it["img"].mean())
if mean < 30:
log.append((it["file"], "밝기", f"아주 어두움({mean:.0f})"))
else:
kept.append(it)
return kept
# 단계 함수를 목록에 넣고 차례로 부른다: 앞 단계의 출력이 다음 단계의 입력
log = []
for stage in [stage_read, stage_dark]:
items = stage(items, log)
print(stage.__name__, "뒤 남은 항목:", [it["file"] for it in items])
print(log)
# 결과: stage_read 뒤 남은 항목: ['a.png', 'b.png']
# stage_dark 뒤 남은 항목: ['a.png']
# [('c.png', '읽기', '깨짐'), ('b.png', '밝기', '아주 어두움(20)')]stage.__name__ 은 함수의 이름 글자입니다. 함수도 파이썬에서는 값이라 목록에 넣고 꺼내 부를 수 있습니다. 두 함수가 같은 꼴(항목 목록, 기록)을 받고 같은 꼴(항목 목록)을 돌려주므로 순서를 바꾸거나 새 단계를 끼워 넣어도 반복문은 그대로입니다.
주의할 점
- 한 함수가 여러 일을 하면(거르면서 밝기도 고치면) 어느 쪽에서 문제가 났는지 찾기 어렵습니다. 기록의 "단계" 칸이 뜻을 잃습니다.
- 단계 함수 안에서 원래 그림 배열을 바꾸지 않습니다. 다듬기에서 고친 그림은 새 배열로 만들어 돌려줍니다. 그래야 다듬기 전후를 견줄 수 있습니다.