TL;DR
이 글은 단일 카메라에서 보행수·고유 방문자 수·영역 체류 시간을 동시에 산출하는 Roboflow Workflows 파이프라인을 구축하는 튜토리얼이다. RF-DETR로 사람을 검출하고 ByteTrack으로 persistent ID를 부여하며 Time in Zone 블록이 폴리곤 내부의 체류 시간을 ID별로 누적한다. 핵심 구성은 검출 파라미터(IoU 0.3, confidence 0.5 등)와 트래커 설정(Min IoU 0.4, 연속 프레임 2, Lost Buffer 60)이며, 로그 저장과 주기적 재학습으로 프로덕션 안정성을 확보해야 한다.
섹션별 상세

- 튜토리얼이 사용한 데이터셋은 5,917개의 보행자 이미지를 포함한다. — 본문의 Dataset 섹션과 이미지 캡처에 데이터셋 이미지 수와 분할(4,142/1,183/592)이 명시되어 있음. 모델 학습 요약 박스에 숫자가 표기됨. 출처



- 학습 설정은 512×512 해상도, 최대 100 epochs, Roboflow RF-DETR (Small) 아키텍처를 사용했다. — Train RF-DETR 섹션과 Training Summary 스크린샷에 모델 아키텍처, 해상도, epoch 수가 기재되어 있음. 출처


- 파이프라인은 RF-DETR로 검출하고 ByteTrack으로 persistent ID를 부여한 뒤 Time in Zone 블록이 영역별 체류 시간을 출력한다. — Build the Workflow 섹션과 파이프라인 다이어그램에 각 블록의 역할과 데이터 흐름(검출→트래킹→시간 누적)이 표시되어 있음. 출처
- 누적 카운트는 비디오별로 seen_tracker_ids_by_video를 유지해 스트림 간 집계가 섞이지 않도록 구현했다. — 튜토리얼에 포함된 Python 코드(run 함수)에서 video_metadata로 video_key를 추출해 스트림별 세트를 유지하는 로직이 포함되어 있음. 출처
용어 해설
- 체류 시간(Dwell Time)
- — 체류 시간은 사람이 정의한 폴리곤 영역에 머문 프레임 수를 초 단위로 환산한 지표로, 감지→트래킹→영역 진입·이탈 이벤트를 기반으로 시작 프레임과 종료 프레임을 계산하여 각 개인의 체류를 측정한다. 이 값은 단순 보행수보다 구매 관심이나 병목 여부를 판단하는 데 유용하다. 구현상 트래커의 persistent ID와 영역 기준(예: BOTTOM_CENTER 트리거)이 정확해야 신뢰할 수 있다.
- 존 분석(Zone Analytics)
- — 존 분석은 특정 카메라 뷰의 폴리곤 영역을 기준으로 점유 상태·체류 기간·동시 점유자 수 등 집계 값을 산출하는 계층으로, 감지 결과와 트래커 출력, 시간 누적 로직을 결합해 영역 단위 인사이트를 생성한다. 운영에서는 폴리곤 좌표와 레이블 오버레이, 로그 저장이 함께 사용된다. 존 좌표가 카메라 관측 각도에 맞춰 설정되어야 정확한 비교가 가능하다.
- 추적자 ID(Tracker ID)
- — 추적자 ID는 ByteTrack 같은 멀티 오브젝트 트래커가 프레임 간 객체 일치를 통해 할당하는 영구 식별자이며, 이 ID를 키로 누적 카운트와 영상별 집계(비디오 키)를 분리해 여러 스트림을 동시에 처리할 수 있다. ID는 정수화해 세트에 저장하고 비디오별 키로 분리하는 방식이 권장된다. ID 손실·중복을 줄이려면 IoU·연속 프레임 임계값을 적절히 조정해야 한다.
- ByteTrack
- — ByteTrack은 객체 검출 출력(박스·스코어)을 입력으로 받아 프레임 간 매칭 규칙(IoU, 최소 연속 프레임 등)으로 트랙을 유지하는 트래킹 방법으로, 트랙 생성·소멸·재식별을 처리해 각 사람에 persistent ID를 부여한다. 실무에서는 Track Activation Threshold, Minimum IoU, Lost Track Buffer 같은 파라미터로 민감도를 조절한다. 트래커 성능이 누적 카운트와 체류 시간 정확도에 직접적인 영향을 준다.
- RF-DETR (Small)(Roboflow RF-DETR (Small))
- — RF-DETR (Small)은 Roboflow 환경에서 제공되는 DETR 계열의 객체검출 아키텍처 변형으로, COCO 벤치마크에서 균형 잡힌 정확도와 추론 속도를 목표로 설계되어 소형 이미지 크기에서 빠르게 수렴한다. 본 튜토리얼은 512×512 해상도와 최대 100 epochs(조기 중단 가능)으로 학습해 검증·테스트 분할을 확인했다. 실전 배포 시 더 큰 사이즈나 추가 학습 데이터로 성능을 향상시킬 수 있다.
코드 예제
def run(self, image, detections):
if not hasattr(self, 'seen_tracker_ids_by_video'):
self.seen_tracker_ids_by_video = {}
video_key = 'default'
try:
video_metadata = getattr(image, 'video_metadata', None)
if isinstance(video_metadata, dict):
video_key = str(
video_metadata.get('video_identifier') or video_metadata.get('source_id') or video_metadata.get('run_id') or 'default'
)
elif video_metadata is not None:
video_key = str(
getattr(video_metadata, 'video_identifier', None)
or getattr(video_metadata, 'source_id', None)
or getattr(video_metadata, 'run_id', None)
or 'default'
)
except Exception:
video_key = 'default'
seen = self.seen_tracker_ids_by_video.setdefault(video_key, set())
tracker_ids = getattr(detections, 'tracker_id', None)
if tracker_ids is not None:
for tracker_id in tracker_ids:
if tracker_id is None:
continue
try:
tracker_id_int = int(tracker_id)
except Exception:
continue
if tracker_id_int >= 0:
seen.add(tracker_id_int)
return {'count': int(len(seen))}이 코드는 비디오 소스별로 관찰한 tracker ID의 집합을 유지해 전체 고유 방문자 수를 반환하는 역할을 한다. 입력으로 들어오는 image의 video_metadata에서 스트림 키를 추출하고, detections의 tracker_id들을 정수로 변환해 해당 스트림의 집합에 추가한다. 이 방식은 여러 카메라를 동시에 운용할 때 스트림별 합계가 섞이지 않도록 분리하는 구현적 장치를 제공한다.
기술
- RF-DETR
- ByteTrack
- Roboflow Workflows
- Python
활용 사례
- 리테일 매대의 체류 기반 성과 측정 및 진열 최적화
- 대기열 모니터링으로 오픈 카운터 시점 판단
- 공간 점유(Occupancy) 감시 및 용량 초과 알림
- 제한 구역 체류 감지로 보안 이벤트 트리거
AI 요약 · 북마크 · 개인 피드 설정 — 무료
출처 · 인용 안내
인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.