Skip to content

Inference

safety.InferenceHandler

학습한 Object Detection/Classification 모델을 사용하여 검사를 하기 위한 InferenceHandler class 입니다.

Usage

demo/inference.py 참고

build(config) classmethod

InferenceHandler class의 instance를 생성합니다.

Parameters:

Name Type Description Default
config Dict

InferenceHandler를 build 하기 위한 config가 담겨 있는 dictionary 입니다.

{
    # inference_handler config
    "detection_checkpoint_path": str | None, # Detection 모델 체크포인트 경로 (default None, None인 경우 기본 detection model 사용)
    "classification_checkpoint_path": str | None, # Classification 모델 체크포인트 경로 (default None, None인 경우 기본 classification model 사용)
    "reidentification_checkpoint_path": str | None, # Reidentification 모델 체크포인트 경로 (default None, None인 경우 기본 reidentification model 사용)
    "depth_checkpoint_path": str | None, # Depth, Normal, Intrinsic 모델 체크포인트 경로 (default None, None인 경우 기본 depth model 사용)
    "match_checkpoint_path": str | None, # Match 모델 체크포인트 경로 (default None, None인 경우 기본 match model 사용)
    "tracker_checkpoint_path": str | None, # Tracker 모델 체크포인트 경로 (default None, 명시적으로 None을 지정한 경우 기본 tracker 로직 사용)
    "segmentation_checkpoint_path": str | None, # 인양물 검사를 위한 Segmentation 모델 체크포인트 경로 (default None, None인 경우 기본 seg model 사용)
    "deid_enabled": bool, # 얼굴 비식별화 사용 여부 (default False). True면 기본 얼굴 모델을 로드합니다. face_detection_checkpoint_path를 명시하면 이 값과 무관하게 그 모델을 로드합니다 (다른 모델들과 같은 규칙).
    "face_detection_checkpoint_path": str | None, # 얼굴 검출 모델 체크포인트 경로 (default None, None이고 deid_enabled=True인 경우 기본 모델 사용)
    "payload_instability_enabled": bool, # Payload instability 검사 사용 여부, 여부에 따라서 SAM Model Load 여부가 결정됨 (default False)
    "inference_batch_size": int, # Batch size 설정 (default 1)
    "optimize": bool, # ONNX 모델 최적화 여부 (default True)
    "password": str | None,  # 체크포인트 패스워드 (default None)
    "device": str | int,  # GPU 번호 (int) or "cuda" (str) (default "cuda")

    # event_alarm_handlers config
    "camera_ids": list[int] | None, # 검사할 camera_id list. `InferenceHandler.register_camera`와 `InferenceHandler.release_camera`를 통해 camera_id를 등록/해제 할 수 있습니다. (default None)
}

required

Returns:

Name Type Description
InferenceHandler

build가 완료된 safety.InferenceHandler class의 instance를 반환합니다.

Note
  1. 각 테스크 모델의 경로({task}_checkpoint_path)가 None인 경우 해당 버전의 기본 모델을 사용합니다.
  2. default_alarm_options, default_object_options는 API에서 기본적으로 비활성화합니다. (즉, enabled가 False입니다.)
  3. Depth 모델에서 depth, normal, intrinsic을 모두 예측합니다.

infer(images, camera_ids, timestamps)

현재 설정된 inference 옵션을 바탕으로 inference를 수행합니다.

Parameters:

Name Type Description Default
images list[ndarray]

inference를 수행할 이미지들의 list (shape: [H, W, C])

required
camera_ids list[int]

images의 각 image에 대한 camera_id list

required
timestamps list[int]

images의 각 image에 대한 timestamp list (단위: 밀리초)

required

Returns:

Type Description
list[dict]

list[dict]: 검사 결과

