-
-
Save rescenic/8942e8763df05cbb755cc9c249846ff2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import face_recognition | |
import cv2 | |
import numpy as np | |
import argparse | |
import os | |
def apply_blur(image, region, light_blur=False): | |
"""Menerapkan efek blur dengan intensitas berbeda""" | |
try: | |
top, right, bottom, left = region | |
# Pastikan region valid | |
if top >= bottom or left >= right: | |
return image | |
# Ekstrak region | |
region_img = image[top:bottom, left:right] | |
if region_img.size > 0: | |
# Blur kuat untuk wajah, blur ringan untuk background | |
if light_blur: | |
# Blur ringan (nilai kernel kecil) | |
blurred = cv2.GaussianBlur(region_img, (15, 15), 5) | |
else: | |
# Blur sangat kuat sampai tidak terlihat | |
for _ in range(3): # Triple blur untuk efek lebih kuat | |
blurred = cv2.GaussianBlur(region_img, (99, 99), 30) | |
region_img = blurred | |
image[top:bottom, left:right] = blurred | |
except Exception as e: | |
print(f"⚠️ Peringatan: Gagal memproses blur: {str(e)}") | |
return image | |
def get_face_info(image, model='hog'): | |
"""Deteksi wajah dan dapatkan encoding""" | |
face_locations = face_recognition.face_locations(image, model=model) | |
if not face_locations: | |
return None, None | |
if len(face_locations) > 1: | |
print(f"⚠️ Peringatan: Ditemukan lebih dari satu wajah. Akan menggunakan wajah pertama.") | |
encoding = face_recognition.face_encodings(image, known_face_locations=[face_locations[0]])[0] | |
return encoding, face_locations[0] | |
def classify_similarity(distance): | |
"""Mengklasifikasikan kemiripan wajah berdasarkan jarak""" | |
if distance < 0.5: | |
return "SANGAT MIRIP", (0, 255, 0) # Hijau | |
elif distance < 0.6: | |
return "MIRIP", (0, 255, 255) # Kuning | |
elif distance < 0.7: | |
return "TIDAK MIRIP", (0, 165, 255) # Oranye | |
else: | |
return "SANGAT BERBEDA", (0, 0, 255) # Merah | |
def draw_info(image, text_lines, color, line_height=30): | |
"""Menambahkan teks dengan latar belakang pada gambar""" | |
y = image.shape[0] - (len(text_lines) * line_height) + 20 | |
for line in text_lines: | |
text_size = cv2.getTextSize(line, cv2.FONT_HERSHEY_SIMPLEX, 0.8, 2)[0] | |
cv2.rectangle(image, (0, y-25), (text_size[0]+10, y+10), (0, 0, 0), -1) | |
cv2.putText(image, line, (10, y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2) | |
y += line_height | |
return image | |
def process_image(image_path, model='hog', blur_faces=False): | |
"""Memuat dan memproses gambar dengan blur selektif""" | |
try: | |
img = cv2.imread(image_path) | |
if img is None: | |
raise ValueError(f"Format gambar tidak didukung atau file rusak: {image_path}") | |
image_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) | |
encoding, face_location = get_face_info(image_rgb, model) | |
if encoding is None: | |
raise ValueError(f"Tidak terdeteksi wajah pada {image_path}") | |
if blur_faces: | |
# Blur seluruh gambar sedikit (background) | |
img = apply_blur(img, (0, img.shape[1], img.shape[0], 0), light_blur=True) | |
# Blur wajah sangat kuat | |
if face_location: | |
img = apply_blur(img, face_location, light_blur=False) | |
return img, encoding, face_location | |
except Exception as e: | |
raise ValueError(f"Gagal memproses gambar {image_path}: {str(e)}") | |
def main(): | |
parser = argparse.ArgumentParser(description="Alat Perbandingan Wajah dengan Blur Privasi") | |
parser.add_argument("known_image", help="Path ke gambar wajah referensi") | |
parser.add_argument("test_image", help="Path ke gambar wajah uji") | |
parser.add_argument("-o", "--output", help="Simpan hasil ke file") | |
parser.add_argument("-m", "--model", choices=['hog', 'cnn'], default='hog', | |
help="Model deteksi wajah (hog lebih cepat, cnn lebih akurat)") | |
parser.add_argument("-b", "--blur", action='store_true', | |
help="Aktifkan mode privasi: wajah blur kuat, background blur ringan") | |
args = parser.parse_args() | |
try: | |
img1, enc1, loc1 = process_image(args.known_image, args.model, args.blur) | |
img2, enc2, loc2 = process_image(args.test_image, args.model, args.blur) | |
except Exception as e: | |
print(f"❌ Error: {e}") | |
return | |
# Hitung kemiripan | |
distance = face_recognition.face_distance([enc1], enc2)[0] | |
similarity = (1 - distance) * 100 | |
label, color = classify_similarity(distance) | |
# Gambar kotak deteksi (jika tidak dalam mode blur) | |
if not args.blur: | |
for img, loc in [(img1, loc1), (img2, loc2)]: | |
if loc: | |
top, right, bottom, left = loc | |
cv2.rectangle(img, (left, top), (right, bottom), color, 4) | |
# Gabungkan gambar | |
max_height = 600 | |
img1 = resize_image(img1, max_height) if img1 is not None else None | |
img2 = resize_image(img2, max_height) if img2 is not None else None | |
if img1 is not None and img2 is not None: | |
combined = np.hstack((img1, img2)) | |
# Tambahkan info teks dengan warna sesuai klasifikasi | |
info_lines = [ | |
f"Jarak: {distance:.4f}", | |
f"Kemiripan: {similarity:.2f}%", | |
f"Klasifikasi: {label}", | |
"Mode Privasi: AKTIF" if args.blur else "Mode Privasi: NON-AKTIF" | |
] | |
combined = draw_info(combined, info_lines, color) | |
# Tampilkan atau simpan hasil | |
if args.output: | |
cv2.imwrite(args.output, combined) | |
print(f"✅ Hasil disimpan ke {args.output}") | |
else: | |
cv2.imshow("Hasil Perbandingan Wajah", combined) | |
cv2.waitKey(0) | |
cv2.destroyAllWindows() | |
else: | |
print("❌ Tidak dapat memproses gambar. Pastikan kedua gambar berisi wajah yang terdeteksi.") | |
def resize_image(image, target_height): | |
"""Mengubah ukuran gambar secara proporsional ke tinggi target""" | |
if image is None: | |
return None | |
h, w = image.shape[:2] | |
ratio = target_height / h | |
return cv2.resize(image, (int(w * ratio), target_height), interpolation=cv2.INTER_AREA) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment