VeuReu commited on
Commit
2b00691
·
verified ·
1 Parent(s): ef78bba

Upload 4 files

Browse files
Files changed (1) hide show
  1. character_detection.py +61 -91
character_detection.py CHANGED
@@ -16,18 +16,22 @@ from sklearn.cluster import DBSCAN
16
  import numpy as np
17
  from typing import List, Dict, Any, Tuple
18
 
19
- # Imports de las herramientas de vision y audio
20
- # Nota: Estos imports asumen que los archivos están en originales/
21
- # y que tienen las dependencias necesarias instaladas
22
  try:
23
- import sys
24
- sys.path.insert(0, str(Path(__file__).parent / "originales"))
25
- from vision_tools_salamandra_2 import FaceOfImageEmbedding_video_nuevo, ImageEmbedding, keyframe_conditional_extraction_ana
26
- from audio_tools_ana_2 import extract_audio_ffmpeg, diarize_audio, embed_voice_segments
27
- TOOLS_AVAILABLE = True
28
  except Exception as e:
29
- TOOLS_AVAILABLE = False
30
- logging.warning(f"No se pudieron importar las herramientas de Ana: {e}")
 
 
 
 
 
 
 
 
31
 
32
  logging.basicConfig(level=logging.INFO)
33
  logger = logging.getLogger(__name__)
@@ -58,19 +62,21 @@ class CharacterDetector:
58
 
59
  def extract_faces_embeddings(self) -> List[Dict[str, Any]]:
60
  """
61
- Extrae caras del vídeo y calcula sus embeddings.
62
- Basado en faces_embedding_extraction de Ana.
63
 
64
  Returns:
65
  Lista de dicts con {"embeddings": [...], "path": "..."}
66
  """
67
- if not TOOLS_AVAILABLE:
68
- logger.warning("Herramientas no disponibles, retornando lista vacía")
69
  return []
70
 
71
  logger.info("Extrayendo caras del vídeo...")
 
 
 
 
72
  extract_every = 1.0 # segundos
73
- embedder = FaceOfImageEmbedding_video_nuevo()
74
  video = cv2.VideoCapture(self.video_path)
75
  fps = int(video.get(cv2.CAP_PROP_FPS))
76
  frame_interval = int(fps * extract_every)
@@ -87,20 +93,40 @@ class CharacterDetector:
87
  if frame_count % frame_interval == 0:
88
  temp_path = self.faces_dir / "temp_frame.jpg"
89
  cv2.imwrite(str(temp_path), frame)
90
- resultados = embedder.encode_image(temp_path)
91
 
92
- if resultados:
93
- for i, r in enumerate(resultados):
94
- embedding = r['embedding']
95
- cara = r['face_crop']
96
- save_path = self.faces_dir / f"frame_{saved_count:04d}.jpg"
97
- cv2.imwrite(str(save_path), cv2.cvtColor(cara, cv2.COLOR_RGB2BGR))
98
- embeddings_caras.append({
99
- "embeddings": embedding,
100
- "path": str(save_path),
101
- "frame": frame_count
102
- })
103
- saved_count += 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
  if temp_path.exists():
106
  os.remove(temp_path)
@@ -114,80 +140,24 @@ class CharacterDetector:
114
  def extract_voices_embeddings(self) -> List[Dict[str, Any]]:
115
  """
116
  Extrae voces del vídeo y calcula sus embeddings.
117
- Basado en voices_embedding_extraction de Ana.
118
 
119
  Returns:
120
  Lista de dicts con {"embeddings": [...], "path": "..."}
121
  """
122
- if not TOOLS_AVAILABLE:
123
- logger.warning("Herramientas no disponibles, retornando lista vacía")
124
- return []
125
-
126
- logger.info("Extrayendo voces del vídeo...")
127
- sr = 16000
128
- fmt = "wav"
129
-
130
- wav_path = extract_audio_ffmpeg(
131
- self.video_path,
132
- self.voices_dir / f"{Path(self.video_path).stem}.{fmt}",
133
- sr=sr
134
- )
135
-
136
- min_dur = 0.5
137
- max_dur = 10.0
138
-
139
- clip_paths, diar_segs = diarize_audio(
140
- wav_path,
141
- self.voices_dir,
142
- "clips",
143
- min_dur,
144
- max_dur
145
- )
146
-
147
- embeddings_voices = []
148
- embeddings = embed_voice_segments(clip_paths)
149
-
150
- for i, emb in enumerate(embeddings):
151
- embeddings_voices.append({
152
- "embeddings": emb,
153
- "path": str(clip_paths[i])
154
- })
155
-
156
- logger.info(f"Voces extraídas: {len(embeddings_voices)}")
157
- return embeddings_voices
158
 
159
  def extract_scenes_embeddings(self) -> List[Dict[str, Any]]:
160
  """
161
- Extrae escenas clave del vídeo y calcula sus embeddings.
162
- Basado en scenes_embedding_extraction de Ana.
163
 
164
  Returns:
165
  Lista de dicts con {"embeddings": [...], "path": "..."}
166
  """