[
    {
        "detected_objects": [ # 검출된 object들에 대한 정보 리스트
            {
                "id": int, # object ID
                "bounding_box": list[int], # object bounding box (x,y,w,h)
                "object_class": str, # object의 class 이름.
                "object_score": int, # object의 det score. (범위: 0 ~ 100)
                "classification_scores": {
                    "helmet": int,      # helmet class의 score. (범위: 0 ~ 100)
                    "head": int,        # head class의 score. (범위: 0 ~ 100)
                    "person": int,      # person class의 score. (범위: 0 ~ 100)
                    "fire": int,        # fire class의 score. (범위: 0 ~ 100)
                    "smoke": int,       # smoke class의 score. (범위: 0 ~ 100)
                    "fall_down": int,   # fall_down class의 score. (범위: 0 ~ 100)
                    "harness": int,     # harness class의 score. (범위: 0 ~ 100)
                    "trespass": int, # trespass_detect의 score. 객체 영역 대비 침입 영역과의 겹침 비율 (-1은 해당 없음.  범위: 0 ~ 100)
                    "in_danger_zone": int, # danger_detect의 score. 객체 영역 대비 침입 영역과의 겹침 비율 (-1은 해당 없음. 범위: 0 ~ 100)
                    "in_collision_hazard_zone": int, # in_collision_hazard_zone의 score, 객체 영역 대비 충돌 위험 영역과의 겹침 비율 (-1은 해당 없음. 범위: 0 ~ 100)
                    "collision_hazard": int, # collision_hazard_detect의 score. 객체 영역 대비 충돌 위험 영역과의 겹침 비율 (-1은 해당 없음. 범위: 0 ~ 100)
                    "crush_hazard": int, # crush_detect의 score. 객체 영역 대비 협착 위험 영역과의 겹침 비율 (-1은 해당 없음. 범위: 0 ~ 100)
                    "payload_instability": int, # payload instability의 score. (-1은 해당 없음. 범위: 0 ~ 100)
                    "aloft_work": int, # aloft_work_detect의 score. 지면으로부터의 높이를 score로 사용. (단위: cm, -1은 해당 없음. 범위: 0 이상의 정수)

                },
                "brightness_score": int, # object의 밝기 score. (범위: 0 ~ 100). Person class에 대해서만 존재.
                "movement_score": int,   # object의 움직임 score (범위: 0 ~ 100).
                "segmentation_contour": np.ndarray | None, # 적재 불량 검사에 사용되는 segmentation contour. None인 경우 segmentation 정보가 없는 상태입니다. 정보가 있는 경우, (N, 2) shape의 numpy array입니다.
                "depth": float | None, # object의 depth. None인 경우 depth 정보가 없는 상태입니다. 정보가 있는 경우, 0 이상의 실수입니다.
                "events": { # object에 발생한 event에 대한 딕셔너리. 각 event에 대한 alarm이 비활성화(enabled=False)된 경우엔 event도 항상 False입니다.
                    "without_helmet": bool,                                  # 헬멧 미착용 이벤트 (person object에 대해서만 해당)
                    "without_harness": bool,                                 # 하네스 미착용 이벤트 (person object에 대해서만 해당)
                    "fallen_person": bool,                                   # 쓰러짐 이벤트 (person object에 대해서만 해당)
                    "trespass_detect": bool,                                 # 침입 감지 이벤트 (person object에 대해서만 해당)
                    "danger_detect": bool,                                   # 배회 감지 이벤트 (person object에 대해서만 해당)
                    "in_collision_hazard_zone": bool,                        # 충돌 위험 영역 존재 유무 이벤트 (fire, smoke object 제외하고 모든 object에 대해서 해당)
                    "collision_hazard_detect": bool,                         # 충돌 위험 감지 이벤트 (person object에 대해서만 해당)
                    "crush_detect": bool,                                    # 협착 위험 감지 이벤트 (person object에 대해서만 해당)
                    "proximity_hazard_detect": bool,                         # 근접 위험 감지 이벤트 (person object에 대해서만 해당), use_depth=False인 경우 False를 반환합니다.
                    "fire_detect": bool,                                     # 화재 감지 이벤트 (fire object에 대해서만 해당)
                    "smoke_detect": bool,                                    # 연기 감지 이벤트 (smoke object에 대해서만 해당)
                    "payload_instability_detect": bool,                      # 적재 불량 감지 이벤트 (crane lifted object에 대해서만 해당)
                    "aloft_work_detect": bool,                               # 고소작업 감지 이벤트 (person object에 대해서만 해당). use_depth=False인 경우 False를 반환합니다.

                },
                "alarms": { # object에 발생한 각 event에 대해서 alarm 여부 딕셔너리.
                    "without_helmet": bool,             # 헬멧 미착용 이벤트 (person object에 대해서만 해당)
                    "without_harness": bool,            # 하네스 미착용 이벤트 (person object에 대해서만 해당)
                    "fallen_person": bool,              # 쓰러짐 이벤트 (person object에 대해서만 해당)
                    "trespass_detect": bool,            # 침입 감지 이벤트 (person object에 대해서만 해당)
                    "danger_detect": bool,              # 배회 감지 이벤트 (person object에 대해서만 해당)
                    "in_collision_hazard_zone": bool,   # 충돌 위험 영역 존재 유무 이벤트 (fire, smoke object 제외하고 모든 object에 대해서 해당)
                    "collision_hazard_detect": bool,    # 충돌 위험 감지 이벤트 (person object에 대해서만 해당)
                    "crush_detect": bool,               # 협착 위험 감지 이벤트 (person object에 대해서만 해당)
                    "proximity_hazard_detect": bool,    # 근접 위험 감지 이벤트 (person object에 대해서만 해당)
                    "fire_detect": bool,                # 화재 감지 이벤트 (fire object에 대해서만 해당)
                    "smoke_detect": bool,               # 연기 감지 이벤트 (smoke object에 대해서만 해당)
                    "payload_instability_detect": bool, # 적재 불량 감지 이벤트 (crane lifted object에 대해서만 해당)
                    "aloft_work_detect": bool,          # 고소작업 감지 이벤트 (person object에 대해서만 해당)
                },
                "event_status": {# object에 발생한 event의 중간 결과들에 대한 딕셔너리. 각 event에 대한 alarm이 비활성화(enabled=False)된 경우엔 None 입니다.
                    "without_helmet": str | None,              # 현재는 None 만 반환하고 있습니다.
                    "without_harness": str | None,             # 현재는 None 만 반환하고 있습니다.
                    "fallen_person": str | None,               # 현재는 None 만 반환하고 있습니다.
                    "trespass_detect":str | None,              # 현재는 None 만 반환하고 있습니다.
                    "danger_detect":str | None,                # 현재는 None 만 반환하고 있습니다.
                    "in_collision_hazard_zone": str | None,    # 현재는 None 만 반환하고 있습니다.
                    "collision_hazard_detect": str | None,     # 현재는 None 만 반환하고 있습니다.
                    "crush_detect": str | None,                # 현재는 None 만 반환하고 있습니다.
                    "proximity_hazard_detect": str | None,     # 근접 위험 감지 이벤트에서 사람 침입이 발생한 경우 "trespass" 그 외의 경우 None 입니다 (person object에 대해서만 해당).
                    "fire_detect": str | None,                 # 현재는 None 만 반환하고 있습니다.
                    "smoke_detect": str | None,                # 현재는 None 만 반환하고 있습니다.
                    "payload_instability_detect": str | None,  # 적재 불량 감지 이벤트에서 인양물의 크기가 충분히 크지 않은 경우 "size_insufficient" 그 외의 경우 None 입니다 (crane lifted object에 대해서만 해당).
                    "aloft_work_detect": str | None,           # 현재는 None 만 반환하고 있습니다.
                },
                "crush_hazard_zone": { # 객체의 협착 위험 영역 2D 폴리곤 좌표 배열. 협착 이벤트가 발생한 사람의 경우, 대응하는 객체의 위험 영역을 가집니다.
                    "object_zone": numpy.ndarray | None, # 객체의 2D 폴리곤 좌표 numpy 배열 (shape: [N, 2]) | None (공간 지각 기능을 사용하지 않는 경우엔 None)
                    "crush_hazard_zone": numpy.ndarray | None, # 협착 위험 영역의 2D 폴리곤 좌표 numpy 배열 (shape: [M, 2]) | None
                },
                "face": {
                    "bounding_box": list[int] | None, # face bounding box (x, y, w, h). 얼굴을 찾지 못한 경우 존재. 이 경우 None
                    "score": int | None, # face의 score. (범위: 0 ~ 100) 얼굴을 찾지 못한 경우 존재. 이 경우 None
                }, # deid가 켜진 경우 & 사람 객체인 경우만 존재
            }, ... # 각 image에서 검출된 object와 이에 대한 event, alarm 정보.
        ],
        "time": { # 해당 이미지의 추론에 소요된 시간을 담고있는 dictionary 입니다. (단위: 밀리초)
            "preprocess_time": float,       # 이미지 및 기타 전처리에 소요된 시간
            "postprocess_time": float,      # 기타 후처리에 소요된 시간
            "tracker_time": float,          # tracker에 소요된 시간
            "event_alarm_time": float,      # 이벤트 관제에 소요된 시간
            "detection_time": float,        # detection에 소요된 시간
            "classification_time": float,   # classification에 소요된 시간
            "reidentification_time": float, # person reidentification에 소요된 시간
            "segmentation_time": float,     # (인양물) segmentation에 소요된 시간

            # 아래 두 키는 해당 채널이 비식별화를 끈 경우 0 입니다 (한 일이 없습니다).
            "face_detection_time": float,   # 비식별화용 얼굴 검출에 소요된 시간
            "deidentification_time": float, # 가릴 영역으로 다듬는 데 소요된 시간 (후처리 + 시간축 평활)

            # 아래 키들은 공간지능 기능을 사용하는 경우에만 존재합니다.
            "depth_time": float,  # depth 추정에 소요된 시간
            "normal_time": float, # normal 추정에 소요된 시간
            "match_time": float,  # match 추정에 소요된 시간
            "calib_time": float,  # depth 보정에 소요된 시간
        },
    }, ... # 들어온 image 수 만큼 반복 (들어온 image 순서대로)
]

Note

얼굴 비식별화를 켠 카메라에서는 person 항목에 face 필드가 붙습니다. 그 bounding_box 를 가려주세요.

for obj in result["detected_objects"]:
    face = obj.get("face")
    if face is not None and face["bounding_box"] is not None:
        mask(face["bounding_box"])

얼굴을 찾지 못한 사람에게도 키는 붙고 안쪽 값이 None 입니다. 키가 있다고 가릴 영역이 있는 것은 아니므로 bounding_box 까지 확인하세요.

face 키는 person 항목에만 붙습니다. 화재·연기·지게차 등 다른 class 에는 키 자체가 없고, 비식별화를 켜지 않은 카메라 (set_deid_option(camera_id, {"enabled": True}))나 모델을 올리지 않은 경우에는 어떤 항목에도 없습니다. 즉 키의 유무가 이 카메라가 비식별화를 쓰는지 알려줍니다.

얼굴의 주인은 그 항목 자신입니다 — id 와 bounding_box 가 그 사람의 것입니다.

사람과 짝지어지지 않은 얼굴은 결과에 나오지 않으며 가려지지도 않습니다. 사람 검출이 그 사람을 놓쳤거나, 겹치는 사람이 이미 다른 얼굴을 받은 경우입니다 (한 사람에 얼굴 하나). 한 현장 영상 600프레임 기준 검출된 얼굴의 1.5%, 프레임의 17%에서 발생합니다. 사람 검출 성능에 딸린 한계입니다.

