Spaces:
Sleeping
Sleeping
| # FrameProcessor/graph/steps/extract_features.py | |
| import os | |
| import cv2 | |
| import base64 | |
| import numpy as np | |
| from PIL import Image | |
| from io import BytesIO | |
| from typing import Dict, Any | |
| from langgraph.graph import StateGraph, END | |
| from types_.state import GraphState | |
| def extract_frame_features(state: GraphState) -> GraphState: | |
| """Extracts visual features from the frame image.""" | |
| frame_path = state["frame_path"] | |
| try: | |
| img = cv2.imread(frame_path) | |
| if img is None: | |
| state["frame_features"] = {"error": "Failed to load frame"} | |
| state["next_step"] = "evaluate_importance" | |
| return state | |
| height, width, channels = img.shape | |
| gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| contrast = np.std(gray) | |
| brightness = np.mean(gray) | |
| dark_pixels = np.sum(gray < 30) / (height * width) | |
| color_variance = np.var(img.reshape(-1, 3), axis=0).sum() | |
| face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') | |
| faces = face_cascade.detectMultiScale(gray, 1.1, 4) | |
| has_faces = len(faces) > 0 | |
| state["frame_features"] = { | |
| "dimensions": {"height": height, "width": width}, | |
| "contrast": float(contrast), | |
| "brightness": float(brightness), | |
| "dark_ratio": float(dark_pixels), | |
| "color_variance": float(color_variance), | |
| "has_faces": has_faces, | |
| "face_count": len(faces), | |
| } | |
| # Convert to base64 | |
| pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) | |
| buffered = BytesIO() | |
| pil_img.save(buffered, format="JPEG") | |
| img_str = base64.b64encode(buffered.getvalue()).decode("utf-8") | |
| state["frame_data"] = { | |
| "base64_image": img_str, | |
| "file_name": os.path.basename(frame_path) | |
| } | |
| except Exception as e: | |
| print(f"Error extracting frame features: {str(e)}") | |
| state["frame_features"] = {"error": f"Feature extraction failed: {str(e)}"} | |
| state["frame_data"] = {"file_name": os.path.basename(frame_path)} | |
| state["next_step"] = "evaluate_importance" | |
| return state | |