-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
90 lines (68 loc) · 2.52 KB
/
main.py
File metadata and controls
90 lines (68 loc) · 2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import cv2
import numpy as np
import matplotlib.pyplot as plt
def get_chromaticity(img):
"""Converts BGR image to xy chromaticity coordinates."""
# Convert to float to avoid overflow
img = img.astype(float)
sum_rgb = img[:,:,0] + img[:,:,1] + img[:,:,2]
# Avoid division by zero
sum_rgb[sum_rgb == 0] = 1
# OpenCV uses BGR: img[:,:,2] is Red, img[:,:,1] is Green
x = img[:,:,2] / sum_rgb
y = img[:,:,1] / sum_rgb
return x, y
image = cv2.imread('image.jpg')
print(image)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 2. Define Skin Region (Manual Crop for Step 2)
# For this example, we'll take a central crop.
# In a real app, you'd use a UI or coordinates of the face/arm.
h, w, _ = image.shape
skin_sample = image[h//3:2*h//3, w//3:2*w//3]
skin_sample_rgb = cv2.cvtColor(skin_sample, cv2.COLOR_BGR2RGB)
# 3. Calculate Distribution (Mean and Covariance)
x_full, y_full = get_chromaticity(image)
x_skin, y_skin = get_chromaticity(skin_sample)
# Flatten and calculate stats for the skin sample
skin_data = np.stack((x_skin.flatten(), y_skin.flatten()), axis=1)
mean = np.mean(skin_data, axis=0)
cov = np.cov(skin_data, rowvar=False)
inv_cov = np.linalg.inv(cov)
# 4. Skin Detection (Mahalanobis Distance or Simple Threshold)
# We calculate how "close" every pixel's xy is to the skin mean
diff = np.stack((x_full - mean[0], y_full - mean[1]), axis=-1)
# Calculate distance: (dist = (p-m)^T * InvCov * (p-m))
dist = np.einsum('ijk,kl,ijl->ij', diff, inv_cov, diff)
# Threshold: Pixels with small distance are skin (Threshold ~2.0-5.0)
skin_mask = dist < 2.0
result = image_rgb.copy()
result[~skin_mask] = [255, 255, 255] # Paint non-skin white
# --- Visualization with Subplots ---
plt.figure(figsize=(12, 8))
plt.subplot(2, 3, 1)
plt.title("1. Original Image")
plt.imshow(image_rgb)
plt.axis('off')
plt.subplot(2, 3, 2)
plt.title("2. Skin Sample (Crop)")
plt.imshow(skin_sample_rgb)
plt.axis('off')
plt.subplot(2, 3, 3)
plt.title("3. x-Chromaticity Map")
plt.imshow(x_full, cmap='hot')
plt.colorbar()
plt.subplot(2, 3, 4)
plt.title("4. Chromaticity Distribution")
plt.scatter(x_full.flatten()[::100], y_full.flatten()[::100], c='gray', s=1, alpha=0.1, label='All')
plt.scatter(x_skin.flatten()[::10], y_skin.flatten()[::10], c='red', s=1, label='Skin')
plt.xlabel('x'); plt.ylabel('y'); plt.legend()
plt.subplot(2, 3, 5)
plt.title("5. Detection Mask")
plt.imshow(skin_mask, cmap='gray')
plt.subplot(2, 3, 6)
plt.title("6. Final Result")
plt.imshow(result)
plt.axis('off')
plt.tight_layout()
plt.show()