OpenCV 비전 실무19장 · Vision 데이터 파이프라인4 / 21← 이전목차다음 →MetaContents

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"보고

짧은 예시

Python
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__ 은 함수의 이름 글자입니다. 함수도 파이썬에서는 값이라 목록에 넣고 꺼내 부를 수 있습니다. 두 함수가 같은 꼴(항목 목록, 기록)을 받고 같은 꼴(항목 목록)을 돌려주므로 순서를 바꾸거나 새 단계를 끼워 넣어도 반복문은 그대로입니다.

주의할 점

  • 한 함수가 여러 일을 하면(거르면서 밝기도 고치면) 어느 쪽에서 문제가 났는지 찾기 어렵습니다. 기록의 "단계" 칸이 뜻을 잃습니다.
  • 단계 함수 안에서 원래 그림 배열을 바꾸지 않습니다. 다듬기에서 고친 그림은 새 배열로 만들어 돌려줍니다. 그래야 다듬기 전후를 견줄 수 있습니다.
← 이전 절19장 · 파이프라인이란다음 절 →19장 · 수집 단계