Spaces:
Running
Running
Download utils/frame_processor.py from adidtiya/deepfake-shield-api: direct link, hf CLI and curl.
- Browser
- Download file 3.76 kB
-
https://huggingface.co/spaces/adidtiya/deepfake-shield-api/resolve/main/utils/frame_processor.py
- Command line
-
hf download hf://spaces/adidtiya/deepfake-shield-api/utils/frame_processor.py
-
curl -L -o frame_processor.py https://huggingface.co/spaces/adidtiya/deepfake-shield-api/resolve/main/utils/frame_processor.py
3.76 kB
| """ | |
| frame_processor.py | |
| ================== | |
| Utilitas untuk preprocessing frame video sebelum dimasukkan ke model. | |
| Termasuk: resize, quality enhancement, dan konversi format. | |
| """ | |
| import cv2 | |
| import numpy as np | |
| from typing import Tuple, Optional | |
| def decode_base64_frame(b64_string: str) -> Optional[np.ndarray]: | |
| """ | |
| Decode string base64 menjadi frame OpenCV BGR. | |
| Args: | |
| b64_string: String base64 (dengan atau tanpa data URL prefix) | |
| Returns: | |
| numpy array [H, W, 3] BGR, atau None jika gagal | |
| """ | |
| import base64 | |
| # Hapus prefix data URL jika ada | |
| if "," in b64_string: | |
| b64_string = b64_string.split(",", 1)[1] | |
| try: | |
| # Decode base64 → bytes → numpy | |
| raw_bytes = base64.b64decode(b64_string) | |
| arr = np.frombuffer(raw_bytes, dtype=np.uint8) | |
| frame = cv2.imdecode(arr, cv2.IMREAD_COLOR) | |
| return frame | |
| except Exception: | |
| return None | |
| def preprocess_frame( | |
| frame: np.ndarray, | |
| target_size: Tuple[int, int] = (640, 480), | |
| enhance_quality: bool = True | |
| ) -> np.ndarray: | |
| """ | |
| Preprocess frame video untuk optimasi deteksi. | |
| Args: | |
| frame : Frame BGR dari OpenCV | |
| target_size : (width, height) target untuk resize | |
| enhance_quality: Terapkan CLAHE untuk perbaikan kontras | |
| Returns: | |
| Frame BGR yang sudah dipreprocess | |
| """ | |
| # Resize frame jika terlalu besar (menghemat waktu proses) | |
| h, w = frame.shape[:2] | |
| target_w, target_h = target_size | |
| # Hanya resize jika lebih besar dari target | |
| if w > target_w or h > target_h: | |
| frame = cv2.resize(frame, target_size, interpolation=cv2.INTER_LINEAR) | |
| # CLAHE (Contrast Limited Adaptive Histogram Equalization) | |
| # Meningkatkan kontras lokal untuk membantu deteksi wajah | |
| if enhance_quality: | |
| lab = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB) # Konversi ke LAB color space | |
| l_channel, a, b = cv2.split(lab) | |
| # Terapkan CLAHE hanya pada channel L (luminance/kecerahan) | |
| clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) | |
| l_enhanced = clahe.apply(l_channel) | |
| # Gabungkan kembali channel | |
| enhanced_lab = cv2.merge([l_enhanced, a, b]) | |
| frame = cv2.cvtColor(enhanced_lab, cv2.COLOR_LAB2BGR) | |
| return frame | |
| def draw_detection_overlay( | |
| frame: np.ndarray, | |
| face_boxes: list, | |
| label: str, | |
| score: float | |
| ) -> np.ndarray: | |
| """ | |
| Gambar bounding box dan label deteksi di atas frame. | |
| Args: | |
| frame : Frame BGR | |
| face_boxes: List of [x, y, w, h] dalam piksel | |
| label : Label deteksi ('REAL', 'FAKE', 'UNCERTAIN') | |
| score : Skor keaslian (0.0 - 1.0) | |
| Returns: | |
| Frame dengan overlay | |
| """ | |
| # Pilih warna berdasarkan label | |
| color_map = { | |
| "REAL" : (0, 255, 100), # Hijau neon | |
| "FAKE" : (0, 50, 255), # Merah | |
| "UNCERTAIN": (0, 165, 255), # Oranye | |
| "NO_FACE" : (128, 128, 128), # Abu-abu | |
| } | |
| color = color_map.get(label, (255, 255, 255)) | |
| # Gambar bounding box untuk setiap wajah | |
| for (x, y, w, h) in face_boxes: | |
| # Bounding box utama | |
| cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2) | |
| # Label teks di atas bounding box | |
| label_text = f"{label} {score:.0%}" | |
| cv2.putText( | |
| frame, label_text, | |
| (x, max(y - 10, 10)), # Posisi: di atas bbox, minimal y=10 | |
| cv2.FONT_HERSHEY_SIMPLEX, # Font | |
| 0.7, # Scale | |
| color, # Warna | |
| 2, # Tebal | |
| cv2.LINE_AA # Anti-aliasing | |
| ) | |
| return frame | |