| import gc |
| import os |
| from app.llm import load_yolo |
| import cv2 |
|
|
| from app.config import FRAME_SKIP_YOLO, FRAME_OUTPUT_PATH |
| from app.logger import log |
|
|
| def extract_motion_and_frame(video_path, logger=None): |
| yolo_model = load_yolo() |
| cap = cv2.VideoCapture(video_path) |
|
|
| prev_center = None |
| movements = [] |
| saved_frame = None |
|
|
| frame_count = 0 |
|
|
| try: |
| log(f"Abrindo vídeo: {video_path}", level="info", logger=logger) |
| while True: |
| ret, frame = cap.read() |
| if not ret: |
| break |
|
|
| if frame_count % FRAME_SKIP_YOLO != 0: |
| frame_count += 1 |
| continue |
|
|
| results = yolo_model( |
| frame, |
| imgsz=640, |
| conf=0.4, |
| max_det=50, |
| verbose=False) |
|
|
| for r in results: |
| for box in r.boxes: |
| if int(box.cls[0]) == 0: |
| x1, y1, x2, y2 = box.xyxy[0].tolist() |
| |
| center = ((x1 + x2) / 2, (y1 + y2) / 2) |
|
|
| if prev_center: |
| dist = ((center[0]-prev_center[0])**2 + (center[1]-prev_center[1])**2) ** 0.5 |
| movements.append(dist) |
|
|
| prev_center = center |
| saved_frame = frame |
|
|
| frame_count += 1 |
| finally: |
| log("Liberando recursos do vídeo", level="info", logger=logger) |
| cap.release() |
| del yolo_model |
| gc.collect() |
|
|
| if saved_frame is not None: |
| cv2.imwrite(FRAME_OUTPUT_PATH, saved_frame) |
| log(f"Frame salvo para análise de emoção: {FRAME_OUTPUT_PATH}", level="info", logger=logger) |
|
|
| try: |
| cv2.destroyAllWindows() |
| except: |
| pass |
|
|
| motion = sum(movements)/len(movements) if movements else 0 |
| log(f"Movimento médio: {motion}", level="info", logger=logger) |
|
|
| return motion |