167
- if not TOOLS_AVAILABLE:
168
- logger.warning("Herramientas no disponibles, retornando lista vacía")
169
- return []
170
-
171
- logger.info("Extrayendo escenas del vídeo...")
172
- keyframes_final = keyframe_conditional_extraction_ana(
173
- video_path=self.video_path,
174
- output_dir=self.scenes_dir,
175
- threshold=30.0,
176
- )
177
-
178
- image_embedder = ImageEmbedding()
179
- embeddings_escenas = []
180
-
181
- for keyframe in keyframes_final:
182
- frame_path = keyframe["path"]
183
- embedding = image_embedder.encode_image(frame_path)
184
- embeddings_escenas.append({
185
- "embeddings": embedding,
186
- "path": str(frame_path)
187
- })
188
-
189
- logger.info(f"Escenas extraídas: {len(embeddings_escenas)}")
190
- return embeddings_escenas
191
 
192
  def cluster_faces(self, embeddings_caras: List[Dict], epsilon: float, min_samples: int) -> np.ndarray:
193
  """
 
16
  import numpy as np
17
  from typing import List, Dict, Any, Tuple
18
 
19
+ # Imports de las herramientas de vision y audio desde los módulos de la raíz
 
 
20
  try:
21
+ # Vision tools del engine (ya incluye DeepFace y face_recognition)
22
+ from vision_tools import FaceOfImageEmbedding
23
+ VISION_TOOLS_AVAILABLE = True
 
 
24
  except Exception as e:
25
+ VISION_TOOLS_AVAILABLE = False
26
+ logging.warning(f"Vision tools no disponibles: {e}")
27
+
28
+ try:
29
+ # Audio tools del engine
30
+ from audio_tools import extract_audio_ffmpeg_simple, diarize_with_pyannote, get_speaker_embeddings
31
+ AUDIO_TOOLS_AVAILABLE = True
32
+ except Exception as e:
33
+ AUDIO_TOOLS_AVAILABLE = False
34
+ logging.warning(f"Audio tools no disponibles: {e}")
35
 
36
  logging.basicConfig(level=logging.INFO)
37
  logger = logging.getLogger(__name__)
 
62
 
63
  def extract_faces_embeddings(self) -> List[Dict[str, Any]]:
64
  """
65
+ Extrae caras del vídeo y calcula sus embeddings usando FaceOfImageEmbedding.
 
66
 
67
  Returns:
68
  Lista de dicts con {"embeddings": [...], "path": "..."}
69
  """
70
+ if not VISION_TOOLS_AVAILABLE:
71
+ logger.warning("Vision tools no disponibles, retornando lista vacía")
72
  return []
73
 
74
  logger.info("Extrayendo caras del vídeo...")
75
+
76
+ # Inicializar el embedder (usa face_recognition o DeepFace automáticamente)
77
+ embedder = FaceOfImageEmbedding(deepface_model='Facenet512')
78
+
79
  extract_every = 1.0 # segundos
 
80
  video = cv2.VideoCapture(self.video_path)
81
  fps = int(video.get(cv2.CAP_PROP_FPS))
82
  frame_interval = int(fps * extract_every)
 
93
  if frame_count % frame_interval == 0:
94
  temp_path = self.faces_dir / "temp_frame.jpg"
95
  cv2.imwrite(str(temp_path), frame)
 
96
 
97
+ try:
98
+ # Extraer embeddings usando FaceOfImageEmbedding
99
+ # Devuelve una lista de embeddings (uno por cada cara detectada)
100
+ embeddings_list = embedder.encode_image(temp_path)
101
+
102
+ if embeddings_list:
103
+ # Si es una lista de listas (múltiples caras)
104
+ if isinstance(embeddings_list[0], list):
105
+ for i, embedding in enumerate(embeddings_list):
106
+ save_path = self.faces_dir / f"frame_{saved_count:04d}.jpg"
107
+ # Guardar el frame completo (la extracción de cara ya se hizo internamente)
108
+ cv2.imwrite(str(save_path), frame)
109
+
110
+ embeddings_caras.append({
111
+ "embeddings": embedding,
112
+ "path": str(save_path),
113
+ "frame": frame_count
114
+ })
115
+ saved_count += 1
116
+ else:
117
+ # Si es un solo embedding
118
+ save_path = self.faces_dir / f"frame_{saved_count:04d}.jpg"
119
+ cv2.imwrite(str(save_path), frame)
120
+
121
+ embeddings_caras.append({
122
+ "embeddings": embeddings_list,
123
+ "path": str(save_path),
124
+ "frame": frame_count
125
+ })
126
+ saved_count += 1
127
+
128
+ except Exception as e:
129
+ logger.debug(f"No se detectaron caras en frame {frame_count}: {e}")
130
 
131
  if temp_path.exists():
132
  os.remove(temp_path)
 
140
  def extract_voices_embeddings(self) -> List[Dict[str, Any]]:
141
  """
142
  Extrae voces del vídeo y calcula sus embeddings.
143
+ Por ahora retorna lista vacía (funcionalidad opcional).
144
 
145
  Returns:
146
  Lista de dicts con {"embeddings": [...], "path": "..."}
147
  """
148
+ logger.info("Extracción de voces deshabilitada temporalmente")
149
+ return []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
  def extract_scenes_embeddings(self) -> List[Dict[str, Any]]:
152
  """
153
+ Extrae escenas clave del vídeo.
154
+ Por ahora retorna lista vacía (funcionalidad opcional).
155
 
156
  Returns:
157
  Lista de dicts con {"embeddings": [...], "path": "..."}
158
  """
159
+ logger.info("Extracción de escenas deshabilitada temporalmente")
160
+ return []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
  def cluster_faces(self, embeddings_caras: List[Dict], epsilon: float, min_samples: int) -> np.ndarray:
163
  """