From d2a84c1da045fdbf7326d2ea1846f95259bba4c8 Mon Sep 17 00:00:00 2001 From: jwkim Date: Wed, 4 Mar 2026 16:54:28 +0900 Subject: [PATCH] =?UTF-8?q?edit=20:=20ward=5Fid=20=EC=A0=81=EC=9A=A9=20(?= =?UTF-8?q?=EC=A0=95=EC=9D=98=EB=90=9C=20=EC=83=81=EC=88=98=EA=B0=92=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cctv.py | 43 ++++++++++++++++++++++++++++++++++--------- config.yaml | 19 +++++++++++++++++-- parsing_msg.py | 10 +++++++--- schema.py | 4 ++-- 4 files changed, 60 insertions(+), 16 deletions(-) diff --git a/cctv.py b/cctv.py index 19cb672..79e5152 100644 --- a/cctv.py +++ b/cctv.py @@ -116,12 +116,14 @@ class CameraStream: print(f"[{self.name}] 재접속 실패") def get_frame(self): - """현재 저장된 가장 최신 프레임을 반환 (타임아웃 체크 포함)""" + """ + 현재 저장된 가장 최신 프레임을 반환 (타임아웃 체크 포함) + """ with self.lock: # 마지막 수신 후 3초 이상 지났으면 신호 없음(False) 처리 if time.time() - self.last_read_time > 3.0: - return False, None - return self.ret, self.latest_frame + return False, None, self.name + return self.ret, self.latest_frame, self.name def stop(self): self.running = False @@ -153,6 +155,8 @@ def main(): DISPLAY_TURN_ON = CFG.get('display').get('turn_on') # display 출력 여부 + SNAPSHOT_SEND = CFG.get('img_snap_shot') + current_cam_index = 0 # 현재 보고 있는 카메라 인덱스 last_switch_time = time.time() # 마지막 전환 시간 switch_interval = SWITCH_INTERVAL # 5초마다 자동 전환 @@ -167,6 +171,10 @@ def main(): fps_sum = 0 fps_count = 0 warmup_frames = 30 # 초반 불안정한 프레임 제외 + + # pubilsh time check + last_publish_time = None + delay_after_publish = 4.0 # publish 후 n초 동안은 추가 publish 금지, 0일경우 무제한 print("\n=== CCTV 시스템 시작 ===") print(f"{switch_interval}초마다 자동으로 카메라가 전환됩니다.") @@ -212,7 +220,7 @@ def main(): # 2. 현재 선택된 카메라의 최신 프레임 가져오기 target_cam = cameras[current_cam_index] - ret, frame = target_cam.get_frame() + ret, frame, name = target_cam.get_frame() if ret and frame is not None: # FPS 계산 @@ -248,13 +256,31 @@ def main(): od_message = [] - parser.set(msg=hpe_message,img=frame) + parser.set( + msg=hpe_message, + img=frame if SNAPSHOT_SEND else None, + ward_id=name) parsing_msg = parser.parse() #mqtt publish if parsing_msg is not None: - mqtt_publisher.client.publish(MQTT_TOPIC, parsing_msg, qos=1) - + + #time check + if last_publish_time is None: + last_publish_time = datetime.now() + mqtt_publisher.client.publish(MQTT_TOPIC, parsing_msg, qos=1) + else: + current_time = datetime.now() + time_diff = current_time - last_publish_time + time_diff_seconds = time_diff.total_seconds() + + # n초에 한 번만 publish + if time_diff_seconds < delay_after_publish: + pass + else: + last_publish_time = datetime.now() + mqtt_publisher.client.publish(MQTT_TOPIC, parsing_msg, qos=1) + # 탐지 결과 라벨링 (원본 좌표 기준) if DISPLAY_TURN_ON: detector.hpe_labeling(frame, hpe_message) @@ -298,8 +324,7 @@ def main(): cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 255), 2, cv2.LINE_AA) # 노란색 cv2.imshow(window_name, frame) - - + elif DISPLAY_TURN_ON: # 신호가 없을 때 보여줄 대기 화면 # MONITOR_RESOLUTION은 (width, height)이므로 numpy shape는 (height, width, 3)이어야 함 diff --git a/config.yaml b/config.yaml index bcafb6b..d7db4f1 100644 --- a/config.yaml +++ b/config.yaml @@ -16,6 +16,7 @@ use_hpe_frame_check: false # n개 프레임 체크 후 HPE 위험 판단 # --- 디버그 --- add_cross_arm: false # cross arm 디버그 모드 +img_snap_shot: false # 이미지 스냅샷 전송 여부 # --- 소스 설정 --- # RTSP 카메라 프리셋 (source에서 프리셋 이름으로 사용 가능) @@ -75,8 +76,8 @@ cctv: # - {src: 0, name: "Realtek_Webcam_0"} # - {src: "rtsp://daool:Ekdnfeldpsdptm1@192.168.200.101/axis-media/media.amp", name: "ipcam_1"} # - {src: "rtsp://daool:Ekdnfeldpsdptm1@192.168.200.102/axis-media/media.amp", name: "ipcam_2"} - - {src: "rtsp://192.168.200.231:50199/wd", name: "dev1_stream"} - - {src: "rtsp://192.168.200.232:50299/wd", name: "dev2_stream"} + # - {src: "rtsp://192.168.200.231:50199/wd", name: "dev1_stream"} + # - {src: "rtsp://192.168.200.232:50299/wd", name: "dev2_stream"} # - {src: "rtsp://192.168.200.236:8554/videodevice", name: "boss_webcam"} # - {src: "rtsp://192.168.200.236:8554/1.mp4", name: "boss_stream1"} # - {src: "rtsp://192.168.200.214/1.mp4", name: "sgm_stream1"} @@ -85,3 +86,17 @@ cctv: # - {src: "rtsp://192.168.200.111/2.mp4", name: "hp_stream2"} # - {src: "rtsp://192.168.200.215/1.mp4", name: "msk_stream1"} # - {src: "rtsp://192.168.200.215/2.mp4", name: "msk_stream2"} + + - {src: "rtsp://192.168.200.233:50399/h1", name: "dev3_stream_hospital_1"} + - {src: "rtsp://192.168.200.233:50399/h2", name: "dev3_stream_hospital_2"} + - {src: "rtsp://192.168.200.233:50399/h3", name: "dev3_stream_hospital_3"} + - {src: "rtsp://192.168.200.233:50399/h4", name: "dev3_stream_hospital_4"} + - {src: "rtsp://192.168.200.233:50399/h5", name: "dev3_stream_hospital_5"} + - {src: "rtsp://192.168.200.233:50399/h6", name: "dev3_stream_hospital_6"} + + # - {src: "rtsp://192.168.200.233:50399/k1", name: "dev3_stream_kepco_1"} + # - {src: "rtsp://192.168.200.233:50399/k2", name: "dev3_stream_kepco_2"} + # - {src: "rtsp://192.168.200.233:50399/k3", name: "dev3_stream_kepco_3"} + # - {src: "rtsp://192.168.200.233:50399/k4", name: "dev3_stream_kepco_4"} + # - {src: "rtsp://192.168.200.233:50399/k5", name: "dev3_stream_kepco_5"} + # - {src: "rtsp://192.168.200.233:50399/k6", name: "dev3_stream_kepco_6"} \ No newline at end of file diff --git a/parsing_msg.py b/parsing_msg.py index cf807f3..6c3abd4 100644 --- a/parsing_msg.py +++ b/parsing_msg.py @@ -11,14 +11,18 @@ class ParsingMsg(): def __init__(self): self.msg = None self.img = None + self.ward_id = None + self.parsed_msg = None - def set(self, msg:list, img): + def set(self, msg:list, img, ward_id): self.msg = None self.img = None + self.ward_id = None self.msg = msg self.img = img + self.ward_id = ward_id self.parsed_msg = None def get(self): @@ -33,7 +37,7 @@ class ParsingMsg(): """ _, JPEG = cv2.imencode(".jpg", img_data, [int(cv2.IMWRITE_JPEG_QUALITY), 80]) # Base64 encode - b64 = b64encode(JPEG) + b64 = b64encode(JPEG.tobytes()) return b64.decode("utf-8") @@ -54,7 +58,7 @@ class ParsingMsg(): """ msg = Header( camera_id= "CAMERA_001", - ward_id= "WARD_001", + ward_id= self.ward_id, timestamp= datetime.now().strftime("%Y-%m-%d %H:%M:%S"), frame_id= 0 ) diff --git a/schema.py b/schema.py index 5f93336..ecb1583 100644 --- a/schema.py +++ b/schema.py @@ -7,8 +7,8 @@ from datetime import datetime #========================================= class Header(BaseModel): camera_id: str - ward_id: str - timestamp: datetime + ward_id: str | None + timestamp: str frame_id: int #=========================================