Enforce 90% face similarity for live webcam swaps; only swap if match is high. Improves accuracy and prevents mismatched swaps.
							parent
							
								
									ba008e72eb
								
							
						
					
					
						commit
						ea59ef7635
					
				| 
						 | 
					@ -28,6 +28,10 @@ FACE_SWAPPER = None
 | 
				
			||||||
THREAD_LOCK = threading.Lock()
 | 
					THREAD_LOCK = threading.Lock()
 | 
				
			||||||
NAME = "DLC.FACE-SWAPPER"
 | 
					NAME = "DLC.FACE-SWAPPER"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add a face similarity threshold (90%) for live webcam swaps.
 | 
				
			||||||
 | 
					# Only swap if the cosine similarity between source and detected face is above threshold.
 | 
				
			||||||
 | 
					FACE_SIMILARITY_THRESHOLD = 0.90  # Only swap if similarity > 90%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
abs_dir = os.path.dirname(os.path.abspath(__file__))
 | 
					abs_dir = os.path.dirname(os.path.abspath(__file__))
 | 
				
			||||||
models_dir = os.path.join(
 | 
					models_dir = os.path.join(
 | 
				
			||||||
    os.path.dirname(os.path.dirname(os.path.dirname(abs_dir))), "models"
 | 
					    os.path.dirname(os.path.dirname(os.path.dirname(abs_dir))), "models"
 | 
				
			||||||
| 
						 | 
					@ -276,6 +280,11 @@ def _process_live_target_v2(source_frame_full: Frame, temp_frame: Frame) -> Fram
 | 
				
			||||||
                face_id = id(target_face)
 | 
					                face_id = id(target_face)
 | 
				
			||||||
                if face_id in swapped_faces:
 | 
					                if face_id in swapped_faces:
 | 
				
			||||||
                    continue
 | 
					                    continue
 | 
				
			||||||
 | 
					                # Similarity check for many_faces mode
 | 
				
			||||||
 | 
					                if hasattr(source_face_obj, 'normed_embedding') and hasattr(target_face, 'normed_embedding'):
 | 
				
			||||||
 | 
					                    similarity = float(np.dot(source_face_obj.normed_embedding, target_face.normed_embedding))
 | 
				
			||||||
 | 
					                    if similarity < FACE_SIMILARITY_THRESHOLD:
 | 
				
			||||||
 | 
					                        continue  # Skip if not similar enough
 | 
				
			||||||
                temp_frame = swap_face(source_face_obj, target_face, source_frame_full, temp_frame)
 | 
					                temp_frame = swap_face(source_face_obj, target_face, source_frame_full, temp_frame)
 | 
				
			||||||
                swapped_faces.add(face_id)
 | 
					                swapped_faces.add(face_id)
 | 
				
			||||||
    else: # not many_faces (apply simple_map logic)
 | 
					    else: # not many_faces (apply simple_map logic)
 | 
				
			||||||
| 
						 | 
					@ -293,6 +302,11 @@ def _process_live_target_v2(source_frame_full: Frame, temp_frame: Frame) -> Fram
 | 
				
			||||||
                closest_centroid_index, _ = find_closest_centroid(target_embeddings, detected_face.normed_embedding)
 | 
					                closest_centroid_index, _ = find_closest_centroid(target_embeddings, detected_face.normed_embedding)
 | 
				
			||||||
                if closest_centroid_index < len(source_faces_from_map):
 | 
					                if closest_centroid_index < len(source_faces_from_map):
 | 
				
			||||||
                    source_face_obj_from_map = source_faces_from_map[closest_centroid_index]
 | 
					                    source_face_obj_from_map = source_faces_from_map[closest_centroid_index]
 | 
				
			||||||
 | 
					                    # Similarity check for mapped faces
 | 
				
			||||||
 | 
					                    if hasattr(source_face_obj_from_map, 'normed_embedding') and hasattr(detected_face, 'normed_embedding'):
 | 
				
			||||||
 | 
					                        similarity = float(np.dot(source_face_obj_from_map.normed_embedding, detected_face.normed_embedding))
 | 
				
			||||||
 | 
					                        if similarity < FACE_SIMILARITY_THRESHOLD:
 | 
				
			||||||
 | 
					                            continue  # Skip if not similar enough
 | 
				
			||||||
                    temp_frame = swap_face(source_face_obj_from_map, detected_face, source_frame_full, temp_frame)
 | 
					                    temp_frame = swap_face(source_face_obj_from_map, detected_face, source_frame_full, temp_frame)
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    logging.warning(f"Centroid index {closest_centroid_index} out of bounds for source_faces_from_map.")
 | 
					                    logging.warning(f"Centroid index {closest_centroid_index} out of bounds for source_faces_from_map.")
 | 
				
			||||||
| 
						 | 
					@ -303,6 +317,11 @@ def _process_live_target_v2(source_frame_full: Frame, temp_frame: Frame) -> Fram
 | 
				
			||||||
                    closest_detected_face_index, _ = find_closest_centroid(detected_faces_embeddings, target_embedding)
 | 
					                    closest_detected_face_index, _ = find_closest_centroid(detected_faces_embeddings, target_embedding)
 | 
				
			||||||
                    source_face_obj_from_map = source_faces_from_map[i]
 | 
					                    source_face_obj_from_map = source_faces_from_map[i]
 | 
				
			||||||
                    target_face_to_swap = detected_faces[closest_detected_face_index]
 | 
					                    target_face_to_swap = detected_faces[closest_detected_face_index]
 | 
				
			||||||
 | 
					                    # Similarity check for mapped faces
 | 
				
			||||||
 | 
					                    if hasattr(source_face_obj_from_map, 'normed_embedding') and hasattr(target_face_to_swap, 'normed_embedding'):
 | 
				
			||||||
 | 
					                        similarity = float(np.dot(source_face_obj_from_map.normed_embedding, target_face_to_swap.normed_embedding))
 | 
				
			||||||
 | 
					                        if similarity < FACE_SIMILARITY_THRESHOLD:
 | 
				
			||||||
 | 
					                            continue  # Skip if not similar enough
 | 
				
			||||||
                    temp_frame = swap_face(source_face_obj_from_map, target_face_to_swap, source_frame_full, temp_frame)
 | 
					                    temp_frame = swap_face(source_face_obj_from_map, target_face_to_swap, source_frame_full, temp_frame)
 | 
				
			||||||
                    # Optionally, remove the swapped detected face to prevent re-swapping if one source maps to multiple targets.
 | 
					                    # Optionally, remove the swapped detected face to prevent re-swapping if one source maps to multiple targets.
 | 
				
			||||||
                    # This depends on desired behavior. For now, simple independent mapping.
 | 
					                    # This depends on desired behavior. For now, simple independent mapping.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue