import gradio as gr import numpy as np from PIL import Image import cv2 import dlib import os import warnings warnings.filterwarnings('ignore') # عنوان برنامه TITLE = "🔍 سامانه پیشرفته تشخیص هویت چهره" DESCRIPTION = """ 🎯 سیستم هوشمند تشخیص هویت با استفاده از نقاط کلیدی صورت ✨ امکانات: - تشخیص ۶۸ نقطه کلیدی روی چهره - مقایسه ساختار استخوانی و هندسی صورت - مقاوم در برابر تغییرات نور و آرایش - دقت بسیار بالا با الگوریتم‌های پیشرفته 📌 راهنمایی: 1. تصویر اول را آپلود کنید 2. تصویر دوم را آپلود کنید 3. دقت مورد نظر را انتخاب کنید 4. روی دکمه "تشخیص هویت" کلیک کنید """ # بارگذاری مدل‌های dlib print("🔄 در حال بارگذاری مدل‌های تشخیص چهره...") try: # تشخیص نقاط کلیدی صورت predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat') detector = dlib.get_frontal_face_detector() face_rec_model = dlib.face_recognition_model_v1('dlib_face_recognition_resnet_model_v1.dat') print("✅ مدل‌ها با موفقیت بارگذاری شدند!") MODELS_LOADED = True except Exception as e: print(f"⚠️ مدل‌ها یافت نشدند. از روش جایگزین استفاده می‌کنیم... {e}") MODELS_LOADED = False # تابع تشخیص چهره و نقاط کلیدی با dlib def detect_face_landmarks_dlib(image_array): """تشخیص ۶۸ نقطه کلیدی صورت با dlib""" if not MODELS_LOADED: return None, None, None try: # تشخیص چهره faces = detector(image_array, 1) if len(faces) == 0: return None, None, None # گرفتن اولین چهره face = faces[0] # تشخیص نقاط کلیدی shape = predictor(image_array, face) # استخراج بردار ویژگی چهره face_descriptor = face_rec_model.compute_face_descriptor(image_array, shape) face_encoding = np.array(face_descriptor) # استخراج نقاط کلیدی landmarks = np.array([[p.x, p.y] for p in shape.parts()]) return face, landmarks, face_encoding except Exception as e: print(f"خطا در تشخیص نقاط کلیدی: {e}") return None, None, None # تابع تشخیص چهره جایگزین با OpenCV def detect_face_features_opencv(image_array): """تشخیص ویژگی‌های صورت با OpenCV پیشرفته""" try: # تشخیص چهره gray = cv2.cvtColor(image_array, cv2.COLOR_RGB2GRAY) face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') faces = face_cascade.detectMultiScale(gray, 1.3, 5) if len(faces) == 0: return None, None # گرفتن اولین چهره x, y, w, h = faces[0] face_region = image_array[y:y+h, x:x+w] # استخراج ویژگی‌های پیشرفته # ۱. هیستوگرام گرادیان‌ها (HOG) gray_face = cv2.cvtColor(face_region, cv2.COLOR_RGB2GRAY) gray_face = cv2.resize(gray_face, (64, 128)) # محاسبه گرادیان gx = cv2.Sobel(gray_face, cv2.CV_32F, 1, 0) gy = cv2.Sobel(gray_face, cv2.CV_32F, 0, 1) mag, ang = cv2.cartToPolar(gx, gy) # هیستوگرام گرادیان‌های جهت‌دار bins = np.int32(16 * ang / (2 * np.pi)) bin_cells = bins[:10, :10], bins[10:, :10], bins[:10, 10:], bins[10:, 10:] mag_cells = mag[:10, :10], mag[10:, :10], mag[:10, 10:], mag[10:, 10:] hists = [np.bincount(b.ravel(), m.ravel(), 16) for b, m in zip(bin_cells, mag_cells)] hist = np.hstack(hists) # ۲. ویژگی‌های رنگ و بافت face_resized = cv2.resize(face_region, (64, 64)) # هیستوگرام رنگ color_hist = cv2.calcHist([face_resized], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256]).flatten() color_hist = color_hist[:128] # گرفتن ۱۲۸ مقدار اول # ویژگی‌های آماری mean_color = face_resized.mean(axis=(0, 1)) std_color = face_resized.std(axis=(0, 1)) # ۳. ویژگی‌های الگوی محلی (LBP) lbp_features = extract_lbp_features(gray_face)[:64] # ترکیب تمام ویژگی‌ها features = np.concatenate([ hist / (hist.sum() + 1e-8), # نرمال‌سازی هیستوگرام color_hist / (color_hist.sum() + 1e-8), # نرمال‌سازی هیستوگرام رنگ mean_color / 255, std_color / 255, lbp_features ]) return faces[0], features except Exception as e: print(f"خطا در استخراج ویژگی‌های OpenCV: {e}") return None, None def extract_lbp_features(gray_image): """استخراج ویژگی‌های الگوی محلی باینری (LBP)""" try: # تغییر سایز به اندازه ثابت img = cv2.resize(gray_image, (64, 64)) # محاسبه LBP lbp = np.zeros_like(img, dtype=np.uint8) for i in range(1, img.shape[0]-1): for j in range(1, img.shape[1]-1): center = img[i, j] code = 0 code |= (img[i-1, j-1] >= center) << 7 code |= (img[i-1, j] >= center) << 6 code |= (img[i-1, j+1] >= center) << 5 code |= (img[i, j+1] >= center) << 4 code |= (img[i+1, j+1] >= center) << 3 code |= (img[i+1, j] >= center) << 2 code |= (img[i+1, j-1] >= center) << 1 code |= (img[i, j-1] >= center) << 0 lbp[i, j] = code # هیستوگرام LBP hist, _ = np.histogram(lbp.ravel(), bins=256, range=(0, 256)) return hist except Exception as e: print(f"خطا در استخراج LBP: {e}") return np.zeros(256) # تابع مقایسه پیشرفته def compare_faces_advanced(features1, features2, threshold): """مقایسه پیشرفته دو بردار ویژگی""" if features1 is None or features2 is None: return None, None, "❌ خطا در استخراج ویژگی‌ها" try: # محاسبه فاصله اقلیدسی distance = np.linalg.norm(features1 - features2) # محاسبه شباهت کسینوسی cos_similarity = np.dot(features1, features2) / (np.linalg.norm(features1) * np.linalg.norm(features2) + 1e-10) # محاسبه شباهت کلی similarity = 1.0 / (1.0 + distance) # تصمیم‌گیری is_match = distance <= threshold return distance, similarity, is_match except Exception as e: print(f"خطا در مقایسه: {e}") return None, None, None # تابع رسم نقاط کلیدی def draw_landmarks_on_image(image_array, landmarks, face_rect): """رسم نقاط کلیدی و مستطیل چهره""" img_copy = image_array.copy() # رسم مستطیل دور چهره if face_rect is not None: if hasattr(face_rect, 'left'): # dlib rectangle cv2.rectangle(img_copy, (face_rect.left(), face_rect.top()), (face_rect.right(), face_rect.bottom()), (0, 255, 0), 3) else: # OpenCV rectangle x, y, w, h = face_rect cv2.rectangle(img_copy, (x, y), (x+w, y+h), (0, 255, 0), 3) # رسم نقاط کلیدی if landmarks is not None: for i, (x, y) in enumerate(landmarks): # رنگ‌های مختلف برای نقاط مختلف صورت if i < 17: # خط فک color = (255, 0, 0) elif i < 22: # ابروی راست color = (0, 255, 0) elif i < 27: # ابروی چپ color = (0, 0, 255) elif i < 36: # بینی color = (255, 255, 0) elif i < 48: # چشم‌ها color = (255, 0, 255) else: # دهان color = (0, 255, 255) cv2.circle(img_copy, (int(x), int(y)), 3, color, -1) return img_copy # تابع اصلی پردازش def process_faces(image1, image2, precision_level): """پردازش و مقایسه دو تصویر چهره""" print(f"🔍 شروع پردازش با دقت: {precision_level}") # تبدیل تصاویر به آرایه if isinstance(image1, str): image1_array = np.array(Image.open(image1)) else: image1_array = np.array(image1) if isinstance(image2, str): image2_array = np.array(Image.open(image2)) else: image2_array = np.array(image2) # تنظیم آستانه thresholds = { 'high': 0.4, # دقت بالا 'medium': 0.5, # دقت متوسط 'low': 0.6 # دقت پایین } threshold = thresholds.get(precision_level, 0.5) print(f"🔧 آستانه انتخاب شده: {threshold}") # پردازش تصویر اول print("📸 پردازش تصویر اول...") if MODELS_LOADED: face1, landmarks1, features1 = detect_face_landmarks_dlib(image1_array) if face1 is None: features1 = None else: face1, features1 = detect_face_features_opencv(image1_array) landmarks1 = None # پردازش تصویر دوم print("📸 پردازش تصویر دوم...") if MODELS_LOADED: face2, landmarks2, features2 = detect_face_landmarks_dlib(image2_array) if face2 is None: features2 = None else: face2, features2 = detect_face_features_opencv(image2_array) landmarks2 = None # بررسی خطاها if features1 is None: return "❌ خطا: تشخیص چهره در تصویر اول ناموفق بود!", None, None if features2 is None: return "❌ خطا: تشخیص چهره در تصویر دوم ناموفق بود!", None, None # مقایسه چهره‌ها print("🔄 در حال مقایسه چهره‌ها...") distance, similarity, is_match = compare_faces_advanced(features1, features2, threshold) if distance is None: return "❌ خطا در مقایسه ویژگی‌ها!", None, None # ایجاد تصاویر با نشانگر img1_processed = draw_landmarks_on_image(image1_array, landmarks1, face1) img2_processed = draw_landmarks_on_image(image2_array, landmarks2, face2) # تبدیل به RGB img1_processed = cv2.cvtColor(img1_processed, cv2.COLOR_BGR2RGB) img2_processed = cv2.cvtColor(img2_processed, cv2.COLOR_BGR2RGB) # ایجاد گزارش result_text = f""" 🎯 **نتایج تشخیص هویت چهره** 📊 **آمار فنی:** - فاصله بردار ویژگی: `{distance:.4f}` - میزان شباهت: `{similarity:.4f}` - آستانه انتخابی: `{threshold:.2f}` 🎭 **نتیجه‌گیری:** """ if is_match: if distance < 0.3: confidence = "🔒 **تطبیق با اطمینان بسیار بالا**" elif distance < 0.4: confidence = "✅ **تطبیق با اطمینان بالا**" else: confidence = "✓ **تطبیق با اطمینان متوسط**" result_text += f""" {confidence} 🟢 **این دو تصویر متعلق به یک شخص هستند** _تحلیل سیستم:_ - فاصله محاسبه‌شده ({distance:.4f}) کمتر از آستانه ({threshold:.2f}) است - ساختار صورت و ویژگی‌های کلیدی بسیار مشابه هستند - احتمال اینکه این دو تصویر از یک شخص باشند: **{(1-distance)*100:.1f}%** """ else: if distance > 0.7: confidence = "🔒 **عدم تطبیق با اطمینان بسیار بالا**" else: confidence = "❌ **عدم تطبیق با اطمینان متوسط**" result_text += f""" {confidence} 🔴 **این دو تصویر متعلق به اشخاص مختلف هستند** _تحلیل سیستم:_ - فاصله محاسبه‌شده ({distance:.4f}) بیشتر از آستانه ({threshold:.2f}) است - ساختار صورت و ویژگی‌های کلیدی تفاوت قابل توجهی دارند - شباهت: **{(1-distance)*100:.1f}%** """ result_text += f""" 📈 **جزئیات فنی:** """ if MODELS_LOADED: result_text += "- ✅ استفاده از مدل dlib با ۶۸ نقطه کلیدی\n" else: result_text += "- ⚠️ استفاده از روش OpenCV (دقت کمتر)\n" result_text += f""" - تعداد ویژگی‌های استخراج‌شده: {len(features1)} - روش تشخیص: نقاط کلیدی صورت + ساختار هندسی - دامنه فاصله: ۰ (کاملاً مشابه) تا ۱ (کاملاً متفاوت) 🛠️ **توضیح فنی:** سیستم از نقاط کلیدی صورت (چشم‌ها، بینی، دهان، فک) استفاده می‌کند و ساختار هندسی صورت را با دقت بالا مقایسه می‌کند. """ return result_text, img1_processed, img2_processed # ایجاد رابط Gradio with gr.Blocks(theme=gr.themes.Soft(), title=TITLE) as demo: # هدر برنامه gr.HTML(f"""

