| |
| import cv2 |
| import tensorflow as tf |
| import time |
| import base64 |
| import datetime |
| import os |
|
|
| |
| MODEL_PATH = os.getenv('MODEL_PATH', 'model') |
| RESOLUTION = int(os.getenv('RESOLUTION', 172)) |
| CONFIDENCE_THRESHOLD = 0.65 |
|
|
| print(f"Loading MoViNet from {MODEL_PATH}...") |
| model = tf.saved_model.load(MODEL_PATH) |
| infer = model.signatures['serving_default'] |
| print("Model loaded!") |
|
|
| def get_init_states(): |
| dummy = tf.zeros([1, 1, RESOLUTION, RESOLUTION, 3], dtype=tf.float32) |
| return model.init_states(tf.shape(dummy)) |
| os.environ["OPENCV_FFMPEG_INTERRUPT_TIMEOUT"] = "60000" |
| os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;tcp" |
| class VideoProcessor: |
| def __init__(self): |
| self.running = False |
|
|
| def start_processing(self, rtsp_url, result_queue): |
| self.running = True |
| print(f"Trying to open: {rtsp_url}") |
| cap = cv2.VideoCapture(rtsp_url, cv2.CAP_FFMPEG) |
| if not cap.isOpened(): |
| result_queue.put({"error": "Cannot open RTSP URL"}) |
| return |
| print("RTSP Stream Opened successfully with TCP!") |
| states = get_init_states() |
| |
| |
| in_event = False |
| event_start_time = None |
| cooldown_counter = 0 |
| COOLDOWN_LIMIT = 30 |
|
|
| while self.running: |
| ret, frame = cap.read() |
| if not ret: |
| break |
|
|
| |
| rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
| resized = tf.image.resize(rgb, [RESOLUTION, RESOLUTION]) |
| input_tensor = tf.cast(resized, tf.float32) / 255.0 |
| input_tensor = input_tensor[tf.newaxis, tf.newaxis, ...] |
|
|
| outputs = infer(image=input_tensor, **states) |
| logits = outputs['logits'] |
| states = {k: v for k, v in outputs.items() if k != 'logits'} |
| probs = tf.nn.softmax(logits, axis=-1)[0] |
| |
| fight_conf = float(probs[0]) |
| norm_conf = float(probs[1]) |
| is_violence = (fight_conf > norm_conf) and (fight_conf > CONFIDENCE_THRESHOLD) |
|
|
| |
| current_time = datetime.datetime.now() |
| msg = None |
|
|
| if is_violence: |
| cooldown_counter = 0 |
| if not in_event: |
| in_event = True |
| event_start_time = current_time |
| |
| |
| small_frame = cv2.resize(frame, (640, 360)) |
| _, buffer = cv2.imencode('.jpg', small_frame) |
| img_base64 = base64.b64encode(buffer).decode('utf-8') |
| |
| msg = { |
| "type": "START", |
| "timestamp": current_time.isoformat(), |
| "score": fight_conf, |
| "image": img_base64 |
| } |
| else: |
| if in_event: |
| cooldown_counter += 1 |
| if cooldown_counter >= COOLDOWN_LIMIT: |
| |
| duration = (current_time - event_start_time).total_seconds() |
| msg = { |
| "type": "END", |
| "timestamp": current_time.isoformat(), |
| "duration": duration |
| } |
| in_event = False |
| |
| |
| if msg: |
| result_queue.put(msg) |
| |
| |
|
|
| cap.release() |
| result_queue.put({"status": "Stream stopped"}) |
|
|