따라서 object option 의 person.enabled 가 켜져 있어야 합니다. 꺼면 사람 항목 자체가 없어 face 도 하나도 나오지 않습니다.

face["bounding_box"] 는 검출된 얼굴 크기 그대로입니다 — 넓히지 않습니다. 칠하기 전에 받는 쪽에서 각 변을 넓히세요(set_deid_option Note 2 참고). 병합·평활을 거치므로 검출된 얼굴 개수와는 1:1 이 아닙니다.

프레임을 시간 순서대로 넣어야 합니다 — 시간축 평활이 채널마다 트랙을 유지하며 여러 프레임의 점수를 평균해 판정합니다. 넣지 않은 프레임은 가려지지 않으므로, 띄엄띄엄 넣는다면 그 사이를 직전 영역으로 버티도록 받는 쪽에서 그만큼 더 넓혀야 합니다 (set_deid_option 참고).

warmup()

현재 설정된 inference 옵션을 바탕으로 warmup을 수행합니다. warmup은, 현재 inference_option이 잘 동작하는지 확인 + GPU를 첫 호출시 속도가 느린 이슈를 해결하기 위해, 현재 inference_option에 맞춰 더미 입력에 대한 InferenceHandler.infer를 호출합니다.

Usage
handler.warmup()

get_default_inference_option(model, key)

Model별 Postprocess 옵션의 기본 설정 값을 반환합니다.

Parameters:

Name Type Description Default
model str

"safety", "detection", "face_detection", "classification", "depth", "match" 중 하나.

required
key str

옵션 key

required

Returns:

Name Type Description
Any Any

옵션 value

사용 가능한 key와 value 목록

model: safety key: 가능한 key는 다음과 같습니다.

{
    "outputs.time": bool,  # 인퍼런스 시 각 요소에 걸린 시간을 반환할지 여부. (default False)
    "params.mlc_filter_thresholds": dict[str, float],  # MLC 필터의 각 클래스별 threshold 값. 각 값은 [0, 1] 범위의 실수. (default {"person": 0.9, "fire": 0.5, "smoke": 0.5})
                                                       # 소형 box 에는 `min(small_object.mlc_threshold[class], 이 값)`이 적용됩니다 (작은 객체를 더 통과시키기 위함).
    "params.small_object": dict,  # 소형 객체 보정 파라미터. 3개 key 를 모두 넘겨야 합니다. (default {"area": 900.0, "crop_margin": 0.1, "mlc_threshold": {"person": 0.7, "fire": -1, "smoke": -1}})
                                              #   "area": 소형으로 판정할 box 면적(px^2) 상한. 0 이상의 실수. (default 900.0 = 30x30px)
                                              #   "crop_margin": 소형 box 를 분류기에 넣을 때 각 변을 확장할 비율. [0, 1] 범위의 실수. 타이트한 crop 은 분류가 어려워 문맥을 넣습니다. (default 0.1 = 10% 확장)
                                              #   "mlc_threshold": 클래스별 소형 게이트. person/fire/smoke 3개 key 를 모두 넘겨야 합니다. 각 값은 [0, 1] 범위의 실수 또는 -1. (default {"person": 0.7, "fire": -1, "smoke": -1})
                                              #                    값이 있으면 그 class 가 crop 마진 대상이 되고, 소형 box 만 mlc_filter_thresholds 와 비교해 더 낮은 값으로 게이트됩니다.
                                              #                    -1 이면 그 class 는 소형 보정에서 제외됩니다 (crop 마진·게이트 완화 둘 다 없음).
                                              # 주의: 오프라인 채점(benchmark)도 같은 값을 읽습니다. 런타임에 바꾼 뒤 벤치를 돌릴 때는 같은 값을 함께 넘겨야 수치가 맞습니다.
}

model: detection key: DET 모델 결과 후처리 파라미터. 가능한 key는 다음과 같습니다.

{
    "params.object_score_threshold": list[int],  # 각 클래스의 score threshold 값. 예측 box의 score가 threshold보다 작은 경우 필터링 됩니다.
                                                    # 각 값은 [0, 100] 범위의 정수. (default [30, 10, ... , 10])
    "params.object_area_threshold": list[int],  # 각 클래스의 area threshold 값. 예측 box의 면적이 threshold보다 작은 경우 필터링 됩니다.
                                                # 각 값은 0 이상의 정수. (default [0, ... , 0])
    "params.max_num_of_detected_objects": list[int],  # 각 클래스의 최대 예측 박스 개수. 예측 box의 개수가 이 값을 넘을 경우 score가 낮은 순으로 제거됩니다.
                                                        # 각 값은 -1 이상의 정수이며, 값이 -1인 경우 개수 필터링을 적용하지 않습니다. (default [30, -1, ... , -1])
}

model: face_detection key: 얼굴 검출 모델 결과 후처리 파라미터. 비식별화를 켜고 빌드한 경우에만 사용할 수 있으며, 아닌 경우 FaceDetectionNotAvailableError(151)가 발생합니다. 가능한 key는 다음과 같습니다.

{
    "params.object_score_threshold": int,  # 얼굴 box의 score threshold. 낮출수록 미검은 줄고 헛검출은 늡니다.
                                            # [0, 100] 범위의 정수. (default 20)
    "params.person_score_threshold": int,  # 얼굴 모델이 내는 사람 box의 score threshold. 가릴 대상이 아니라
                                            # 후처리 게이트 재료라 얼굴보다 높게 잡습니다. [0, 100] 범위의 정수. (default 50)
    "params.nms_iou_threshold": int,  # 겹친 얼굴 box를 억제하는 IoU threshold. 학습 config와 같은 값이며,
                                        # 올려 잡으면 한 얼굴에 box가 여러 개 쌓입니다. [0, 100] 범위의 정수. (default 30)
    "params.dedup_iou_threshold": int,  # 거의 같은 위치의 box를 하나로 줄이는 IoU threshold. [0, 100] 범위의 정수. (default 95)
    "params.max_num_of_detected_objects": int,  # 최대 얼굴 box 개수. 넘으면 score가 낮은 순으로 제거됩니다.
                                                # -1 이상의 정수이며, -1인 경우 개수 필터링을 적용하지 않습니다. (default 300)
}

model: classification key: CLS 모델 결과 후처리 파라미터. 가능한 key는 다음과 같습니다.

{
    "params.additional_scores": list[int | float],  # scores_including_add를 계산할 때, scores_original에 더해지는 값입니다. 각 값은 [0, 100] 범위의 실수. (default [0.0, ... , 0.0])
}

model: depth key: DEPTH, NORMAL 모델 결과 후처리 파라미터. 가능한 key는 다음과 같습니다.

{
    "params.max_depth": float,  # 모델의 최대 추정 가능 깊이 (default 100.0 m)
}

model: match key: MATCH 모델 결과 후처리 파라미터. 가능한 key는 다음과 같습니다.

{
    "params.match_threshold": float,  # 두 이미지의 키포인트가 같은 위치인지 판단하는 threshold. (default 0.6)
}

Usage
err, msg, option = handler.get_default_inference_option(model="safety", key="outputs.time")
print(option)
# False

get_inference_option(model, key)

Model에 따른 현재 설정된 postprocess 옵션 값을 읽습니다.

Parameters:

Name Type Description Default
model str

"safety", "detection", "face_detection", "classification", "depth", "match" 중 하나.

required
key str

옵션 key

required

Returns:

Name Type Description
Any Any

옵션 value

Keys

get_default_inference_option과 동일합니다.

Usage
err, msg, _ = handler.get_inference_option(model="safety", key="outputs.time")
print(option)
# True or False

set_inference_option(model, key, value)

Model에 따른 Postprocess 옵션을 설정합니다.

Parameters:

Name Type Description Default
model str

"safety", "detection", "face_detection", "classification", "depth", "match" 중 하나.

required
key str

설정하고자 하는 옵션 key 입니다.

required
value Any

설정하고자 하는 옵션 value 입니다.

required

Returns:

Name Type Description
None None

None

Keys

get_default_inference_option과 동일합니다.

Usage
err, msg, _ = handler.set_inference_option(model="safety", key="outputs.time", value=True)
err, msg, option = handler.get_inference_option(model="safety", key="outputs.time")
print(option)
# True

register_camera(camera_id)

검사할 camera_id를 등록합니다.

Parameters:

Name Type Description Default
camera_id int

등록할 camera_id

required

Returns:

Name Type Description
None None

None

Raises:

Type Description
InvalidCameraIdError

camera_id가 int가 아닌 경우 발생하는 에러

AlreadyRegisteredCameraIdError

이미 등록된 camera_id를 등록하려고 할 때 발생하는 에러

Usage
err, msg, _ = handler.register_camera(camera_id=0)
err, msg, cam_ids = handler.get_registered_camera_ids()
0 in cam_ids
# True

release_camera(camera_id)

등록된 camera_id를 해제합니다.

Parameters:

Name Type Description Default
camera_id int

해제할 camera_id

required

Returns:

Name Type Description
None None

None

Raises:

Type Description
UnregisteredCameraIdError

등록되지 않은 camera_id를 해제하려고 할 때 발생하는 에러

Usage
err, msg, _ = handler.register_camera(camera_id=0)
err, msg, cam_ids = handler.get_registered_camera_ids()
0 in cam_ids
# True

err, msg, _ = handler.release_camera(camera_id=0)
err, msg, cam_ids = handler.get_registered_camera_ids()
0 in cam_ids
# False

get_registered_camera_ids()

등록된 camera_id 리스트를 반환합니다.

Returns:

Type Description
list[int]

list[int]: 등록된 camera_id 리스트

get_default_tracker_option(camera_id)

기본 tracker option을 반환합니다.

Parameters:

Name Type Description Default
camera_id int

tracker option을 반환할 camera_id (사용하지 않음, 단순히 다른 API와의 일관성을 위해 존재)

required

Returns:

Type Description
dict[str, Any]

dict[str, Any]: tracker option

{
    "object_score_threshold": int, # object의 detection score가 이 값보다 크면 바로 track 합니다. (default 70)
    "min_continuous_count": int, # object의 detection score가 object_score_threshold보다 낮을 때 object가 track 되기 위한 최소 연속 프레임 수 (default 1)
}

Usage
err, msg, option = handler.get_default_tracker_option(camera_id=0)
print(option)
# {"object_score_threshold": 70, "min_continuous_count": 5}

Note: camera_id는 사용하지 않으며, 단순히 다른 API와의 일관성을 위해 존재합니다.

get_tracker_option(camera_id)

등록된 camera_id에 대한 tracker option을 반환합니다.

Parameters:

Name Type Description Default
camera_id int

tracker option을 반환할 camera_id

required

Returns:

Type Description
dict[str, Any]

dict[str, Any]: tracker option. 형태는 InferenceHandler.get_default_tracker_option의 반환값과 동일합니다.

Raises:

Type Description
UnregisteredCameraIdError

등록되지 않은 camera_id에 대한 정보를 요청할 때 발생하는 에러

Usage
option = handler.get_tracker_option(camera_id=0)
print(option)
# {"object_score_threshold": 70, "min_continuous_count": 5} 사용자가 설정한 값이 반환됩니다.

set_tracker_option(camera_id, tracker_option)

등록된 camera_id에 대한 tracker option을 설정합니다.

Parameters:

Name Type Description Default
camera_id int

tracker option을 설정할 camera_id

required
tracker_option dict[str, Any]

tracker option. 형태는 InferenceHandler.get_default_tracker_option의 반환값과 동일합니다.

required

Returns:

Name Type Description
None None

None

Raises:

Type Description
InvalidTrackerOptionError

tracker_option가 올바르지 않을 때 발생하는 에러

UnregisteredCameraIdError

등록되지 않은 camera_id에 대해 설정할 때 발생하는 에러

Usage
option = handler.get_tracker_option(camera_id=0)
option["object_score_threshold"] = 70
option["min_continuous_count"] = 5
handler.set_tracker_option(camera_id=0, tracker_option=option)
option = handler.get_tracker_option(camera_id=0)
print(option)
# {"object_score_threshold": 70, "min_continuous_count": 5} # 설정한 값이 반환됩니다.

get_default_deid_option(camera_id)

얼굴 비식별화 옵션의 기본값을 가져옵니다.

Parameters:

Name Type Description Default
camera_id int

옵션을 반환할 camera_id (사용하지 않음, 단순히 다른 API와의 일관성을 위해 존재)

required

Returns:

Type Description
dict[str, Any]

dict[str, Any]: 기본 비식별화 옵션. 자세한 항목은 set_deid_option 참고.

get_deid_option(camera_id)

해당 카메라의 얼굴 비식별화 옵션을 가져옵니다.

Parameters:

Name Type Description Default
camera_id int

카메라 ID.

required

Returns:

Type Description
dict[str, Any]

dict[str, Any]: 현재 비식별화 옵션.

set_deid_option(camera_id, deid_option)

해당 카메라의 얼굴 비식별화 옵션을 변경합니다.

바꾸려는 항목만 담아 넘기면 됩니다. 넘기지 않은 항목은 그대로 유지됩니다.

Parameters:

Name Type Description Default
camera_id int

카메라 ID.

required
deid_option dict[str, Any]

변경할 옵션.

{
    "enabled": bool,          # 이 채널의 비식별화 사용 여부 (default False)
    "person_gate": bool,      # 사람 박스 밖의 얼굴 검출을 버립니다 (default True)
    "gate_below": int,        # 이 점수 이상인 얼굴은 게이트를 건너뜁니다 (0~100)
    "smooth_thr": int,        # 평활 통과 점수 (0~100, default 30)
    "smooth_enabled": bool,   # 시간축 평활 사용 여부 (default True)
    "smooth_window": int,     # 평활 창. 초가 아니라 **프레임 수**입니다
    ...
}

required
Note
  1. 프레임을 시간 순서대로 넣어야 합니다. 시간축 평활이 채널마다 트랙을 유지하며 여러 프레임의 점수를 평균해 판정하므로, 순서가 섞이면 에러 없이 깜빡임이나 과검으로 나타납니다.
  2. 좌표는 검출된 얼굴 크기 그대로이며 넓히지 않습니다. 검출 박스는 머리카락 경계·턱선을 조금 못 덮으므로, 칠하기 전에 받는 쪽에서 각 변을 넓히세요.

화면에는 모든 프레임이 나가는데 여기로는 골라서 넣는다면, 넣지 않은 프레임은 받는 쪽이 직전 영역을 그대로 붙들고 있어야 합니다. 그사이 사람이 움직이면 얼굴이 그 영역을 벗어나므로 그만큼 더 넓혀야 합니다. 이 모듈은 넣는 주기도, 어떻게 칠할지도 알 수 없습니다. 3. smooth_window 등 평활 항목의 단위는 초가 아니라 프레임 수입니다. 넣는 프레임레이트가 달라지면 같은 값이라도 시간 상수가 달라집니다. 4. 얼굴 검출 문턱은 채널별 옵션이 아니라 모델 옵션입니다. 다른 모델과 마찬가지로 set_inference_option("face_detection", ...) 으로 바꿉니다. 눈금은 여기 점수 항목과 같은 0~100 이라 그대로 비교하면 됩니다. smooth_thr 는 검출 문턱보다 커야 뜻이 있습니다 — 같거나 낮으면 들어오는 박스가 이미 전부 그 값을 넘긴 것들이라 아무것도 걸러지지 않습니다. (기본값은 검출 문턱 20, smooth_thr 30 입니다.) 5. person_gate 가 쓰는 사람 박스는 safety 검출기의 person 클래스입니다 (infer 결과의 boxes_xyxy). 얼굴 모델이 따로 내는 것이 아닙니다.

get_default_grid_option(camera_id)

기본 grid option을 반환합니다.

Parameters:

Name Type Description Default
camera_id int

grid option을 반환할 camera_id (사용하지 않음, 단순히 다른 API와의 일관성을 위해 존재)

required

Returns:

Type Description
dict[str, Any]

dict[str, Any]: grid option

{
    "grid_step_wh": tuple[int, int], # the number of step in width and height direction. (default (1, 1))
    "overlap_ratio": float,          # the ratio of overlap between adjacent grid cells. (default 0.0)
}

Usage
err, msg, option = handler.get_default_grid_option(camera_id=0)
print(option)
# {"grid_step_wh": (1, 1), "overlap_ratio": 0.0}

Note: camera_id는 사용하지 않으며, 단순히 다른 API와의 일관성을 위해 존재합니다.

get_grid_option(camera_id)

등록된 camera_id에 대한 grid option을 반환합니다.

Parameters:

Name Type Description Default
camera_id int

grid option을 반환할 camera_id

required

Returns:

Type Description
dict[str, Any]

dict[str, Any]: grid option. 형태는 InferenceHandler.get_default_grid_option의 반환값과 동일합니다.

Raises:

Type Description
UnregisteredCameraIdError

등록되지 않은 camera_id에 대한 정보를 요청할 때 발생하는 에러

Usage
option = handler.get_grid_option(camera_id=0)
print(option)
# {"grid_step_wh": (2, 2), "overlap_ratio": 0.1} # 사용자가 설정한 값이 반환됩니다.

set_grid_option(camera_id, grid_option)

등록된 camera_id에 대한 grid option을 설정합니다.

Parameters:

Name Type Description Default
camera_id int

grid option을 설정할 camera_id

required
grid_option dict[str, Any]

grid option. 형태는 InferenceHandler.get_default_grid_option의 반환값과 동일합니다.

required

Returns:

Name Type Description
None None

None

Raises:

Type Description
InvalidGridOptionError

grid_option이 올바르지 않을 때 발생하는 에러

UnregisteredCameraIdError

등록되지 않은 camera_id에 대해 설정할 때 발생하는 에러

Usage
option = handler.get_grid_option(camera_id=0)
option["grid_step_wh"] = (2, 2)
option["overlap_ratio"] = 0.1
handler.set_grid_option(camera_id=0, grid_option=option)
option = handler.get_grid_option(camera_id=0)
print(option)
# {"grid_step_wh": (2, 2), "overlap_ratio": 0.1} # 설정한 값이 반환됩니다.

get_reference_image(camera_id)

등록된 camera_id에 대한 reference image를 반환합니다.

Parameters:

Name Type Description Default
camera_id int

reference image를 반환할 camera_id

required

Returns:

Type Description
ndarray | None

np.ndarray | None: reference image (shape: [H, W, C]). None인 경우 reference image가 설정되지 않은 상태입니다.

Raises:

Type Description
UnregisteredCameraIdError

등록되지 않은 camera_id에 대한 정보를 요청할 때 발생하는 에러

Usage
err, msg, img = handler.get_reference_image(camera_id=0)
if img is None:
    print("Reference image is not set.")
else:
    print(img.shape)

set_reference_image(camera_id, reference_image, surface_points)

등록된 camera_id에 대한 reference image를 설정합니다.

Parameters:

Name Type Description Default
camera_id int

reference image를 설정할 camera_id

required
reference_image ndarray

reference image 형태는 InferenceHandler.get_reference_image의 반환값과 동일합니다.

required
surface_points list[list[int]]

Surface depth fitting에 사용할 surface points.

    [
        [x1, y1], [x2, y2], ..., [xn, yn] # n개의 점으로 이루어진 surface points (n >= 3)
    ]

required

Returns:

Name Type Description
None None

None

Raises:

Type Description
InvalidReferenceImageError

reference_image가 올바르지 않을 때 발생하는 에러

UnregisteredCameraIdError

등록되지 않은 camera_id에 대해 설정할 때 발생하는 에러

InsufficientSurfacePointsError

surface_points의 개수가 3개 미만인 경우 발생하는 에러

Usage
import cv2
reference_image = cv2.imread("reference.jpg")
surface_points = [[0, 0], [100, 0], [100, 100], [0, 100]]
err, msg, _ = handler.set_reference_image(camera_id=0, reference_image=reference_image, surface_points=surface_points)
err, msg, img = handler.get_reference_image(camera_id=0)
np.array_equal(reference_image, img)
# True # set과 get 과정에서 형변환이 일어나기 때문에 완전히 동일하지 않을 수 있습니다.

get_monitoring_area(camera_id)

등록된 camera_id에 대한 monitoring area를 반환합니다.

Parameters:

Name Type Description Default
camera_id int

monitoring area를 반환할 camera_id

required

Returns:

Type Description
dict[str, list[list[list[int]]]]

dict[str, list[list[list[int]]]]: dictionary of monitoring area polygon list

{
    "includes": [ # 포함하는 영역의 polygon 리스트 (default [])
        [[x1, y1], ..., [xn, yn]], # n개의 점으로 이루어진 polygon (n >= 3)
        ...
    ],
    "excludes": list[list[list[int]]] # 제외하는 영역의 polygon 리스트(includes와 동일).
}

Raises: UnregisteredCameraIdError: 등록되지 않은 camera_id에 대한 정보를 요청할 때 발생하는 에러

Usage
err, msg, area = handler.get_monitoring_area(camera_id=0)
print(area)
# {"includes": [[[0, 0], [100, 0], [100, 100], [0, 100]]], "excludes": []} # 사용자가 설정한 값이 반환됩니다.

set_monitoring_area(camera_id, monitoring_area)

등록된 camera_id에 대한 monitoring area를 설정합니다.

Parameters:

Name Type Description Default
camera_id int

monitoring area를 설정할 camera_id

required
monitoring_area dict[str, list[list[list[int]]]]

dictionary of monitoring area polygon list 형태는 InferenceHandler.get_monitoring_area의 반환값과 동일합니다.

required

Returns:

Name Type Description
None None

None

Raises:

Type Description
InvalidMonitoringAreaError

monitoring_area가 올바르지 않을 때 발생하는 에러

UnregisteredCameraIdError

등록되지 않은 camera_id에 대해 설정할 때 발생하는 에러

Usage
area = {"includes": [[[0, 0], [100, 0], [100, 100], [0, 100]]], "excludes": []}
err, msg, _ = handler.set_monitoring_area(camera_id=0, monitoring_area=area)
err, msg, area = handler.get_monitoring_area(camera_id=0)
print(area)
# {"includes": [[[0, 0], [100, 0], [100, 100], [0, 100]]], "excludes": []} # 설정한 값이 반환됩니다.

get_default_object_options(camera_id)

등록된 camera_id에 대한 default object options를 반환합니다.

Parameters:

Name Type Description Default
camera_id int

default object options를 반환할 camera_id

required

Returns:

Type Description
dict[str, dict]

dict[str, dict[str, Any]]: object options

{
    "person": {
        # 얼굴 비식별화를 함께 쓴다면 이 항목의 필터가 가리기에도 그대로 적용됩니다.
        # `face`는 person object에만 붙으므로, 아래 옵션으로 걸러진 사람의 얼굴은
        # 에러 없이 가려지지 않습니다. `enabled`가 False면 한 장도 가려지지 않습니다.
        "enabled": bool,         # 해당 object_type을 검출할지 여부. 라이센스 조정을 위해 사용됩니다. (default False)
        "area_threshold": float | tuple[float, float] | list[float], # 해당 object_type의 면적 필터. float면 최소 면적(이 값보다 작으면 필터링), 길이 2의 (min, max) tuple/list면 최소/최대 면적(범위 밖이면 필터링, 0 <= min <= max). (default 100.0)
        "score_threshold": int,  # 해당 object_type의 score threshold (0~100). 이 값보다 낮은 `object_score`를 가진 object는 필터링 됩니다. (default 30)

        # 아래 옵션들은 `ignore_dark_object` 옵션을 가진 이벤트들에서, 해당 object가 dark object인지 판단하는데 사용됩니다.
        "brightness_threshold": int, # 해당 object_type의 밝기 threshold (0~100). 이 값보다 크거나 같은 `brightness_score`를 가진 object는 dark object가 아닌 것으로 취급. (default 27)
        "surrounding_brightness_threshold": int, # object 주변 영역의 밝기 threshold (0~100). 이 값보다 크거나 같은 `surrounding_brightness_score`를 가진 object는 주변이 밝은 것으로 취급되어 dark object 판정에서 제외됨. (default 30)
        "small_area_threshold": float, # 해당 object_type의 작은 면적 threshold. 이 값보다 크거나 같은 면적을 가진 object는 밝기와 상관없이 dark object가 아닌 것으로 취급. (default 2500.0)
    },
    "fire": {
        "enabled": bool,         # default False
        "area_threshold": float | tuple[float, float] | list[float], # default 900.0. 길이 2의 (min, max) tuple/list로 상한 지정 가능 (0 <= min <= max)
        "score_threshold": int,  # default 10
    },
    "smoke": {
        "enabled": bool,         # default False
        "area_threshold": float | tuple[float, float] | list[float], # default 900.0. 길이 2의 (min, max) tuple/list로 상한 지정 가능 (0 <= min <= max)
        "score_threshold": int,  # default 10
        "movement_score_threshold": int, # 이 값보다 크거나 같은 movement score를 가진 smoke object만 object로 남습니다. (default 0)
    },
    "excavator": {
        "enabled": bool,         # default False
        "area_threshold": float | tuple[float, float] | list[float], # default 900.0. 길이 2의 (min, max) tuple/list로 상한 지정 가능 (0 <= min <= max)
        "score_threshold": int,  # default 30
        "center_y_offset_ratio": float,  # default 1.0
        "width_scale": float,    # default 1.2
        "height_scale": float,   # default 0.5
        "area_scale": float,     # default 1.5
    },
    "forklift": {
        "enabled": bool,         # default False
        "area_threshold": float | tuple[float, float] | list[float], # default 900.0. 길이 2의 (min, max) tuple/list로 상한 지정 가능 (0 <= min <= max)
        "score_threshold": int,  # default 30
        "center_y_offset_ratio": float,  # default 1.0
        "width_scale": float,    # default 1.2
        "height_scale": float,   # default 0.5
        "area_scale": float,     # default 1.5
    },
    "crane_body": {
        "enabled": bool,         # default False
        "area_threshold": float | tuple[float, float] | list[float], # default 900.0. 길이 2의 (min, max) tuple/list로 상한 지정 가능 (0 <= min <= max)
        "score_threshold": int,  # default 30
        "center_y_offset_ratio": float,  # default 1.0
        "width_scale": float,    # default 1.2
        "height_scale": float,   # default 0.5
        "area_scale": float,     # default 1.5
    },
    "crane_hook": {
        "enabled": bool,         # default False
        "area_threshold": float | tuple[float, float] | list[float], # default 900.0. 길이 2의 (min, max) tuple/list로 상한 지정 가능 (0 <= min <= max)
        "score_threshold": int,  # default 30
        "center_y_offset_ratio": float,  # default 1.0
        "width_scale": float,    # default 1.2
        "height_scale": float,   # default 0.5
        "area_scale": float,     # default 1.5
    },
    "crane_lifted_object": {
        "enabled": bool,         # default False
        "area_threshold": float | tuple[float, float] | list[float], # default 900.0. 길이 2의 (min, max) tuple/list로 상한 지정 가능 (0 <= min <= max)
        "score_threshold": int,  # default 30
        "center_y_offset_ratio": float,  # default 1.0
        "width_scale": float,    # default 1.2
        "height_scale": float,   # default 0.5
        "area_scale": float,     # default 1.5
    },
    "heavy_equipment": {
        "enabled": bool,         # default False
        "area_threshold": float | tuple[float, float] | list[float], # default 900.0. 길이 2의 (min, max) tuple/list로 상한 지정 가능 (0 <= min <= max)
        "score_threshold": int,  # default 30
        "center_y_offset_ratio": float,  # default 1.0
        "width_scale": float,    # default 1.2
        "height_scale": float,   # default 0.5
        "area_scale": float,     # default 1.5
    },
    "vehicle": {
        "enabled": bool,         # default False
        "area_threshold": float | tuple[float, float] | list[float], # default 900.0. 길이 2의 (min, max) tuple/list로 상한 지정 가능 (0 <= min <= max)
        "score_threshold": int,  # default 30
        "center_y_offset_ratio": float,  # default 1.0
        "width_scale": float,    # default 1.2
        "height_scale": float,   # default 0.5
        "area_scale": float,     # default 1.5
    },
}

Raises:

Type Description
UnregisteredCameraIdError

등록되지 않은 camera_id에 대한 정보를 요청할 때 발생하는 에러

Usage
err, msg, options = handler.get_default_object_options(camera_id=0)
print(options)
# {"person": {...}, ...} # object type별 기본 옵션이 반환됩니다.

get_object_options(camera_id)

등록된 camera_id에 대한 object options를 반환합니다.

Parameters:

Name Type Description Default
camera_id int

object options를 반환할 camera_id

required

Returns:

Type Description
dict[str, dict]

dict[str, dict[str, Any]]: object options. 형태는 InferenceHandler.get_default_object_options의 반환값과 동일합니다.

Raises:

Type Description
UnregisteredCameraIdError

등록되지 않은 camera_id에 대한 정보를 요청할 때 발생하는 에러

Usage
options = handler.get_object_options(camera_id=0)
print(options)
# {"person": {...}, ...} # 사용자가 설정한 값이 반환됩니다.

set_object_options(camera_id, object_options)

등록된 camera_id에 대한 object options를 설정합니다.

Parameters:

Name Type Description Default
camera_id int

object options를 설정할 camera_id

required
object_options dict[str, dict]

object options. 형태는 InferenceHandler.get_default_object_options의 반환값과 동일합니다.

required

Returns:

Name Type Description
None None

None

Raises:

Type Description
InvalidObjectOptionsError

object_options가 올바르지 않을 때 발생하는 에러

UnregisteredCameraIdError

등록되지 않은 camera_id에 대해 설정할 때 발생하는 에러

Usage
options = handler.get_object_options(camera_id=0)
options["person"]["enabled"] = True
options["person"]["score_threshold"] = 50
handler.set_object_options(camera_id=0, object_options=options)
options = handler.get_object_options(camera_id=0)
print(options)
# {"person": {"enabled": True, "area_threshold": 100.0, "score_threshold": 50}, ...} # 설정한 값이 반환됩니다.
# {"smoke": {"enabled": True, "area_threshold": 900.0, "score_threshold": 50, "movement_score_threshold": 10}, ...} # 설정한 값이 반환됩니다.
Note

얼굴 비식별화를 함께 쓴다면 person 항목의 필터가 가리기에도 그대로 적용됩니다. face는 person object에만 붙으므로, 여기서 걸러진 사람의 얼굴은 에러 없이 가려지지 않습니다. person.enabled가 False면(기본값) 한 장도 가려지지 않습니다.

