Spaces:
No application file
No application file
Upload 3 files
Browse files- Face_Segmentation_Project.ipynb +0 -0
- face_segmentation_project.py +1038 -0
- requirements.txt +8 -3
Face_Segmentation_Project.ipynb
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
face_segmentation_project.py
ADDED
|
@@ -0,0 +1,1038 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""Face_Segmentation_Project.ipynb
|
| 3 |
+
|
| 4 |
+
Automatically generated by Colab.
|
| 5 |
+
|
| 6 |
+
Original file is located at
|
| 7 |
+
https://colab.research.google.com/drive/1sLYDzM6pK7GBZW2JH7xMoVa0kOYYS9B5
|
| 8 |
+
|
| 9 |
+
## STEP 1 β Google Drive Mount Karo
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
from google.colab import drive
|
| 13 |
+
drive.mount('/content/drive')
|
| 14 |
+
|
| 15 |
+
"""## β
STEP 2 β Set Path
|
| 16 |
+
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
# Pehle path define karo (Apne folder ke hisaab se check kar lena)
|
| 20 |
+
TRAIN_NPY = "/content/drive/MyDrive/Face_Segmentation_Project/data/raw/Part 1- Train data - images.npy"
|
| 21 |
+
|
| 22 |
+
import numpy as np
|
| 23 |
+
|
| 24 |
+
print("Loading .npy file... (thoda time lagega 1.26GB hai)")
|
| 25 |
+
data = np.load(TRAIN_NPY, allow_pickle=True)
|
| 26 |
+
|
| 27 |
+
print("\n--- DATA INFO ---")
|
| 28 |
+
print("Type :", type(data))
|
| 29 |
+
print("Shape :", data.shape)
|
| 30 |
+
print("Dtype :", data.dtype)
|
| 31 |
+
|
| 32 |
+
# Agar object/dictionary ho
|
| 33 |
+
if data.dtype == object:
|
| 34 |
+
print("\nObject type hai, keys dekho:")
|
| 35 |
+
try:
|
| 36 |
+
d = data.item()
|
| 37 |
+
print("Keys:", d.keys())
|
| 38 |
+
except:
|
| 39 |
+
print("Array of objects - length:", len(data))
|
| 40 |
+
print("First element type:", type(data[0]))
|
| 41 |
+
print("First element shape:", data[0].shape if hasattr(data[0], 'shape') else "no shape")
|
| 42 |
+
else:
|
| 43 |
+
print("\nMin value :", data.min())
|
| 44 |
+
print("Max value :", data.max())
|
| 45 |
+
print("Total images:", data.shape[0])
|
| 46 |
+
|
| 47 |
+
# STEP 3 β Data Visualization (Andar kya hai dekho)
|
| 48 |
+
|
| 49 |
+
import matplotlib.pyplot as plt
|
| 50 |
+
|
| 51 |
+
# Pehla sample nikaalte hain
|
| 52 |
+
sample = data[0]
|
| 53 |
+
image_data = sample[0] # Pehla part image hona chahiye
|
| 54 |
+
mask_data = sample[1] # Dusra part mask ya annotations
|
| 55 |
+
|
| 56 |
+
print(f"Image shape: {image_data.shape}")
|
| 57 |
+
print(f"Mask/Metadata type: {type(mask_data)}")
|
| 58 |
+
|
| 59 |
+
# Ek bar visualize karke dekhte hain
|
| 60 |
+
plt.imshow(image_data)
|
| 61 |
+
plt.title("Sample Image")
|
| 62 |
+
plt.show()
|
| 63 |
+
|
| 64 |
+
# β
STEP 4 β Mask Check Karo (Andar kya hai?)
|
| 65 |
+
|
| 66 |
+
# List ka content check karte hain
|
| 67 |
+
print("Mask List Content:")
|
| 68 |
+
print(mask_data)
|
| 69 |
+
|
| 70 |
+
# Agar list ke pehle element mein 'notes' ya 'points' jaisi koi key hai toh:
|
| 71 |
+
if len(mask_data) > 0:
|
| 72 |
+
print("\nFirst element in list:", mask_data[0])
|
| 73 |
+
|
| 74 |
+
# π οΈ STEP 5 β Coordinates se Binary Mask Banana
|
| 75 |
+
|
| 76 |
+
import cv2
|
| 77 |
+
import numpy as np
|
| 78 |
+
|
| 79 |
+
def create_mask(image_shape, mask_list):
|
| 80 |
+
# Ek khali black image banao (0s)
|
| 81 |
+
mask = np.zeros(image_shape[:2], dtype=np.uint8)
|
| 82 |
+
|
| 83 |
+
h, w = image_shape[:2]
|
| 84 |
+
|
| 85 |
+
for item in mask_list:
|
| 86 |
+
# Normalized coordinates ko pixel values mein badlo
|
| 87 |
+
p1 = item['points'][0]
|
| 88 |
+
p2 = item['points'][1]
|
| 89 |
+
|
| 90 |
+
x1, y1 = int(p1['x'] * w), int(p1['y'] * h)
|
| 91 |
+
x2, y2 = int(p2['x'] * w), int(p2['y'] * h)
|
| 92 |
+
|
| 93 |
+
# Is area ko white (255) kar do
|
| 94 |
+
cv2.rectangle(mask, (x1, y1), (x2, y2), 255, -1)
|
| 95 |
+
|
| 96 |
+
return mask
|
| 97 |
+
|
| 98 |
+
# Test karte hain
|
| 99 |
+
test_mask = create_mask(image_data.shape, mask_data)
|
| 100 |
+
|
| 101 |
+
# Visualize Image + Mask
|
| 102 |
+
plt.figure(figsize=(10, 5))
|
| 103 |
+
plt.subplot(1, 2, 1)
|
| 104 |
+
plt.imshow(image_data); plt.title("Original Image")
|
| 105 |
+
plt.subplot(1, 2, 2)
|
| 106 |
+
plt.imshow(test_mask, cmap='gray'); plt.title("Generated Mask")
|
| 107 |
+
plt.show()
|
| 108 |
+
|
| 109 |
+
# β
STEP 6 β Data Preprocessing for U-Net
|
| 110 |
+
|
| 111 |
+
import cv2
|
| 112 |
+
import numpy as np
|
| 113 |
+
from tqdm import tqdm
|
| 114 |
+
|
| 115 |
+
IMG_HEIGHT = 256
|
| 116 |
+
IMG_WIDTH = 256
|
| 117 |
+
|
| 118 |
+
X = []
|
| 119 |
+
y = []
|
| 120 |
+
|
| 121 |
+
print("Processing 409 images and masks...")
|
| 122 |
+
|
| 123 |
+
for i in tqdm(range(len(data))):
|
| 124 |
+
img_array = data[i][0]
|
| 125 |
+
mask_list = data[i][1]
|
| 126 |
+
|
| 127 |
+
img_resized = cv2.resize(img_array, (IMG_WIDTH, IMG_HEIGHT))
|
| 128 |
+
|
| 129 |
+
if len(img_resized.shape) == 2:
|
| 130 |
+
img_resized = cv2.cvtColor(img_resized, cv2.COLOR_GRAY2RGB)
|
| 131 |
+
elif img_resized.shape[2] == 4:
|
| 132 |
+
img_resized = cv2.cvtColor(img_resized, cv2.COLOR_RGBA2RGB)
|
| 133 |
+
|
| 134 |
+
m_array = create_mask(img_array.shape, mask_list)
|
| 135 |
+
mask_resized = cv2.resize(m_array, (IMG_WIDTH, IMG_HEIGHT))
|
| 136 |
+
|
| 137 |
+
img_norm = img_resized / 255.0
|
| 138 |
+
mask_norm = mask_resized / 255.0
|
| 139 |
+
|
| 140 |
+
# β
Original image add karo
|
| 141 |
+
X.append(img_norm)
|
| 142 |
+
y.append(mask_norm)
|
| 143 |
+
|
| 144 |
+
# β
Augmentation 1 β Horizontal Flip
|
| 145 |
+
X.append(cv2.flip(img_norm, 1))
|
| 146 |
+
y.append(cv2.flip(mask_norm, 1))
|
| 147 |
+
|
| 148 |
+
# β
Augmentation 2 β Rotation 15 degree
|
| 149 |
+
M = cv2.getRotationMatrix2D((128, 128), 15, 1.0)
|
| 150 |
+
X.append(cv2.warpAffine(img_norm, M, (256, 256)))
|
| 151 |
+
y.append(cv2.warpAffine(mask_norm, M, (256, 256)))
|
| 152 |
+
|
| 153 |
+
# β
Augmentation 3 β Brightness Change
|
| 154 |
+
bright = np.clip(img_norm * 1.2, 0, 1)
|
| 155 |
+
X.append(bright)
|
| 156 |
+
y.append(mask_norm)
|
| 157 |
+
|
| 158 |
+
X = np.array(X, dtype=np.float32)
|
| 159 |
+
y = np.array(y, dtype=np.float32)
|
| 160 |
+
y = np.expand_dims(y, axis=-1)
|
| 161 |
+
|
| 162 |
+
print("\nβ
Preprocessing Complete!")
|
| 163 |
+
print(f"Images Shape: {X.shape}")
|
| 164 |
+
print(f"Masks Shape : {y.shape}")
|
| 165 |
+
|
| 166 |
+
# π STEP 7 β Model Building: U-Net with MobileNetV2
|
| 167 |
+
|
| 168 |
+
from sklearn.model_selection import train_test_split
|
| 169 |
+
|
| 170 |
+
X_train, X_temp, y_train, y_temp = train_test_split(
|
| 171 |
+
X, y, test_size=0.2, random_state=42
|
| 172 |
+
)
|
| 173 |
+
|
| 174 |
+
X_val, X_test, y_val, y_test = train_test_split(
|
| 175 |
+
X_temp, y_temp, test_size=0.5, random_state=42
|
| 176 |
+
)
|
| 177 |
+
|
| 178 |
+
print(f"Training data : {X_train.shape}")
|
| 179 |
+
print(f"Validation data : {X_val.shape}")
|
| 180 |
+
print(f"Test data : {X_test.shape}")
|
| 181 |
+
|
| 182 |
+
from tensorflow.keras.applications import MobileNetV2
|
| 183 |
+
from tensorflow.keras.layers import Input, Conv2D, UpSampling2D, Concatenate, BatchNormalization, Activation, Dropout
|
| 184 |
+
from tensorflow.keras.models import Model
|
| 185 |
+
import tensorflow as tf
|
| 186 |
+
|
| 187 |
+
def build_unet(input_shape):
|
| 188 |
+
inputs = Input(input_shape)
|
| 189 |
+
|
| 190 |
+
base_model = MobileNetV2(input_tensor=inputs, weights="imagenet", include_top=False)
|
| 191 |
+
|
| 192 |
+
# β
FIX 1: Encoder freeze karo
|
| 193 |
+
base_model.trainable = False
|
| 194 |
+
for layer in base_model.layers[-30:]:
|
| 195 |
+
layer.trainable = True
|
| 196 |
+
|
| 197 |
+
# Skip connections
|
| 198 |
+
s1 = inputs
|
| 199 |
+
s2 = base_model.get_layer("block_1_expand_relu").output
|
| 200 |
+
s3 = base_model.get_layer("block_3_expand_relu").output
|
| 201 |
+
s4 = base_model.get_layer("block_6_expand_relu").output
|
| 202 |
+
bridge = base_model.get_layer("block_13_expand_relu").output
|
| 203 |
+
|
| 204 |
+
# β
FIX 2: Dropout add kiya har decoder block mein
|
| 205 |
+
u1 = UpSampling2D((2, 2))(bridge)
|
| 206 |
+
u1 = Concatenate()([u1, s4])
|
| 207 |
+
u1 = Conv2D(256, 3, padding="same", kernel_initializer="he_normal")(u1)
|
| 208 |
+
u1 = BatchNormalization()(u1)
|
| 209 |
+
u1 = Activation("relu")(u1)
|
| 210 |
+
u1 = Dropout(0.3)(u1) # β
|
| 211 |
+
|
| 212 |
+
u2 = UpSampling2D((2, 2))(u1)
|
| 213 |
+
u2 = Concatenate()([u2, s3])
|
| 214 |
+
u2 = Conv2D(128, 3, padding="same", kernel_initializer="he_normal")(u2)
|
| 215 |
+
u2 = BatchNormalization()(u2)
|
| 216 |
+
u2 = Activation("relu")(u2)
|
| 217 |
+
u2 = Dropout(0.3)(u2) # β
|
| 218 |
+
|
| 219 |
+
u3 = UpSampling2D((2, 2))(u2)
|
| 220 |
+
u3 = Concatenate()([u3, s2])
|
| 221 |
+
u3 = Conv2D(64, 3, padding="same", kernel_initializer="he_normal")(u3)
|
| 222 |
+
u3 = BatchNormalization()(u3)
|
| 223 |
+
u3 = Activation("relu")(u3)
|
| 224 |
+
u3 = Dropout(0.2)(u3) # β
|
| 225 |
+
|
| 226 |
+
u4 = UpSampling2D((2, 2))(u3)
|
| 227 |
+
u4 = Concatenate()([u4, s1])
|
| 228 |
+
u4 = Conv2D(32, 3, padding="same", kernel_initializer="he_normal")(u4)
|
| 229 |
+
u4 = BatchNormalization()(u4)
|
| 230 |
+
u4 = Activation("relu")(u4)
|
| 231 |
+
|
| 232 |
+
outputs = Conv2D(1, 1, activation="sigmoid")(u4)
|
| 233 |
+
|
| 234 |
+
return Model(inputs, outputs)
|
| 235 |
+
|
| 236 |
+
model = build_unet((256, 256, 3))
|
| 237 |
+
|
| 238 |
+
# β
FIX 3: Combined Loss
|
| 239 |
+
def dice_coefficient(y_true, y_pred):
|
| 240 |
+
y_true_f = tf.cast(tf.reshape(y_true, [-1]), tf.float32)
|
| 241 |
+
y_pred_f = tf.cast(tf.reshape(y_pred, [-1]), tf.float32)
|
| 242 |
+
intersection = tf.reduce_sum(y_true_f * y_pred_f)
|
| 243 |
+
return (2. * intersection + 1.0) / (tf.reduce_sum(y_true_f) + tf.reduce_sum(y_pred_f) + 1.0)
|
| 244 |
+
|
| 245 |
+
def dice_loss(y_true, y_pred):
|
| 246 |
+
return 1 - dice_coefficient(y_true, y_pred)
|
| 247 |
+
|
| 248 |
+
def combined_loss(y_true, y_pred):
|
| 249 |
+
return dice_loss(y_true, y_pred) + tf.keras.losses.binary_crossentropy(y_true, y_pred)
|
| 250 |
+
|
| 251 |
+
model.compile(
|
| 252 |
+
optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),
|
| 253 |
+
loss=combined_loss, # β
Combined loss
|
| 254 |
+
metrics=[dice_coefficient, "accuracy"]
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
print("β
Model Compiled Successfully!")
|
| 258 |
+
|
| 259 |
+
# Training se PEHLE yeh check karo:
|
| 260 |
+
print(f"X_train shape: {X_train.shape}")
|
| 261 |
+
print(f"X_val shape : {X_val.shape}")
|
| 262 |
+
print(f"X_test shape : {X_test.shape}")
|
| 263 |
+
|
| 264 |
+
# π STEP 9 β Model Training (Fit)
|
| 265 |
+
|
| 266 |
+
from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping
|
| 267 |
+
|
| 268 |
+
callbacks = [
|
| 269 |
+
ModelCheckpoint("best_face_model.keras", monitor='val_dice_coefficient',
|
| 270 |
+
mode='max', save_best_only=True, verbose=1),
|
| 271 |
+
ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5,
|
| 272 |
+
min_lr=1e-7, verbose=1),
|
| 273 |
+
EarlyStopping(monitor='val_loss', patience=12,
|
| 274 |
+
restore_best_weights=True, verbose=1)
|
| 275 |
+
]
|
| 276 |
+
|
| 277 |
+
print("π Training shuru ho rahi hai!")
|
| 278 |
+
|
| 279 |
+
history = model.fit(
|
| 280 |
+
X_train, y_train,
|
| 281 |
+
validation_data=(X_val, y_val),
|
| 282 |
+
epochs=50,
|
| 283 |
+
batch_size=8,
|
| 284 |
+
callbacks=callbacks,
|
| 285 |
+
shuffle=True
|
| 286 |
+
)
|
| 287 |
+
|
| 288 |
+
print("\nβ
Training Complete!")
|
| 289 |
+
|
| 290 |
+
# Step - Evaluation Metrix
|
| 291 |
+
from sklearn.metrics import f1_score
|
| 292 |
+
import time
|
| 293 |
+
import numpy as np
|
| 294 |
+
|
| 295 |
+
def evaluate_model(model, X_test, y_test):
|
| 296 |
+
y_pred = model.predict(X_test)
|
| 297 |
+
y_pred_binary = (y_pred > 0.5).astype(np.float32)
|
| 298 |
+
|
| 299 |
+
# 1. Dice Coefficient
|
| 300 |
+
intersection = np.sum(y_test * y_pred_binary)
|
| 301 |
+
dice = (2. * intersection + 1.0) / (
|
| 302 |
+
np.sum(y_test) + np.sum(y_pred_binary) + 1.0
|
| 303 |
+
)
|
| 304 |
+
|
| 305 |
+
# 2. IoU Score
|
| 306 |
+
union = np.sum(y_test) + np.sum(y_pred_binary) - intersection
|
| 307 |
+
iou = intersection / union
|
| 308 |
+
|
| 309 |
+
# 3. F1 Score
|
| 310 |
+
f1 = f1_score(
|
| 311 |
+
y_test.flatten().astype(int),
|
| 312 |
+
y_pred_binary.flatten().astype(int)
|
| 313 |
+
)
|
| 314 |
+
|
| 315 |
+
# 4. β
Inference Speed β FIXED VERSION
|
| 316 |
+
model.predict(X_test[:1], verbose=0) # Warmup 1
|
| 317 |
+
model.predict(X_test[:1], verbose=0) # Warmup 2
|
| 318 |
+
times = []
|
| 319 |
+
for _ in range(5):
|
| 320 |
+
start = time.time()
|
| 321 |
+
model.predict(X_test[:1], verbose=0)
|
| 322 |
+
times.append((time.time() - start) * 1000)
|
| 323 |
+
speed = np.mean(times)
|
| 324 |
+
|
| 325 |
+
print("="*45)
|
| 326 |
+
print(f"Dice Coefficient : {dice:.4f} (Target >0.92)")
|
| 327 |
+
print(f"IoU Score : {iou:.4f} (Target >0.88)")
|
| 328 |
+
print(f"F1 Score : {f1:.4f} (Target >0.90)")
|
| 329 |
+
print(f"Inference Speed : {speed:.1f}ms (Target <100ms)")
|
| 330 |
+
print("="*45)
|
| 331 |
+
|
| 332 |
+
# Dobara chalao
|
| 333 |
+
evaluate_model(model, X_test, y_test)
|
| 334 |
+
|
| 335 |
+
# STEP 11 β Training Curves Plot
|
| 336 |
+
|
| 337 |
+
import matplotlib.pyplot as plt
|
| 338 |
+
|
| 339 |
+
plt.figure(figsize=(12, 4))
|
| 340 |
+
|
| 341 |
+
plt.subplot(1, 2, 1)
|
| 342 |
+
plt.plot(history.history['dice_coefficient'], label='Train Dice')
|
| 343 |
+
plt.plot(history.history['val_dice_coefficient'], label='Val Dice')
|
| 344 |
+
plt.title('Dice Coefficient Progress')
|
| 345 |
+
plt.xlabel('Epoch')
|
| 346 |
+
plt.legend()
|
| 347 |
+
|
| 348 |
+
plt.subplot(1, 2, 2)
|
| 349 |
+
plt.plot(history.history['loss'], label='Train Loss')
|
| 350 |
+
plt.plot(history.history['val_loss'], label='Val Loss')
|
| 351 |
+
plt.title('Loss Progress')
|
| 352 |
+
plt.xlabel('Epoch')
|
| 353 |
+
plt.legend()
|
| 354 |
+
|
| 355 |
+
plt.tight_layout()
|
| 356 |
+
plt.show()
|
| 357 |
+
|
| 358 |
+
import matplotlib.pyplot as plt
|
| 359 |
+
|
| 360 |
+
def visualize_prediction(index):
|
| 361 |
+
img = X_val[index]
|
| 362 |
+
gt_mask = y_val[index]
|
| 363 |
+
|
| 364 |
+
# Model se prediction lo
|
| 365 |
+
pred_mask = model.predict(np.expand_dims(img, axis=0))[0]
|
| 366 |
+
|
| 367 |
+
# Thresholding (0.5 se upar white, niche black)
|
| 368 |
+
pred_mask_binary = (pred_mask > 0.5).astype(np.uint8)
|
| 369 |
+
|
| 370 |
+
plt.figure(figsize=(12, 4))
|
| 371 |
+
plt.subplot(1, 3, 1)
|
| 372 |
+
plt.imshow(img); plt.title("Original Image")
|
| 373 |
+
|
| 374 |
+
plt.subplot(1, 3, 2)
|
| 375 |
+
plt.imshow(gt_mask.squeeze(), cmap='gray'); plt.title("Ground Truth Mask")
|
| 376 |
+
|
| 377 |
+
plt.subplot(1, 3, 3)
|
| 378 |
+
plt.imshow(pred_mask_binary.squeeze(), cmap='gray'); plt.title("Predicted Mask")
|
| 379 |
+
plt.show()
|
| 380 |
+
|
| 381 |
+
# Pehli 3 validation images check karte hain
|
| 382 |
+
for i in [0, 5, 10]:
|
| 383 |
+
visualize_prediction(i)
|
| 384 |
+
|
| 385 |
+
# π STEP 12 β Improving Accuracy with Hugging Face (SegFormer)
|
| 386 |
+
|
| 387 |
+
!pip install -q transformers datasets
|
| 388 |
+
|
| 389 |
+
from transformers import SegformerImageProcessor, SegformerForSemanticSegmentation
|
| 390 |
+
import torch
|
| 391 |
+
from PIL import Image
|
| 392 |
+
|
| 393 |
+
# 1. Pre-trained Model Load Karein
|
| 394 |
+
|
| 395 |
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 396 |
+
|
| 397 |
+
# Processor images ko transform karega, model segmentation karega
|
| 398 |
+
processor = SegformerImageProcessor.from_pretrained("nvidia/mit-b0")
|
| 399 |
+
hf_model = SegformerForSemanticSegmentation.from_pretrained("nvidia/mit-b0",
|
| 400 |
+
num_labels=1,
|
| 401 |
+
ignore_mismatched_sizes=True).to(device)
|
| 402 |
+
|
| 403 |
+
print("β
Hugging Face SegFormer Model Loaded!")
|
| 404 |
+
|
| 405 |
+
# π οΈ STEP 12 β SegFormer Dataset Class
|
| 406 |
+
import torch
|
| 407 |
+
from torch.utils.data import Dataset, DataLoader
|
| 408 |
+
import numpy as np
|
| 409 |
+
|
| 410 |
+
class FaceDataset(Dataset):
|
| 411 |
+
def __init__(self, images, masks, processor):
|
| 412 |
+
self.images = images
|
| 413 |
+
self.masks = masks
|
| 414 |
+
self.processor = processor
|
| 415 |
+
|
| 416 |
+
def __len__(self):
|
| 417 |
+
return len(self.images)
|
| 418 |
+
|
| 419 |
+
def __getitem__(self, idx):
|
| 420 |
+
# Image aur Mask uthayein
|
| 421 |
+
# (X_train already normalized hai, hume original format chahiye processor ke liye)
|
| 422 |
+
image = (self.images[idx] * 255).astype(np.uint8)
|
| 423 |
+
mask = self.masks[idx].squeeze().astype(np.longlong) # SegFormer expects long for masks
|
| 424 |
+
|
| 425 |
+
# Processor se transform karein
|
| 426 |
+
encoded_inputs = self.processor(image, mask, return_tensors="pt")
|
| 427 |
+
|
| 428 |
+
# Squeeze batch dimension jo processor add karta hai
|
| 429 |
+
for k, v in encoded_inputs.items():
|
| 430 |
+
encoded_inputs[k] = v.squeeze(0)
|
| 431 |
+
|
| 432 |
+
return encoded_inputs
|
| 433 |
+
|
| 434 |
+
# 1. Dataset Objects Banayein
|
| 435 |
+
train_dataset = FaceDataset(X_train, y_train, processor)
|
| 436 |
+
val_dataset = FaceDataset(X_val, y_val, processor)
|
| 437 |
+
|
| 438 |
+
# 2. DataLoaders Banayein
|
| 439 |
+
train_dataloader = DataLoader(train_dataset, batch_size=4, shuffle=True)
|
| 440 |
+
val_dataloader = DataLoader(val_dataset, batch_size=4)
|
| 441 |
+
|
| 442 |
+
print(f"β
DataLoaders Ready! Training samples: {len(train_dataset)}")
|
| 443 |
+
|
| 444 |
+
# π STEP 13 β Fine-tuning SegFormer (Training Loop)
|
| 445 |
+
|
| 446 |
+
from tqdm.notebook import tqdm
|
| 447 |
+
from torch.optim import AdamW
|
| 448 |
+
|
| 449 |
+
# 1. Optimizer setup
|
| 450 |
+
optimizer = AdamW(hf_model.parameters(), lr=5e-5)
|
| 451 |
+
|
| 452 |
+
# 2. Training Loop
|
| 453 |
+
num_epochs = 10 # SegFormer jaldi seekh jata hai
|
| 454 |
+
hf_model.train()
|
| 455 |
+
|
| 456 |
+
print("π SegFormer Training shuru ho rahi hai...")
|
| 457 |
+
|
| 458 |
+
for epoch in range(num_epochs):
|
| 459 |
+
train_loss = 0
|
| 460 |
+
# Tqdm progress bar ke liye
|
| 461 |
+
pbar = tqdm(train_dataloader, desc=f"Epoch {epoch+1}")
|
| 462 |
+
|
| 463 |
+
for batch in pbar:
|
| 464 |
+
# Data ko GPU/CPU par bhejein
|
| 465 |
+
pixel_values = batch["pixel_values"].to(device)
|
| 466 |
+
labels = batch["labels"].to(device)
|
| 467 |
+
|
| 468 |
+
# Forward pass
|
| 469 |
+
outputs = hf_model(pixel_values=pixel_values, labels=labels)
|
| 470 |
+
loss = outputs.loss
|
| 471 |
+
|
| 472 |
+
# Backward pass
|
| 473 |
+
loss.backward()
|
| 474 |
+
optimizer.step()
|
| 475 |
+
optimizer.zero_grad()
|
| 476 |
+
|
| 477 |
+
train_loss += loss.item()
|
| 478 |
+
pbar.set_postfix({'loss': loss.item()})
|
| 479 |
+
|
| 480 |
+
avg_train_loss = train_loss / len(train_dataloader)
|
| 481 |
+
print(f"β
Epoch {epoch+1} Complete | Average Loss: {avg_train_loss:.4f}")
|
| 482 |
+
|
| 483 |
+
print("\nπ SegFormer Fine-tuning Finished!")
|
| 484 |
+
|
| 485 |
+
# π¨ STEP 14 β SegFormer Prediction & Visualization
|
| 486 |
+
|
| 487 |
+
import torch.nn as nn
|
| 488 |
+
|
| 489 |
+
def visualize_segformer_prediction(index):
|
| 490 |
+
# 1. Validation set se data lein
|
| 491 |
+
inputs = val_dataset[index]
|
| 492 |
+
pixel_values = inputs["pixel_values"].unsqueeze(0).to(device)
|
| 493 |
+
gt_mask = inputs["labels"].numpy()
|
| 494 |
+
|
| 495 |
+
# 2. Prediction karein
|
| 496 |
+
hf_model.eval()
|
| 497 |
+
with torch.no_grad():
|
| 498 |
+
outputs = hf_model(pixel_values=pixel_values)
|
| 499 |
+
logits = outputs.logits # [1, num_labels, height/4, width/4]
|
| 500 |
+
|
| 501 |
+
# 3. Logits ko original image size (256x256) par upsample karein
|
| 502 |
+
upsampled_logits = nn.functional.interpolate(
|
| 503 |
+
logits,
|
| 504 |
+
size=(256, 256),
|
| 505 |
+
mode='bilinear',
|
| 506 |
+
align_corners=False
|
| 507 |
+
)
|
| 508 |
+
|
| 509 |
+
# 4. Binary mask banayein (Squeeze karke threshold lagayein)
|
| 510 |
+
pred_mask = torch.sigmoid(upsampled_logits).cpu().numpy().squeeze()
|
| 511 |
+
pred_mask_binary = (pred_mask > 0.5).astype(np.uint8)
|
| 512 |
+
|
| 513 |
+
# 5. Plotting
|
| 514 |
+
plt.figure(figsize=(12, 4))
|
| 515 |
+
|
| 516 |
+
# Original Image (Pixel values ko denormalize karke dikhayenge)
|
| 517 |
+
display_img = pixel_values.cpu().squeeze().permute(1, 2, 0).numpy()
|
| 518 |
+
display_img = (display_img - display_img.min()) / (display_img.max() - display_img.min())
|
| 519 |
+
|
| 520 |
+
plt.subplot(1, 3, 1)
|
| 521 |
+
plt.imshow(display_img)
|
| 522 |
+
plt.title("Original Image")
|
| 523 |
+
|
| 524 |
+
plt.subplot(1, 3, 2)
|
| 525 |
+
plt.imshow(gt_mask, cmap='gray')
|
| 526 |
+
plt.title("Ground Truth Mask")
|
| 527 |
+
|
| 528 |
+
plt.subplot(1, 3, 3)
|
| 529 |
+
plt.imshow(pred_mask_binary, cmap='gray')
|
| 530 |
+
plt.title("SegFormer Prediction")
|
| 531 |
+
|
| 532 |
+
plt.show()
|
| 533 |
+
|
| 534 |
+
# Pehle 3 validation images par results dekhein
|
| 535 |
+
for i in [0, 5, 10]:
|
| 536 |
+
visualize_segformer_prediction(i)
|
| 537 |
+
|
| 538 |
+
# πΎ STEP 15 β Model aur Processor ko Save Karein
|
| 539 |
+
|
| 540 |
+
import os
|
| 541 |
+
|
| 542 |
+
# 1. Ek folder banate hain model ke liye
|
| 543 |
+
save_directory = "my_face_segformer_model"
|
| 544 |
+
os.makedirs(save_directory, exist_ok=True)
|
| 545 |
+
|
| 546 |
+
# 2. Model ke weights aur config save karein
|
| 547 |
+
hf_model.save_pretrained(save_directory)
|
| 548 |
+
|
| 549 |
+
# 3. Processor (jo image resize aur normalize karta hai) bhi save karein
|
| 550 |
+
processor.save_pretrained(save_directory)
|
| 551 |
+
|
| 552 |
+
print(f"β
Model successfully saved in: {save_directory}")
|
| 553 |
+
|
| 554 |
+
# --- Google Colab Users ke liye ---
|
| 555 |
+
# Agar aap chahte hain ki ye hamesha ke liye safe rahe, toh ise Zip karke download kar lein
|
| 556 |
+
!zip -r face_model.zip my_face_segformer_model/
|
| 557 |
+
print("π¦ Zip file ban gayi hai! Ab aap ise left side ke 'Files' tab se download kar sakte hain.")
|
| 558 |
+
|
| 559 |
+
from google.colab import drive
|
| 560 |
+
import shutil
|
| 561 |
+
import os
|
| 562 |
+
|
| 563 |
+
# 1. Drive mount karein
|
| 564 |
+
drive.mount('/content/drive')
|
| 565 |
+
|
| 566 |
+
# 2. Aapka bataya hua path define karein
|
| 567 |
+
# Hum Face_Segmentation_Project ke andar 'saved_model' naam ka folder banayenge
|
| 568 |
+
base_path = '/content/drive/MyDrive/Face_Segmentation_Project'
|
| 569 |
+
model_save_path = os.path.join(base_path, 'trained_segformer_model')
|
| 570 |
+
|
| 571 |
+
# 3. Folder banayein agar nahi hai toh
|
| 572 |
+
os.makedirs(model_save_path, exist_ok=True)
|
| 573 |
+
|
| 574 |
+
# 4. Colab ki temporary files ko Drive par copy karein
|
| 575 |
+
source_folder = '/content/my_face_segformer_model'
|
| 576 |
+
|
| 577 |
+
# Purani files clear karke fresh copy karein
|
| 578 |
+
if os.path.exists(model_save_path):
|
| 579 |
+
shutil.rmtree(model_save_path)
|
| 580 |
+
|
| 581 |
+
shutil.copytree(source_folder, model_save_path)
|
| 582 |
+
|
| 583 |
+
print(f"β
Kaam ho gaya! Aapka model yahan save hai:")
|
| 584 |
+
print(f"π {model_save_path}")
|
| 585 |
+
|
| 586 |
+
import os
|
| 587 |
+
|
| 588 |
+
# Actor folders banao
|
| 589 |
+
actors = [
|
| 590 |
+
"Robert_Downey_Jr",
|
| 591 |
+
"Scarlett_Johansson",
|
| 592 |
+
"Chris_Evans",
|
| 593 |
+
"Tom_Cruise",
|
| 594 |
+
"Leonardo_DiCaprio",
|
| 595 |
+
"Brad_Pitt",
|
| 596 |
+
"Chris Hemsworth"
|
| 597 |
+
]
|
| 598 |
+
|
| 599 |
+
for actor in actors:
|
| 600 |
+
os.makedirs(f"/content/actor_db/{actor}", exist_ok=True)
|
| 601 |
+
|
| 602 |
+
print("β
Actor folders ban gaye!")
|
| 603 |
+
print(os.listdir("/content/actor_db"))
|
| 604 |
+
|
| 605 |
+
import requests
|
| 606 |
+
import os
|
| 607 |
+
|
| 608 |
+
actor_images = {
|
| 609 |
+
"Robert_Downey_Jr": [
|
| 610 |
+
"https://wallpapers.com/images/hd/focused-photography-robert-downey-jr-pjs7jatnx0yfofsc.jpg",
|
| 611 |
+
"https://static1.srcdn.com/wordpress/wp-content/uploads/2024/07/instar53643496.jpg"
|
| 612 |
+
],
|
| 613 |
+
"Scarlett_Johansson": [
|
| 614 |
+
"https://tse2.mm.bing.net/th/id/OIP.OwNfXHWEAynGbQwhmUNQWwHaKk?rs=1&pid=ImgDetMain&o=7&rm=3",
|
| 615 |
+
"https://m.media-amazon.com/images/M/MV5BMjAyNjE1NjgyMF5BMl5BanBnXkFtZTcwMjg0ODY1NA@@._V1_.jpg"
|
| 616 |
+
],
|
| 617 |
+
"Chris_Evans": [
|
| 618 |
+
"https://cdn.britannica.com/28/215028-050-94E9EA1E/American-actor-Chris-Evans-2019.jpg",
|
| 619 |
+
"https://tse4.mm.bing.net/th/id/OIP._aupdpOey-23R2KHLQd0OgHaLH?rs=1&pid=ImgDetMain&o=7&rm=3"
|
| 620 |
+
],
|
| 621 |
+
"Tom_Cruise": [
|
| 622 |
+
"https://image.tmdb.org/t/p/original/8qBylBsQf4llkGrWR3qAsOtOU8O.jpg",
|
| 623 |
+
"https://m.media-amazon.com/images/M/MV5BMmU1YWU1NmMtMjAyMi00MjFiLWFmZmUtOTc1ZjI5ODkxYmQyXkEyXkFqcGc@._V1_FMjpg_UX1000_.jpg"
|
| 624 |
+
],
|
| 625 |
+
"Leonardo_DiCaprio": [
|
| 626 |
+
"https://image.tmdb.org/t/p/original/aLUFp0zWpLVyIOgY0scIpuuKZLE.jpg",
|
| 627 |
+
"https://wallpapers.com/images/hd/leonardo-dicaprio-actor-nl2l96xppg1rj9hz.jpg"
|
| 628 |
+
],
|
| 629 |
+
"Brad_Pitt": [
|
| 630 |
+
"https://fr.web.img2.acsta.net/pictures/20/02/10/10/37/1374948.jpg",
|
| 631 |
+
"https://www.gratistodo.com/wp-content/uploads/2016/09/Brad-Pitt-7.jpg"
|
| 632 |
+
],
|
| 633 |
+
"Chris Hemsworth": [
|
| 634 |
+
"https://cdn.britannica.com/92/215392-050-96A4BC1D/Australian-actor-Chris-Hemsworth-2019.jpg",
|
| 635 |
+
"https://static1.cbrimages.com/wordpress/wp-content/uploads/2023/06/chris-hemsworth-thor-love-and-thunder-mcu.jpg"
|
| 636 |
+
]
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
success = 0
|
| 640 |
+
fail = 0
|
| 641 |
+
|
| 642 |
+
for actor_name, urls in actor_images.items():
|
| 643 |
+
for i, url in enumerate(urls):
|
| 644 |
+
try:
|
| 645 |
+
response = requests.get(url, timeout=15)
|
| 646 |
+
if response.status_code == 200:
|
| 647 |
+
path = f"/content/actor_db/{actor_name}/{i}.jpg"
|
| 648 |
+
with open(path, 'wb') as f:
|
| 649 |
+
f.write(response.content)
|
| 650 |
+
print(f"β
{actor_name} β photo {i+1} downloaded")
|
| 651 |
+
success += 1
|
| 652 |
+
else:
|
| 653 |
+
print(f"β {actor_name} β photo {i+1} failed ({response.status_code})")
|
| 654 |
+
fail += 1
|
| 655 |
+
except Exception as e:
|
| 656 |
+
print(f"β {actor_name} β photo {i+1} error: {e}")
|
| 657 |
+
fail += 1
|
| 658 |
+
|
| 659 |
+
print(f"\nβ
Success: {success} | β Failed: {fail}")
|
| 660 |
+
|
| 661 |
+
# Verify karo
|
| 662 |
+
print("\nπ Database Status:")
|
| 663 |
+
for actor in os.listdir("/content/actor_db"):
|
| 664 |
+
photos = os.listdir(f"/content/actor_db/{actor}")
|
| 665 |
+
print(f" {actor}: {len(photos)} photos")
|
| 666 |
+
|
| 667 |
+
!pip install deepface -q
|
| 668 |
+
!pip install tf-keras -q
|
| 669 |
+
print("β
DeepFace installed!")
|
| 670 |
+
|
| 671 |
+
# Test Karo
|
| 672 |
+
|
| 673 |
+
from deepface import DeepFace
|
| 674 |
+
import cv2
|
| 675 |
+
import numpy as np
|
| 676 |
+
|
| 677 |
+
# Test β ek image pe try karo
|
| 678 |
+
test_img = "/content/actor_db/Robert_Downey_Jr/0.jpg"
|
| 679 |
+
|
| 680 |
+
result = DeepFace.analyze(
|
| 681 |
+
img_path=test_img,
|
| 682 |
+
actions=['age', 'gender'],
|
| 683 |
+
enforce_detection=False
|
| 684 |
+
)
|
| 685 |
+
print("β
DeepFace working!")
|
| 686 |
+
print(f"Age: {result[0]['age']}")
|
| 687 |
+
print(f"Gender: {result[0]['dominant_gender']}")
|
| 688 |
+
|
| 689 |
+
# Step 1 β Sahi versions install karo
|
| 690 |
+
!pip install tf-keras==2.19.0 -q
|
| 691 |
+
!pip install keras==2.19.0 -q
|
| 692 |
+
print("β
Done!")
|
| 693 |
+
|
| 694 |
+
import keras
|
| 695 |
+
import tensorflow as tf
|
| 696 |
+
|
| 697 |
+
def dice_coefficient(y_true, y_pred):
|
| 698 |
+
y_true_f = tf.cast(tf.reshape(y_true,[-1]),tf.float32)
|
| 699 |
+
y_pred_f = tf.cast(tf.reshape(y_pred,[-1]),tf.float32)
|
| 700 |
+
i = tf.reduce_sum(y_true_f*y_pred_f)
|
| 701 |
+
return (2.*i+1.)/(tf.reduce_sum(y_true_f)+tf.reduce_sum(y_pred_f)+1.)
|
| 702 |
+
|
| 703 |
+
def combined_loss(y_true, y_pred):
|
| 704 |
+
return 1-dice_coefficient(y_true,y_pred)+tf.keras.losses.binary_crossentropy(y_true,y_pred)
|
| 705 |
+
|
| 706 |
+
# Pehle load karo
|
| 707 |
+
model = keras.models.load_model(
|
| 708 |
+
"/content/best_face_model.keras",
|
| 709 |
+
custom_objects={
|
| 710 |
+
'dice_coefficient': dice_coefficient,
|
| 711 |
+
'combined_loss': combined_loss
|
| 712 |
+
}
|
| 713 |
+
)
|
| 714 |
+
|
| 715 |
+
# Weights alag save karo
|
| 716 |
+
model.save_weights("/content/model_weights.weights.h5")
|
| 717 |
+
print("β
Weights saved!")
|
| 718 |
+
|
| 719 |
+
# Commented out IPython magic to ensure Python compatibility.
|
| 720 |
+
# %%writefile /content/app.py
|
| 721 |
+
# import os
|
| 722 |
+
# os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
|
| 723 |
+
# os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
|
| 724 |
+
#
|
| 725 |
+
# import streamlit as st
|
| 726 |
+
# import numpy as np
|
| 727 |
+
# import cv2
|
| 728 |
+
# from PIL import Image
|
| 729 |
+
# import tensorflow as tf
|
| 730 |
+
# import time
|
| 731 |
+
# import io
|
| 732 |
+
#
|
| 733 |
+
# st.set_page_config(page_title="Scene Cast AI", page_icon="π¬", layout="wide")
|
| 734 |
+
#
|
| 735 |
+
# st.markdown("""<style>
|
| 736 |
+
# @import url('https://fonts.googleapis.com/css2?family=Syne:wght@700;800&family=DM+Sans:wght@300;400&display=swap');
|
| 737 |
+
# :root{--bg:#0a0a0f;--card:#16161f;--gold:#f5c518;--blue:#4cc9f0;--text:#f0f0f5;--muted:#7a7a8c;--border:rgba(245,197,24,0.15);}
|
| 738 |
+
# html,body,[class*="css"]{font-family:'DM Sans',sans-serif;background:var(--bg);color:var(--text);}
|
| 739 |
+
# .stApp{background:var(--bg);}
|
| 740 |
+
# #MainMenu,footer,header{visibility:hidden;}
|
| 741 |
+
# [data-testid="stSidebar"]{background:#111118;border-right:1px solid var(--border);}
|
| 742 |
+
# .hero-title{font-family:'Syne',sans-serif;font-size:3rem;font-weight:800;background:linear-gradient(135deg,#f5c518,#f0f0f5,#4cc9f0);-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin:0;}
|
| 743 |
+
# .card{background:var(--card);border:1px solid var(--border);border-radius:16px;padding:1.2rem;position:relative;overflow:hidden;}
|
| 744 |
+
# .card::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,var(--gold),var(--blue));}
|
| 745 |
+
# .label{font-family:'Syne',sans-serif;font-size:0.75rem;font-weight:700;letter-spacing:0.15em;text-transform:uppercase;color:var(--gold);margin-bottom:0.8rem;}
|
| 746 |
+
# .metric-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin:1rem 0;}
|
| 747 |
+
# .metric{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:1rem;text-align:center;}
|
| 748 |
+
# .mval{font-family:'Syne',sans-serif;font-size:1.5rem;font-weight:800;color:var(--gold);}
|
| 749 |
+
# .mval.warn{color:#fb923c;}.mval.fast{color:var(--blue);}
|
| 750 |
+
# .mlbl{color:var(--muted);font-size:0.75rem;text-transform:uppercase;}
|
| 751 |
+
# .mtgt{font-size:0.65rem;color:var(--muted);margin-top:0.2rem;}
|
| 752 |
+
# .info{background:rgba(245,197,24,0.08);border-left:3px solid var(--gold);padding:0.8rem;border-radius:0 8px 8px 0;font-size:0.83rem;color:var(--muted);margin-top:0.8rem;}
|
| 753 |
+
# .sec{display:flex;align-items:center;gap:0.8rem;margin:1.5rem 0 1rem;}
|
| 754 |
+
# .sec-line{flex:1;height:1px;background:var(--border);}
|
| 755 |
+
# .sec-title{font-family:'Syne',sans-serif;font-size:0.75rem;font-weight:700;letter-spacing:0.2em;text-transform:uppercase;color:var(--muted);}
|
| 756 |
+
# .actor-card{background:var(--card);border:1px solid rgba(245,197,24,0.3);border-radius:16px;padding:1rem;text-align:center;}
|
| 757 |
+
# .actor-name{font-family:'Syne',sans-serif;font-size:1rem;font-weight:800;color:var(--gold);margin:0.5rem 0 0.2rem;}
|
| 758 |
+
# .stDownloadButton>button{background:linear-gradient(135deg,rgba(245,197,24,0.15),rgba(76,201,240,0.1))!important;border:1px solid rgba(245,197,24,0.4)!important;color:var(--gold)!important;font-family:'Syne',sans-serif!important;font-weight:700!important;border-radius:10px!important;width:100%!important;}
|
| 759 |
+
# </style>""", unsafe_allow_html=True)
|
| 760 |
+
#
|
| 761 |
+
# # ββ Model Architecture Rebuild + Weights Load ββ
|
| 762 |
+
# from tensorflow.keras.applications import MobileNetV2
|
| 763 |
+
# from tensorflow.keras.layers import Input, Conv2D, UpSampling2D, Concatenate, BatchNormalization, Activation, Dropout
|
| 764 |
+
# from tensorflow.keras.models import Model
|
| 765 |
+
#
|
| 766 |
+
# def dice_coefficient(y_true, y_pred):
|
| 767 |
+
# y_true_f = tf.cast(tf.reshape(y_true,[-1]),tf.float32)
|
| 768 |
+
# y_pred_f = tf.cast(tf.reshape(y_pred,[-1]),tf.float32)
|
| 769 |
+
# i = tf.reduce_sum(y_true_f*y_pred_f)
|
| 770 |
+
# return (2.*i+1.)/(tf.reduce_sum(y_true_f)+tf.reduce_sum(y_pred_f)+1.)
|
| 771 |
+
#
|
| 772 |
+
# def combined_loss(y_true, y_pred):
|
| 773 |
+
# return 1-dice_coefficient(y_true,y_pred)+tf.keras.losses.binary_crossentropy(y_true,y_pred)
|
| 774 |
+
#
|
| 775 |
+
# def build_unet(input_shape=(256,256,3)):
|
| 776 |
+
# inputs = Input(input_shape)
|
| 777 |
+
# base = MobileNetV2(input_tensor=inputs, weights=None, include_top=False)
|
| 778 |
+
# base.trainable = False
|
| 779 |
+
# s1=inputs
|
| 780 |
+
# s2=base.get_layer("block_1_expand_relu").output
|
| 781 |
+
# s3=base.get_layer("block_3_expand_relu").output
|
| 782 |
+
# s4=base.get_layer("block_6_expand_relu").output
|
| 783 |
+
# bridge=base.get_layer("block_13_expand_relu").output
|
| 784 |
+
# u1=UpSampling2D((2,2))(bridge)
|
| 785 |
+
# u1=Concatenate()([u1,s4])
|
| 786 |
+
# u1=Conv2D(256,3,padding="same",kernel_initializer="he_normal")(u1)
|
| 787 |
+
# u1=BatchNormalization()(u1); u1=Activation("relu")(u1); u1=Dropout(0.3)(u1)
|
| 788 |
+
# u2=UpSampling2D((2,2))(u1)
|
| 789 |
+
# u2=Concatenate()([u2,s3])
|
| 790 |
+
# u2=Conv2D(128,3,padding="same",kernel_initializer="he_normal")(u2)
|
| 791 |
+
# u2=BatchNormalization()(u2); u2=Activation("relu")(u2); u2=Dropout(0.3)(u2)
|
| 792 |
+
# u3=UpSampling2D((2,2))(u2)
|
| 793 |
+
# u3=Concatenate()([u3,s2])
|
| 794 |
+
# u3=Conv2D(64,3,padding="same",kernel_initializer="he_normal")(u3)
|
| 795 |
+
# u3=BatchNormalization()(u3); u3=Activation("relu")(u3); u3=Dropout(0.2)(u3)
|
| 796 |
+
# u4=UpSampling2D((2,2))(u3)
|
| 797 |
+
# u4=Concatenate()([u4,s1])
|
| 798 |
+
# u4=Conv2D(32,3,padding="same",kernel_initializer="he_normal")(u4)
|
| 799 |
+
# u4=BatchNormalization()(u4); u4=Activation("relu")(u4)
|
| 800 |
+
# outputs=Conv2D(1,1,activation="sigmoid")(u4)
|
| 801 |
+
# return Model(inputs,outputs)
|
| 802 |
+
#
|
| 803 |
+
# @st.cache_resource(show_spinner=False)
|
| 804 |
+
# def load_model():
|
| 805 |
+
# with tf.device('/CPU:0'):
|
| 806 |
+
# m = build_unet()
|
| 807 |
+
# m.load_weights("/content/model_weights.weights.h5", by_name=True, skip_mismatch=True)
|
| 808 |
+
# m.compile(
|
| 809 |
+
# optimizer=tf.keras.optimizers.Adam(1e-4),
|
| 810 |
+
# loss=combined_loss,
|
| 811 |
+
# metrics=[dice_coefficient]
|
| 812 |
+
# )
|
| 813 |
+
# return m
|
| 814 |
+
#
|
| 815 |
+
# def create_overlay(image, mask):
|
| 816 |
+
# img=cv2.resize(np.array(image),(256,256))
|
| 817 |
+
# cm=np.zeros_like(img); cm[mask>127]=[245,197,24]
|
| 818 |
+
# ov=cv2.addWeighted(img,0.55,cm,0.45,0)
|
| 819 |
+
# ctrs,_=cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
|
| 820 |
+
# cv2.drawContours(ov,ctrs,-1,(245,197,24),2)
|
| 821 |
+
# return ov
|
| 822 |
+
#
|
| 823 |
+
# def face_count(mask):
|
| 824 |
+
# ctrs,_=cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
|
| 825 |
+
# return len([c for c in ctrs if cv2.contourArea(c)>256*256*0.005])
|
| 826 |
+
#
|
| 827 |
+
# def img_bytes(arr):
|
| 828 |
+
# buf=io.BytesIO(); Image.fromarray(arr).save(buf,format="PNG"); return buf.getvalue()
|
| 829 |
+
#
|
| 830 |
+
# def get_face_crops(image,mask):
|
| 831 |
+
# img=cv2.resize(np.array(image),(256,256))
|
| 832 |
+
# ctrs,_=cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
|
| 833 |
+
# crops=[]
|
| 834 |
+
# for c in ctrs:
|
| 835 |
+
# if cv2.contourArea(c)>256*256*0.005:
|
| 836 |
+
# x,y,w,h=cv2.boundingRect(c)
|
| 837 |
+
# crop=img[max(0,y-10):min(255,y+h+10),max(0,x-10):min(255,x+w+10)]
|
| 838 |
+
# if crop.size>0: crops.append(crop)
|
| 839 |
+
# return crops
|
| 840 |
+
#
|
| 841 |
+
# def identify_actors(crops):
|
| 842 |
+
# results=[]; db="/content/actor_db"
|
| 843 |
+
# if not os.path.exists(db): return results
|
| 844 |
+
# has_photos=any(len(os.listdir(f"{db}/{a}"))>0 for a in os.listdir(db) if os.path.isdir(f"{db}/{a}"))
|
| 845 |
+
# if not has_photos: return results
|
| 846 |
+
# try:
|
| 847 |
+
# from deepface import DeepFace
|
| 848 |
+
# for crop in crops:
|
| 849 |
+
# try:
|
| 850 |
+
# dfs=DeepFace.find(img_path=crop,db_path=db,model_name="VGG-Face",enforce_detection=False,silent=True)
|
| 851 |
+
# if len(dfs)>0 and len(dfs[0])>0:
|
| 852 |
+
# best=dfs[0].iloc[0]
|
| 853 |
+
# name=best['identity'].split('/')[-2].replace('_',' ')
|
| 854 |
+
# dist=best.get('distance',1)
|
| 855 |
+
# conf=max(0,(1-dist)*100)
|
| 856 |
+
# results.append({"name":name,"confidence":conf})
|
| 857 |
+
# else:
|
| 858 |
+
# results.append({"name":"Unknown Actor","confidence":0})
|
| 859 |
+
# except:
|
| 860 |
+
# results.append({"name":"Unknown Actor","confidence":0})
|
| 861 |
+
# except ImportError:
|
| 862 |
+
# pass
|
| 863 |
+
# return results
|
| 864 |
+
#
|
| 865 |
+
# with st.sidebar:
|
| 866 |
+
# st.markdown("""<div style="text-align:center;padding:1rem 0 1.5rem;">
|
| 867 |
+
# <div style="font-size:2.5rem;">π¬</div>
|
| 868 |
+
# <div style="font-family:'Syne',sans-serif;font-weight:800;color:#f5c518;">Scene Cast AI</div>
|
| 869 |
+
# <div style="font-size:0.75rem;color:#7a7a8c;">Face Segmentation Engine</div>
|
| 870 |
+
# </div>""",unsafe_allow_html=True)
|
| 871 |
+
# st.markdown("**βοΈ SETTINGS**")
|
| 872 |
+
# threshold=st.slider("Confidence Threshold",0.1,0.9,0.5,0.05)
|
| 873 |
+
# show_ov=st.checkbox("Face Overlay",value=True)
|
| 874 |
+
# show_mask=st.checkbox("Binary Mask",value=True)
|
| 875 |
+
# show_conf=st.checkbox("Confidence Map",value=False)
|
| 876 |
+
# show_actor=st.checkbox("π Actor Recognition",value=True)
|
| 877 |
+
# st.markdown("---")
|
| 878 |
+
# st.markdown("""**π MODEL INFO**
|
| 879 |
+
# <div style="font-size:0.8rem;color:#7a7a8c;line-height:1.9;">
|
| 880 |
+
# ποΈ <b style="color:#f0f0f5;">Architecture:</b> U-Net<br>
|
| 881 |
+
# π§ <b style="color:#f0f0f5;">Encoder:</b> MobileNetV2<br>
|
| 882 |
+
# π¦ <b style="color:#f0f0f5;">Input:</b> 256Γ256<br>
|
| 883 |
+
# π <b style="color:#f0f0f5;">Val Dice:</b> 0.8742
|
| 884 |
+
# </div>""",unsafe_allow_html=True)
|
| 885 |
+
#
|
| 886 |
+
# st.markdown("""<div style="text-align:center;padding:2rem 1rem 1.5rem;">
|
| 887 |
+
# <div style="display:inline-block;background:rgba(245,197,24,0.1);border:1px solid rgba(245,197,24,0.3);color:#f5c518;font-size:0.7rem;letter-spacing:0.2em;text-transform:uppercase;padding:0.3rem 1rem;border-radius:2rem;margin-bottom:1rem;">π¬ Powered by Deep Learning</div>
|
| 888 |
+
# <h1 class="hero-title">Scene Cast AI</h1>
|
| 889 |
+
# <p style="color:#7a7a8c;font-size:1rem;max-width:480px;margin:0.5rem auto;">Real-time face segmentation + actor identification.</p>
|
| 890 |
+
# <div style="width:60px;height:2px;background:linear-gradient(90deg,#f5c518,#4cc9f0);margin:1.2rem auto 0;border-radius:2px;"></div>
|
| 891 |
+
# </div>""",unsafe_allow_html=True)
|
| 892 |
+
#
|
| 893 |
+
# with st.spinner("π Loading AI Model..."):
|
| 894 |
+
# try:
|
| 895 |
+
# model=load_model()
|
| 896 |
+
# st.success("β
Model loaded!", icon="π€")
|
| 897 |
+
# except Exception as e:
|
| 898 |
+
# st.error(f"β Error: {e}")
|
| 899 |
+
# st.stop()
|
| 900 |
+
#
|
| 901 |
+
# st.markdown('<div class="sec"><div class="sec-line"></div><div class="sec-title">π Upload Movie Scene</div><div class="sec-line"></div></div>',unsafe_allow_html=True)
|
| 902 |
+
# f=st.file_uploader("Upload",type=["jpg","jpeg","png","webp"],label_visibility="collapsed")
|
| 903 |
+
#
|
| 904 |
+
# if f:
|
| 905 |
+
# # π₯ FIX: Streamlit upload β OpenCV decode
|
| 906 |
+
# file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8)
|
| 907 |
+
# img = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
|
| 908 |
+
#
|
| 909 |
+
# if img is None:
|
| 910 |
+
# st.error("β Image read nahi ho pa rahi. Dusri image try karo.")
|
| 911 |
+
# st.stop()
|
| 912 |
+
#
|
| 913 |
+
# img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
| 914 |
+
# image = Image.fromarray(img)
|
| 915 |
+
#
|
| 916 |
+
# # π same code as before
|
| 917 |
+
# ir = cv2.resize(np.array(image),(256,256))/255.0
|
| 918 |
+
# ii = np.expand_dims(ir,0).astype(np.float32)
|
| 919 |
+
#
|
| 920 |
+
# with st.spinner("π§ Analyzing..."):
|
| 921 |
+
# with tf.device('/CPU:0'):
|
| 922 |
+
# t0 = time.time()
|
| 923 |
+
# pred = model.predict(ii,verbose=0)[0]
|
| 924 |
+
# spd = (time.time()-t0)*1000
|
| 925 |
+
#
|
| 926 |
+
# mask = (pred.squeeze()>threshold).astype(np.uint8)*255
|
| 927 |
+
# fc = face_count(mask)
|
| 928 |
+
# cov = (np.sum(mask>0)/(256*256))*100
|
| 929 |
+
#
|
| 930 |
+
# st.markdown('<div class="sec"><div class="sec-line"></div><div class="sec-title">π― Detection Results</div><div class="sec-line"></div></div>',unsafe_allow_html=True)
|
| 931 |
+
#
|
| 932 |
+
# ncols = 1+show_ov+show_mask+show_conf
|
| 933 |
+
# dcols = st.columns(ncols)
|
| 934 |
+
# with dcols[0]:
|
| 935 |
+
# st.markdown('<div class="card"><div class="label">π¬ Original Frame</div>',unsafe_allow_html=True)
|
| 936 |
+
# st.image(image,use_container_width=True)
|
| 937 |
+
# st.markdown(f'<div class="info">π {image.width}Γ{image.height}px | π₯ ~{fc} face(s)</div></div>',unsafe_allow_html=True)
|
| 938 |
+
# idx=1
|
| 939 |
+
# if show_ov:
|
| 940 |
+
# ov=create_overlay(image,mask)
|
| 941 |
+
# with dcols[idx]:
|
| 942 |
+
# st.markdown('<div class="card"><div class="label">β¨ Face Overlay</div>',unsafe_allow_html=True)
|
| 943 |
+
# st.image(ov,use_container_width=True)
|
| 944 |
+
# st.markdown(f'<div class="info">π‘ Gold=face | {cov:.1f}%</div></div>',unsafe_allow_html=True)
|
| 945 |
+
# idx+=1
|
| 946 |
+
# if show_mask:
|
| 947 |
+
# with dcols[idx]:
|
| 948 |
+
# st.markdown('<div class="card"><div class="label">π² Binary Mask</div>',unsafe_allow_html=True)
|
| 949 |
+
# st.image(mask,use_container_width=True)
|
| 950 |
+
# st.markdown(f'<div class="info">β¬ White=face | {threshold:.2f}</div></div>',unsafe_allow_html=True)
|
| 951 |
+
# idx+=1
|
| 952 |
+
# if show_conf:
|
| 953 |
+
# cm=cv2.applyColorMap((pred.squeeze()*255).astype(np.uint8),cv2.COLORMAP_INFERNO)
|
| 954 |
+
# cm=cv2.cvtColor(cm,cv2.COLOR_BGR2RGB)
|
| 955 |
+
# with dcols[idx]:
|
| 956 |
+
# st.markdown('<div class="card"><div class="label">π‘οΈ Confidence</div>',unsafe_allow_html=True)
|
| 957 |
+
# st.image(cm,use_container_width=True)
|
| 958 |
+
# st.markdown('<div class="info">π΄ Hot=face</div></div>',unsafe_allow_html=True)
|
| 959 |
+
# if show_actor:
|
| 960 |
+
# st.markdown('<div class="sec"><div class="sec-line"></div><div class="sec-title">π Actor Recognition</div><div class="sec-line"></div></div>',unsafe_allow_html=True)
|
| 961 |
+
# with st.spinner("π Identifying..."):
|
| 962 |
+
# crops=get_face_crops(image,mask); actors=identify_actors(crops)
|
| 963 |
+
# if actors:
|
| 964 |
+
# acols=st.columns(min(len(actors),4))
|
| 965 |
+
# for i,a in enumerate(actors):
|
| 966 |
+
# cc="#4ade80" if a['confidence']>60 else "#fb923c"
|
| 967 |
+
# with acols[i%4]:
|
| 968 |
+
# st.markdown(f"""<div class="actor-card"><div style="font-size:2rem;">π</div>
|
| 969 |
+
# <div class="actor-name">{a['name']}</div>
|
| 970 |
+
# <div style="font-size:0.78rem;color:{cc};">Confidence: {a['confidence']:.1f}%</div>
|
| 971 |
+
# </div>""",unsafe_allow_html=True)
|
| 972 |
+
# else:
|
| 973 |
+
# st.info("π Actor DB mein photos upload karo!",icon="βΉοΈ")
|
| 974 |
+
# st.markdown('<div class="sec"><div class="sec-line"></div><div class="sec-title">π Performance</div><div class="sec-line"></div></div>',unsafe_allow_html=True)
|
| 975 |
+
# sc="fast" if spd<100 else "warn"
|
| 976 |
+
# st.markdown(f"""<div class="metric-grid">
|
| 977 |
+
# <div class="metric"><div style="font-size:1.3rem;">π―</div><div class="mval warn">0.8845</div><div class="mlbl">Dice</div><div class="mtgt">>0.92</div></div>
|
| 978 |
+
# <div class="metric"><div style="font-size:1.3rem;">π</div><div class="mval warn">0.7929</div><div class="mlbl">IoU</div><div class="mtgt">>0.88</div></div>
|
| 979 |
+
# <div class="metric"><div style="font-size:1.3rem;">βοΈ</div><div class="mval warn">0.8849</div><div class="mlbl">F1</div><div class="mtgt">>0.90</div></div>
|
| 980 |
+
# <div class="metric"><div style="font-size:1.3rem;">β‘</div><div class="mval {sc}">{spd:.0f}ms</div><div class="mlbl">Speed</div><div class="mtgt"><100ms</div></div>
|
| 981 |
+
# </div>""",unsafe_allow_html=True)
|
| 982 |
+
# c1,c2,c3=st.columns(3)
|
| 983 |
+
# for col,icon,val,lbl,clr in [(c1,"π₯",str(fc),"Faces","#f5c518"),(c2,"π",f"{cov:.1f}%","Coverage","#4cc9f0"),(c3,"ποΈ",f"{threshold:.2f}","Threshold","#4ade80")]:
|
| 984 |
+
# with col:
|
| 985 |
+
# st.markdown(f"""<div class="card" style="text-align:center;padding:1rem;">
|
| 986 |
+
# <div style="font-size:2rem;">{icon}</div>
|
| 987 |
+
# <div style="font-family:'Syne',sans-serif;font-size:1.8rem;font-weight:800;color:{clr};">{val}</div>
|
| 988 |
+
# <div style="color:#7a7a8c;font-size:0.78rem;text-transform:uppercase;">{lbl}</div>
|
| 989 |
+
# </div>""",unsafe_allow_html=True)
|
| 990 |
+
# st.markdown('<div class="sec"><div class="sec-line"></div><div class="sec-title">π₯ Export</div><div class="sec-line"></div></div>',unsafe_allow_html=True)
|
| 991 |
+
# d1,d2,d3=st.columns(3)
|
| 992 |
+
# with d1:
|
| 993 |
+
# st.download_button("β¬οΈ Mask",img_bytes(mask),"mask.png","image/png",use_container_width=True)
|
| 994 |
+
# with d2:
|
| 995 |
+
# ov2=create_overlay(image,mask)
|
| 996 |
+
# st.download_button("β¬οΈ Overlay",img_bytes(ov2),"overlay.png","image/png",use_container_width=True)
|
| 997 |
+
# with d3:
|
| 998 |
+
# log=f"File:{f.name}\nFaces:{fc}\nSpeed:{spd:.1f}ms\nDice:0.8845\nIoU:0.7929"
|
| 999 |
+
# st.download_button("β¬οΈ Log",log,"log.txt","text/plain",use_container_width=True)
|
| 1000 |
+
# else:
|
| 1001 |
+
# st.markdown("""<div style="background:#16161f;border:2px dashed rgba(245,197,24,0.2);border-radius:20px;padding:4rem 2rem;text-align:center;margin:2rem 0;">
|
| 1002 |
+
# <div style="font-size:4rem;">π¬</div>
|
| 1003 |
+
# <div style="font-family:'Syne',sans-serif;font-size:1.4rem;font-weight:700;color:#f0f0f5;margin:0.8rem 0 0.4rem;">Ready to Detect & Identify</div>
|
| 1004 |
+
# <div style="color:#7a7a8c;">Upload movie screenshot β AI detects + identifies actors!</div>
|
| 1005 |
+
# </div>""",unsafe_allow_html=True)
|
| 1006 |
+
|
| 1007 |
+
!sed -i 's/use_container_width=True/use_column_width=True/g' /content/app.py
|
| 1008 |
+
|
| 1009 |
+
# Yeh cell chalao β warning fix hogi
|
| 1010 |
+
!sed -i 's/use_column_width=True/use_container_width=True/g' /content/app.py
|
| 1011 |
+
print("β
Fixed!")
|
| 1012 |
+
|
| 1013 |
+
!pip install streamlit pyngrok -q
|
| 1014 |
+
|
| 1015 |
+
# Ek Cell Mein Sab
|
| 1016 |
+
!fuser -k 8501/tcp
|
| 1017 |
+
!pkill -f streamlit
|
| 1018 |
+
|
| 1019 |
+
import time
|
| 1020 |
+
time.sleep(2)
|
| 1021 |
+
|
| 1022 |
+
import subprocess, threading
|
| 1023 |
+
|
| 1024 |
+
def run():
|
| 1025 |
+
subprocess.Popen([
|
| 1026 |
+
'streamlit', 'run', '/content/app.py',
|
| 1027 |
+
'--server.port=8501',
|
| 1028 |
+
'--server.headless=true',
|
| 1029 |
+
'--server.enableCORS=false',
|
| 1030 |
+
'--server.enableXsrfProtection=false'
|
| 1031 |
+
])
|
| 1032 |
+
|
| 1033 |
+
threading.Thread(target=run).start()
|
| 1034 |
+
time.sleep(15)
|
| 1035 |
+
|
| 1036 |
+
from google.colab.output import eval_js
|
| 1037 |
+
url = eval_js("google.colab.kernel.proxyPort(8501)")
|
| 1038 |
+
print(f"β
URL: {url}")
|
requirements.txt
CHANGED
|
@@ -1,3 +1,8 @@
|
|
| 1 |
-
|
| 2 |
-
pandas
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
streamlit
|
| 2 |
+
pandas
|
| 3 |
+
numpy
|
| 4 |
+
matplotlib
|
| 5 |
+
seaborn
|
| 6 |
+
scikit-learn
|
| 7 |
+
tensorflow
|
| 8 |
+
keras
|