Ultralytics YOLO27: 대기자 명단에 등록하세요.
Get Started
컴퓨터 비전 기초·문제 정의하기·레슨 1/10
강의초급

문제 정의하기

막연한 제품 아이디어를 세 줄짜리 작업 명세로 구체화하고, 재학습 없이 변경할 수 있도록 비즈니스 규칙을 코드에 둡니다.

햇빛이 비치는 도시 교차로를 위에서 본 장면으로, 보행자, 자전거 이용자, 버스, 자동차에 Ultralytics YOLO 박스가 표시되어 있습니다.

중단되는 컴퓨터 비전 프로젝트 대부분은 명확한 질문에서 시작하지 않았습니다. “위험한 행동 감지”는 요구사항처럼 들리지만, 주석 작업자는 라벨을 지정할 수 없고, 모델은 이를 학습할 수 없으며, 누구도 제대로 작동하는지 판단할 수 없습니다. 세 줄짜리 명세를 작성하면 반나절 만에 이 문제를 해결할 수 있으며, 학습할 작업, 라벨링할 대상, 보고할 지표도 결정할 수 있습니다.

학습 성과

세 줄짜리 작업 명세(입력, 출력, 결정)를 작성하고, YOLO26 출력을 읽는 코드로 결정을 구현합니다.

속성 과정
이미 사용법을 알고 계신다면, 간단히 요약해 드리겠습니다.
  1. 입력: 소스, 해상도, 프레임 속도, 장면입니다.

  2. 출력: 동사가 아닌 데이터 유형입니다. 라벨, 박스, 마스크, 키포인트 또는 픽셀별 맵이 해당합니다.

  3. 결정: 누가, 언제, 어떤 규칙에 따라 조치하는지입니다.

  4. 출력 행은 모델이 담당합니다. 결정 행은 재학습 없이 변경할 수 있는 코드입니다.

  5. 규칙을 신뢰하기 전에 실제 출력으로 테스트합니다. 이미지에서 겹쳐 보인다고 실제로 가까운 것은 아닙니다.

실습형

명세를 먼저 작성해야 하는 이유#

컴퓨터 비전 프로젝트의 0~4단계: 기반 마련, 데이터 수집 및 준비, 특징 엔지니어링 및 모델 개발, 모델 배포, 모델 모니터링

컴퓨터 비전 프로젝트의 모든 단계는 0단계에서 정한 목표를 이어받습니다. 모호한 질문은 모호한 데이터셋과 의견이 일치하지 않는 주석 작업자, 잘못된 대상을 측정하는 지표를 낳으며, 2단계에서 아무리 학습해도 이를 바로잡을 수 없습니다.

세 줄#

작업 명세는 세 문장으로 구성되며 한 줄에 하나씩 작성합니다. 각 문장은 프로젝트에 참여하는 서로 다른 담당자가 할 질문에 답합니다.

행답하는 질문미흡한 예좋은 예
입력모델은 무엇을 보나요?“카메라 영상”“천장 카메라 12대에서 초당 5프레임으로 촬영한 1920×1080 프레임”
출력어떤 데이터가 반환되나요?“안전 문제 감지”“forklift 및 person의 박스와 각각의 신뢰도 점수”
결정누가 언제 조치하나요?“안전 개선”“지게차와 사람이 2초 동안 2m 이내에 있으면 교대 근무 감독자에게 알림”

출력 행은 작업을 결정하는 데이터 유형을 지정하므로 가장 세심하게 작성해야 합니다.

나란히 표시된 Ultralytics YOLO의 7가지 작업 출력: 탐지, 포즈, 분할, 분류, OBB, 시맨틱 분할, 깊이

이미지 전체에 하나의 라벨을 지정하면 분류, 박스를 사용하면 탐지, 윤곽선을 사용하면 분할, 관절을 사용하면 포즈, 회전 박스를 사용하면 OBB, 픽셀별 클래스나 거리를 사용하면 시맨틱 분할 또는 깊이입니다. 다음 강의에서 7가지 작업을 모두 살펴봅니다.