get_default_event_options(camera_id)

등록된 camera_id에 대한 default event options를 반환합니다.

Parameters:

Name Type Description Default
camera_id int

default event options를 반환할 camera_id

required

Returns:

Type Description
dict[str, dict]

dict[str, dict[str, Any]]: event options

{
    "fire_detect": {
        "fire_score_threshold": int,    # fire score threshold. 이 값보다 높은 fire score를 가진 object에 대해서만 이벤트를 발생시킵니다. (default 10)
    },
    "smoke_detect": {
        "smoke_score_threshold": int,   # smoke score threshold. 이 값보다 높은 smoke score를 가진 object에 대해서만 이벤트를 발생시킵니다. (default 10)
    },
    "without_helmet": {
        "ignore_dark_object": bool,     # 어두운 객체에 대한 이벤트를 무시할지 여부. (default True)
        "object_area_threshold": float,  # object area threshold. 이 값보다 큰 object에 대해서만 이벤트를 발생시킵니다. (default 0.0)
        "head_score_threshold": int,    # head score threshold. 이 값보다 높은 head score를 가진 object에 대해서만 이벤트를 발생시킵니다. (default 90)
        "helmet_score_threshold": int,  # helmet score threshold. 이 값보다 낮은 helmet score를 가진 object에 대해서만 이벤트를 발생시킵니다. (default 30)
    },
    "without_harness": {
        "ignore_dark_object": bool,     # 어두운 객체에 대한 이벤트를 무시할지 여부. (default True)
        "object_area_threshold": float,  # object area threshold. 이 값보다 큰 object에 대해서만 이벤트를 발생시킵니다. (default 0.0)
        "harness_score_threshold": int, # harness score threshold. 이 값보다 낮은 harness score를 가진 object에 대해서만 이벤트를 발생시킵니다. (default 30)
    },
    "fallen_person": {
        "ignore_crossing_image_border_object": bool, # 이미지 경계를 넘어가는 객체에 대한 이벤트를 무시할지 여부. (default False)
        "ignore_dark_object": bool,                  # 어두운 객체에 대한 이벤트를 무시할지 여부. (default True)
        "object_area_threshold": float,               # object area threshold. 이 값보다 큰 object에 대해서만 이벤트를 발생시킵니다. (default 0.0)
        "fall_down_score_threshold": int,            # fall_down score threshold. 이 값보다 높은 fall_down score를 가진 object에 대해서만 이벤트를 발생시킵니다. (default 50)
    },
    "trespass_detect": {
        "area_ratio_threshold": int,                 # area_ratio_threshold. 2D/3D 모두 적용. (default 95)
                                                     # 이 값보다 높은 intersection area ratio (intersection_area / object_area) 를 가진 object에 대해서만 이벤트를 발생시킵니다.
        "polygons": list[list[list[int]]],     # 침입 감지할 영역의 polygon list. (default [])
            ```python
                [
                    [[x1, y1], ..., [xn, yn]], # n개의 점으로 이루어진 polygon (n >= 3)
                    ...
                ]
            ```
        "use_depth": bool,                     # depth 정보를 사용할지 여부. (default False)
    },
    "danger_detect": {
        "area_ratio_threshold": int,                 # area_ratio_threshold. (default 95)
                                                     # 이 값보다 높은 intersection area ratio (intersection_area / object_area) 를 가진 object에 대해서만 이벤트를 발생시킵니다.
        "polygons": list[list[list[int]]],     # 배회 감지할 영역의 polygon list. (default [])
            ```python
                [
                    [[x1, y1], ..., [xn, yn]], # n개의 점으로 이루어진 polygon (n >= 3)
                    ...
                ]
            ```
    }
    "in_collision_hazard_zone": {
        "area_ratio_threshold": int,                 # area_ratio_threshold. (default 95)
                                                     # 이 값보다 높은 intersection area ratio (intersection_area / object_area) 를 가진 object에 대해서만 이벤트를 발생시킵니다.
        "polygons": list[list[list[int]]],     # 충돌 감지할 영역의 polygon list. (default [])
            ```python
                [
                    [[x1, y1], ..., [xn, yn]], # n개의 점으로 이루어진 polygon (n >= 3)
                    ...
                ]
            ```
    }
    "collision_hazard_detect":  {
        "area_ratio_threshold": int,                 # area_ratio_threshold. (default 95)
                                                     # 이 값보다 높은 intersection area ratio (intersection_area / object_area) 를 가진 object에 대해서만 이벤트를 발생시킵니다.
        "movement_score_threshold": int,       # movement_score threshold. 이 값보다 높은 movement score를 가진 object에 대해서만 이벤트를 발생시킵니다. (default 5)
        "polygons": list[list[list[int]]],     # 충돌 감지할 영역의 polygon list. (default [])
            ```python
                [
                    [[x1, y1], ..., [xn, yn]], # n개의 점으로 이루어진 polygon (n >= 3)
                    ...
                ]
            ```
        "hazard_object_types": list[str],            # 충돌 위험 객체로 사용할 object type 리스트. (default 사용 가능한 object type 전체)
                                                     # 사용 가능한 object type은 ["excavator", "forklift", "crane_body", "crane_hook", "crane_lifted_object", "heavy_equipment", "vehicle"] 입니다.
    }
    "crush_detect": {
        "area_ratio_threshold": int,                 # area_ratio_threshold. (default 50)
                                                     # 이 값보다 높은 intersection area ratio (intersection_area / object_area) 를 가진 object에 대해서만 이벤트를 발생시킵니다.
        "use_depth": bool,                           # depth 정보를 사용할지 여부. (default False)
        "hazard_object_types": list[str],            # 협착 위험 객체로 사용할 object type 리스트. (default 사용 가능한 object type 전체)
                                                     # 사용 가능한 object type은 ["excavator", "forklift", "crane_body", "crane_hook", "crane_lifted_object", "heavy_equipment", "vehicle"] 입니다.
    }
    "proximity_hazard_detect": {
        "use_depth": bool,                           # depth 정보를 사용할지 여부. (default False). 현재는 use_depth가 True인 경우에만 동작합니다.
        "polygon_pairs": list[list[list[list[int, int]]]], # 근접 위험 영역의 polygon 쌍 리스트. (default [])
                                                           # 각 polygon 쌍은 충돌 위험 객체를 위한 polygon과 침입 영역을 위한 polygon 순으로 입력된다고 가정합니다.
            ```python
                [
                    [                                                                           [
                        # 충돌 위험 객체를 위한 polygon
                        [[x1, y1], ..., [xn, yn]], # n개의 점으로 이루어진 polygon (n >= 3)

                        # 침입 영역을 위한 polygon 리스트
                        [[x1, y1], ..., [xn, yn]], # n개의 점으로 이루어진 polygon (n >= 3)

                    ],
                    ... # 여러 개의 polygon 쌍
                ]
            ```
        "hazard_object_types": list[str],            # 근접 위험 객체로 사용할 object type 리스트. (default 사용 가능한 object type 전체)
                                                     # 사용 가능한 object type은 ["excavator", "forklift", "crane_body", "crane_hook", "crane_lifted_object", "heavy_equipment", "vehicle"] 입니다.
    }
    "payload_instability_detect": {
        "payload_instability_min_width": int,        # 적재불량 검사에 사용할 최소 적재물 너비 (픽셀 단위). (default 100)
        "payload_instability_active": bool           # 적재불량 검사 활성화 여부. (default False)
        "payload_instability_score_threshold": int   # 적재불량 score threshold. 이 값보다 낮은 payload_instability score를 가진 object에 대해서만 이벤트를 발생시킵니다. (default 80)
    }
    "aloft_work_detect": {
        "use_depth": bool,                           # depth 정보를 사용할지 여부. (default False). 현재는 use_depth가 True인 경우에만 동작합니다.
        "height_threshold": int,                   # 지면 평면 기준 높이 임계값 (단위: cm). 이 값을 초과하면 이벤트를 발생시킵니다. (default 300)
    }
}

Usage
err, msg, options = handler.get_default_event_options(camera_id=0)
print(options)
# {"fire_detect": {...}, ...} # event type별 기본 옵션이 반환됩니다.

get_event_options(camera_id)

등록된 camera_id에 대한 event options를 반환합니다.

Parameters:

Name Type Description Default
camera_id int

event options를 반환할 camera_id

required

Returns:

Type Description
dict[str, dict]

dict[str, dict[str, Any]]: event options. 형태는 InferenceHandler.get_default_event_options의 반환값과 동일합니다.

Raises:

Type Description
UnregisteredCameraIdError

등록되지 않은 camera_id에 대한 정보를 요청할 때 발생하는 에러

Usage
options = handler.get_event_options(camera_id=0)
print(options)
# {"fire_detect": {...}, ...} # 사용자가 설정한 값이 반환됩니다

set_event_options(camera_id, event_options)

등록된 camera_id에 대한 event options를 설정합니다.

Parameters:

Name Type Description Default
camera_id int

event options를 설정할 camera_id

required
event_options dict[str, dict]

event options. 형태는 InferenceHandler.get_default_event_options의 반환값과 동일합니다.

required

Returns:

Name Type Description
None None

None

Raises:

Type Description
InvalidEventOptionsError

event_options가 올바르지 않을 때 발생하는 에러

UnregisteredCameraIdError

등록되지 않은 camera_id에 대해 설정할 때 발생하는 에러

Usage
options = handler.get_event_options(camera_id=0)
options["fire_detect"]["fire_score_threshold"] = 20
handler.set_event_options(camera_id=0, event_options=options)
options = handler.get_event_options(camera_id=0)
print(options)
# {"fire_detect": {"fire_score_threshold": 20}, ...} # 설정한 값이 반환됩니다.

get_default_alarm_options(camera_id)

등록된 camera_id에 대한 default alarm options를 반환합니다.

Parameters:

Name Type Description Default
camera_id int

default alarm options를 반환할 camera_id

required

Returns:

Type Description
dict[str, dict]

dict[str, dict]: alarm options

{
    "fire_detect": {
        "enabled": bool,                # 해당 event_type에 대한 알람 활성화 여부. (default False)
        "time_ranges": list[list[int]], # 알람 활성화 시간대 목록. list의 list 구조: 바깥 list는 시간대들의 목록이고, 안쪽 list는 반드시 길이 2인 [start, end] 이다. (단위: 초, 0 <= start, end <= 86400) 여러 구간 지정 가능. (default [[0, 86400]] = 24시간)
        "alarm_interval": int,          # 한번 울린 알람이 다시 울리기 까지 시간. (단위: 초, default 300)
        "repeat_threshold": int,        # 해당 기간 동안 일정 비율 이상의 event가 발생해야 알람이 발생. (단위: 초, default 3)
        "alarm_ratio_threshold": int,   # repeat_threshold 기간 동안 event가 발생한 비율이 이 값보다 크면 알람 발생. (단위: %, default 50)
    },
    "smoke_detect": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "without_helmet": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "without_harness": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "fallen_person": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "trespass_detect": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "danger_detect": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "in_collision_hazard_zone": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "collision_hazard_detect": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "crush_detect": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "proximity_hazard_detect": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "payload_instability_detect": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
    "aloft_work_detect": {
        "enabled": bool,
        "time_ranges": list[list[int]],
        "alarm_interval": int,
        "repeat_threshold": int,
        "alarm_ratio_threshold": int,
    },
}

Note
  1. time_ranges는 list의 list 입니다. 바깥 list는 활성화 시간대들의 목록이고, 각 안쪽 list는 반드시 길이 2인 [start, end] 이어야 합니다. (예: [[36000, 43200], [46800, 61200]] → 10:00~12:00, 13:00~17:00 활성화)
  2. 현재 시각이 어느 한 구간에라도 포함되면 알람이 활성화됩니다. 구간이 서로 겹쳐도 됩니다. (겹치는 구간은 합집합으로 처리됩니다.) 엔진단에서는 구간 겹침을 검사하지 않으며, 구간 겹침 검증은 front/backend에서 수행됩니다.
  3. 각 구간에서 start == end인 경우, 해당 구간은 항상(24시간) 활성화됩니다.
  4. 각 구간에서 start > end인 경우, 자정을 넘기는 구간으로 해석됩니다. (예: 23:00~04:00 → 23:00~24:00, 00:00~04:00 활성화)

Raises:

Type Description
UnregisteredCameraIdError

등록되지 않은 camera_id에 대한 정보를 요청할 때 발생하는 에러

Usage
err, msg, options = handler.get_default_alarm_options(camera_id=0)
print(options)
# {"fire_detect": {...}, ...} # event type별 기본 옵션이 반환됩니다

get_alarm_options(camera_id)

등록된 camera_id에 대한 alarm options를 반환합니다.

Parameters:

Name Type Description Default
camera_id int

alarm options를 반환할 camera_id

required

Returns:

Type Description
dict[str, dict]

dict[str, dict]: alarm options. 형태는 InferenceHandler.get_default_alarm_options의 반환값과 동일합니다.

Raises:

Type Description
UnregisteredCameraIdError

등록되지 않은 camera_id에 대한 정보를 요청할 때 발생하는 에러

Usage
options = handler.get_alarm_options(camera_id=0)
print(options)
# {"fire_detect": {...}, ...} # 사용자가 설정한 값이 반환됩니다

set_alarm_options(camera_id, alarm_options)

등록된 camera_id에 대한 alarm options를 설정합니다.

Parameters:

Name Type Description Default
camera_id int

alarm options를 설정할 camera_id

required
alarm_options dict[str, dict]

alarm options. 형태는 InferenceHandler.get_default_alarm_options의 반환값과 동일합니다.

required

Returns:

Name Type Description
None None

None

Raises:

Type Description
InvalidAlarmOptionsError

alarm_options가 올바르지 않을 때 발생하는 에러

UnregisteredCameraIdError

등록되지 않은 camera_id에 대해 설정할 때 발생하는 에러

Usage
options = handler.get_alarm_options(camera_id=0)
options["fire_detect"]["enabled"] = True
options["fire_detect"]["time_ranges"] = [[8 * 3600, 12 * 3600], [13 * 3600, 18 * 3600]]
handler.set_alarm_options(camera_id=0, alarm_options=options)
options = handler.get_alarm_options(camera_id=0)
print(options)
# {"fire_detect": {"enabled": True, "time_ranges": [[28800, 43200], [46800, 64800]], ...}, ...} # 설정한 값이 반환됩니다.

reset()

InferenceHandler의 상태를 초기화합니다.

Usage
handler.reset()

get_depth_fitting_preview(image, surface_points)

이미지에 depth fitting preview를 적용합니다.

Parameters:

Name Type Description Default
image ndarray

depth fitting preview를 적용할 이미지, shape: (H, W, C)

required
surface_points list[list[int]]

depth fitting을 위한 reference surface points.

required

Returns:

Type Description
ndarray

np.ndarray: depth fitting preview가 적용된 이미지

Raises:

Type Description
InsufficientSurfacePointsError

surface_points의 개수가 3개 미만인 경우 발생하는 에러

Usage
import cv2
image = cv2.imread("image.jpg")
surface_points = [[100, 100], [200, 100], [150, 200]]
err, msg, preview = handler.get_depth_fitting_preview(image, surface_points)
cv2.imwrite("preview.jpg", preview)