콘텐츠로 이동

CycleSequenceMonitor

실시간 사이클 순서 모니터입니다. InferenceHandler 내부에서 자동으로 동작하며, 각 사이클을 하나씩 받아 기대 순서와 비교하고 이탈 시 알림을 생성합니다.

Note: CycleResultVerifier(배치 검증 API)는 제거되었습니다. 순서 모니터링은 InferenceHandler.get_cycles() 내부에서 자동으로 수행됩니다.

개요

학습 시 훈련 데이터로부터 기대 클래스 순서(expected_class_sequence)가 자동 추출되어 체크포인트에 저장됩니다. 추론 시 InferenceHandler.build()에서 체크포인트를 로드하면 CycleSequenceMonitor가 자동으로 생성되며, get_cycles() 호출 시 각 사이클에 아래 필드가 추가됩니다:

필드 타입 설명
sequence_status str \| None "ok" (정상) 또는 "duplicate" (중복)
expected_class_index int \| None 해당 시점에서 기대하던 class index
sequence_missing list[int] \| None 이 사이클 도착까지 건너뛴 class index 목록 (미검)

동작 원리

expected_sequence = (1, 2, 6, 9, 7, 10, 8)
                     ↑ cursor

입력: class_index=1 → ok  (cursor → 2)
입력: class_index=6 → ok  (cursor → 9, missing=[2])
입력: class_index=99 → duplicate (시퀀스에 없는 클래스)

판단 기준

케이스 상태 설명
cursor 위치의 기대값과 일치 ok 정상 진행
기대 시퀀스의 이후 위치에 존재 ok + missing 건너뛴 클래스들이 missing으로 보고
기대 시퀀스에 없는 클래스 duplicate 중복
이미 지나간 위치의 클래스 duplicate 중복/중복
첫 번째 기대 클래스 재등장 새 super-cycle 시작 이전 cycle의 남은 expected → missing

Super-cycle 순환

한 바퀴(super-cycle)가 끝나면 커서가 자동으로 처음으로 돌아갑니다. 첫 번째 기대 클래스가 중간에 다시 나타나면, 이전 super-cycle을 마무리하고 새 cycle을 시작합니다.

InferenceHandler에서의 사용

별도 설정 없이 자동으로 동작합니다.

on/off 제어

# 현재 상태 확인
error, message, enabled = handler.get_inference_option("sequence_monitor_enabled")

# 비활성화
handler.set_inference_option("sequence_monitor_enabled", False)

# 다시 활성화
handler.set_inference_option("sequence_monitor_enabled", True)

get_cycles() 결과 예시

error, message, cycles = handler.get_cycles()
for cycle in cycles:
    for ci in cycle.get("cycle_info", []):
        print(
            f"class={ci['class_id']}, "
            f"status={ci['sequence_status']}, "
            f"expected={ci['expected_class_index']}, "
            f"missing={ci['sequence_missing']}"
        )

출력 예시:

class=1,  status=ok,       expected=1,  missing=[]
class=6,  status=ok,       expected=2,  missing=[2]     # class 2 미검
class=99, status=duplicate, expected=9,  missing=[]       # 중복
class=9,  status=ok,       expected=9,  missing=[]

모듈 단독 사용

InferenceHandler 없이 직접 사용할 수도 있습니다.

생성

from cycle_counter.modules.sequence_monitor.sequence_monitor import CycleSequenceMonitor

# 직접 생성
v = CycleSequenceMonitor(expected_sequence=(1, 2, 6, 9, 7, 10, 8))

# config dict에서 생성 (InferenceHandler 내부 방식)
v = CycleSequenceMonitor.build({"expected_class_sequence": [1, 2, 6, 9, 7, 10, 8]})

사이클 처리

result = v.process_cycle(class_index=1)
# {'status': 'ok', 'expected_class_index': 1, 'missing_class_indices': []}

result = v.process_cycle(class_index=6)
# {'status': 'ok', 'expected_class_index': 2, 'missing_class_indices': [2]}

finalize / reset

# 영상 종료 시 남은 미검 회수
missing = v.finalize()  # e.g. [9, 7, 10, 8]

# 수동 커서 초기화
v.reset()

에러 코드

코드 에러 클래스 설명
350 EmptyExpectedSequenceError 빈 시퀀스로 생성 시도
351 MissingExpectedSequenceConfigError config에 시퀀스 키가 없음

Demo

전체 예시는 demo/demo_cycle_sequence_monitor.py를 참고하세요.

python demo/demo_cycle_sequence_monitor.py