예제: 모델과 규칙 분리하기#

“창고 바닥에서 지게차가 위험한 행동을 하는 시점을 알고 싶습니다.”

이 문장은 작업이 아니라 프로젝트를 설명합니다. 두 가지 역할을 하나로 섞고 있습니다. 지게차와 사람을 찾는 것은 픽셀에 관한 일이고, 위험한 행동의 기준을 정하는 것은 정책에 관한 일입니다. 다음처럼 분리합니다.

탐지기만 모델입니다. 마름모는 일반 코드입니다. 지금 바로 이 분리 방식을 시험해 볼 수 있습니다. bus.jpg에는 지게차가 없지만, 버스 한 대와 사람 네 명으로 같은 테스트를 할 수 있습니다. 첫 규칙은 “사람 박스가 차량 박스와 30% 넘게 겹치면 알림”입니다.

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]

# The model's job ends here: a class, a box, and a confidence per object.
people = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "person"]
vehicles = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "bus"]

def share_inside(a, b):
    """Fraction of box a's area that lies inside box b."""
    w = max(0, min(a[2], b[2]) - max(a[0], b[0]))
    h = max(0, min(a[3], b[3]) - max(a[1], b[1]))
    return w * h / ((a[2] - a[0]) * (a[3] - a[1]))

# The decision rule is plain code: change the policy without retraining.
ALERT_SHARE = 0.30
for person in people:
    share = max(share_inside(person, v) for v in vehicles)
    print(f"person at x={person[0]:3.0f}: {share:4.0%} inside the bus box -> {'ALERT' if share > ALERT_SHARE else 'ok'}")
person at x= 49:  70% inside the bus box -> ALERT
person at x=223:  76% inside the bus box -> ALERT
person at x=670:  70% inside the bus box -> ALERT
person at x=  0:  62% inside the bus box -> ALERT

알림은 네 번 발생했지만 모두 오탐입니다. 사람들은 주차된 버스 앞쪽 보도에 있습니다. 탐지기는 모든 박스를 정확히 찾았지만 규칙은 잘못되었습니다. 2D 이미지에서 겹쳐 보인다고 실제 세계에서 두 대상이 가까운 것은 아니기 때문입니다. 규칙은 코드이므로 코드로 수정할 수 있습니다. 각 사람의 발이 지면에 닿는 위치를 버스의 바퀴선과 비교합니다.

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]
people = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "person"]
vehicles = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "bus"]

def same_ground_line(person, vehicle, tolerance=40):
    """True when the person's feet are level with the vehicle's wheels and inside its width."""
    feet_x, feet_y = (person[0] + person[2]) / 2, person[3]
    return vehicle[0] < feet_x < vehicle[2] and abs(feet_y - vehicle[3]) < tolerance

for person in people:
    alert = any(same_ground_line(person, v) for v in vehicles)
    print(f"person at x={person[0]:3.0f}: feet y={person[3]:.0f}, bus wheels y={vehicles[0][3]:.0f} -> {'ALERT' if alert else 'ok'}")
person at x= 49: feet y=902, bus wheels y=751 -> ok
person at x=223: feet y=861, bus wheels y=751 -> ok
person at x=670: feet y=880, bus wheels y=751 -> ok
person at x=  0: feet y=871, bus wheels y=751 -> ok

모든 사람의 발은 바퀴선보다 110~150픽셀 아래에 있으므로 버스보다 카메라에 더 가까이 서 있습니다. 재학습도 재라벨링도 필요하지 않습니다. 탐지기는 그대로 두고 안전팀이 규칙을 반복 개선합니다. 프로덕션 버전에서는 보정된 카메라를 사용해 발 위치를 바닥 좌표로 변환하고 객체 추적을 통해 2초 지속 조건을 추가할 수 있습니다. 이 경우에도 같은 박스 위에 코드만 추가하면 됩니다.

정책을 모델에서 분리하세요

주관적인 표현인 "안전하지 않음", "결함 있음", "의심스러움", "VIP"는 모델 출력을 읽는 코드에 두어야 합니다. 모델은 픽셀에 관한 질문에 답합니다. 두 전문가가 라벨을 두고 의견이 다를 수 있다면, 버전 관리와 테스트가 가능하고 변경할 수 있는 규칙에 그 판단을 두어야 합니다.

주의할 점#

출력은 동작을 나타내야 합니다

증상: 사양에 "안전 문제 감지" 또는 "장면 이해"라고 적혀 있어 어노테이터가 무엇을 그려야 하는지 묻습니다. 해결: 출력을 이름이 지정된 클래스를 포함하는 데이터 유형으로 다시 작성합니다. 예: "forklift 및 person의 박스".

가리킬 수 없는 클래스

증상: suspicious_behavior 또는 dangerous 같은 클래스를 같은 프레임에서 두 어노테이터가 서로 다르게 라벨링합니다. 해결: 제한 구역 안에 있는 사람이나 열린 상태로 고정된 문처럼 눈에 보이는 증거로 대체하고, 판단은 의사결정 규칙으로 옮깁니다.

출력이 문장이나 예측인 경우

증상: "무슨 일이 일어나고 있는지 설명"(캡셔닝) 또는 "지게차가 누군가를 칠지 예측"(예측)합니다. 해결: 먼저 객체의 위치를 찾은 다음, 그 위에 트래킹 및 동작 규칙을 추가합니다. 예측에 앞서 디텍터를 구축합니다.

명세에서 성공 기준으로#

명세는 모델이 무엇을 하는지 정의하지만, 어느 정도면 충분한지 또는 미탐이 오탐보다 얼마나 더 큰 비용을 초래하는지는 다루지 않습니다. Building High-Performance YOLO Datasets의 비즈니스 목표부터 시작하기에서는 명세를 측정 가능한 목표로 구체화합니다. 이 과정의 이후 모든 강의는 여러분이 작성한 세 줄을 참조합니다.

사용해 보기

자신의 프로젝트 또는 빈 선반 공간을 표시해야 하는 매장 카메라를 대상으로 세 줄짜리 명세를 작성합니다. 각 줄은 한 문장으로 작성합니다. 그런 다음 결정 행에서 모델이 픽셀만으로는 볼 수 없는 단어를 모두 나열하고, 모델 출력에 적용할 한 줄 규칙으로 결정을 작성합니다(의사 코드도 괜찮습니다).

완료 조건
다음 조건을 모두 충족하면 레슨을 완료한 것입니다.
  • 입력 행에 소스, 해상도, 프레임 속도를 명시합니다.

  • 출력 행에는 동사가 아닌 명명된 클래스가 포함된 데이터 유형을 지정합니다.

  • 출력에 적용할 규칙으로 결정을 작성하고, 주관적인 단어는 모두 클래스 이름이 아니라 규칙에 둡니다.

정답 보기

선반 카메라의 명세 예시:

  • 입력: 한 통로를 향해 고정된 카메라에서 60초마다 촬영하는 1920×1080 정지 이미지입니다.
  • 출력: product 및 empty_facing(제품이 없는 선반 칸)의 바운딩 박스와 각각의 신뢰도 점수입니다.
  • 결정: 매장 영업 시간 중 동일한 선반에서 empty_facing 박스가 3개 이상 연속 5장의 정지 이미지에 나타나면 재고 보충 작업을 생성합니다.

모델이 볼 수 없는 단어는 재고 보충 작업, 동일한 선반, 연속 5장의 이미지에 나타남, 매장 영업 시간입니다. 규칙으로 작성하면 다음과 같습니다.

if count(empty_facing on shelf S) >= 3 in each of the last 5 stills and store_is_open(now):
    create_restock_task(shelf=S)

매장은 이미지 하나도 다시 라벨링하지 않고 “3”, “5” 또는 영업 시간을 변경할 수 있습니다.

다음 단계

다음 내용에서는 Ultralytics YOLO가 지원하는 7가지 작업과 출력 행을 그중 하나에 정확히 연결하는 방법을 살펴봅니다.