{TITLE}

سامانه هوشمند تشخیص هویت با تحلیل نقاط کلیدی صورت

""") # توضیحات with gr.Row(): gr.Markdown(DESCRIPTION) # بخش ورودی‌ها with gr.Row(): with gr.Column(): image1_input = gr.Image(label="📸 تصویر چهره اول", type="pil", height=250) gr.HTML("

تصویر اول را انتخاب یا آپلود کنید

") with gr.Column(): image2_input = gr.Image(label="📸 تصویر چهره دوم", type="pil", height=250) gr.HTML("

تصویر دوم را انتخاب یا آپلود کنید

") # بخش تنظیمات with gr.Row(): with gr.Column(): precision_input = gr.Radio( choices=[ ("high", "🟢 دقت بالا (آستانه ۰.۴)"), ("medium", "🟡 دقت متوسط (آستانه ۰.۵)"), ("low", "🔴 دقت پایین (آستانه ۰.۶)") ], label="🎯 سطح دقت تشخیص", value='medium', type='value' ) # دکمه پردازش with gr.Row(): submit_btn = gr.Button("🚀 شروع تشخیص پیشرفته", variant="primary", size="lg") # بخش خروجی with gr.Row(): with gr.Column(scale=2): output_text = gr.Markdown(label="📊 نتایج تشخیص") with gr.Row(): with gr.Column(): output_image1 = gr.Image(label="تصویر اول - نقاط کلیدی", type="numpy", height=250) with gr.Column(): output_image2 = gr.Image(label="تصویر دوم - نقاط کلیدی", type="numpy", height=250) # راهنمای رنگ‌ها gr.HTML("""

🎨 راهنمای رنگ نقاط کلیدی:

""") # نکات مهم gr.HTML("""

⚠️ نکات مهم:

""") # تنظیمات دکمه submit_btn.click( fn=process_faces, inputs=[image1_input, image2_input, precision_input], outputs=[output_text, output_image1, output_image2] ) # اجرای برنامه if __name__ == "__main__": demo.launch( server_name="0.0.0.0", server_port=7860, share=True, show_error=True )