I’m having problems with values for R1, C1, C2 in step 6:
I don’t want to use dlib or yunet for my solution!
- Find the row number R1 with minimum row sum of gray level in UPART. Find the column numbers C1 and C2 with minimum column sum of gray
level in REYE and LEYE. So, (R1, C1) coordinate represents middle
point of right eyeball and (R1, C2) coordinate represents middle point
of left eyeball.
I get the following output:
C:\Users\cam30\OneDrive\Desktop>python ainv.py
x: 359 y: 242
w: 366 h: 366
Row sums in UPART: [13515 15300 16575 16065 17085 18615 19380 19380 19635 20655 21165 21165
20145 20400 20655 21165 21165 20655 21675 22440 21675 24735 26775 28305
28305 28815 29835 31365 32895 33660 35445 36975 37230 36975 37230 37995
38760 39015 39015 39780 39270 39015 39780 40800 41055 42075 43605 43350
42330 41820 42585 43095 43605 43350 43095 43095 43095 43095 42840 42585
42585 42330 43095 43605 44115 44625 44880 44625 44880 45390 45390 45390
45390 45645 45900 46410 47175 47175 47940 47940 47685 47940 48450 48450
48450 48705 49215 46920 45390 46665 45135 43350 41820 35955 31110 27285
24480 21420 22950 22950 24480 27540 29835 33915 35955 39525 43095 48450
48705 49725 50490 49470 44880 45900 43860 39525 38505 35445 31620 29325
22950 21675 24735 25755 26520 26775 25755 28050 29325 29580 29835 30090
28050 30855 36210 35955 35700 35190 40035 44625 47685 47940 48705 47685
47940 49470 54315 55335 55845 56100 58905 59925 59670 58395 59160 59160
59415 59415 59160 59670 59160 59415 59160 59160 58905 59670 58395 59160
59670 60945 61200 62985 62985 63750 64005 64005 64515 65790 65790 65280
66045 66555 65535]
Selected R1: 0
Column sums in REYE: [ 9690 6630 5865 4335 5100 5610 6630 8160 8670 9180 9180 8925
8670 8415 8415 8415 8415 8160 7905 7140 5355 3825 4590 4590
4845 4845 4845 3570 3060 1785 0 255 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 1530 5865 6885 8925 11730 13770 14535 14025 14790 15045 15300
15300 15555 15555 15555 15555 15555 15555 15555 15810 16065 16065 16320
16320 16320 17340 16575 17340 17595 17085 17340 18360 18360 20910 23205
23715 25755 27285 31875 33915 33915 35445 35955 37485 37740 37740 38760
39015 39780 41055 41310 41565 41565 41565 41055 40290 39525 39525 40035
40290 39780 40035 39780 39015 38760 39270 40290 40290 39780 39270 38760
39015 39525 40035 40035 39780 40290 40035 41565 41820 42075 42330 42075
42585 41565 41565 42585 41820 42330 42330 42585 42840 42840 42075 42840
44370 44880 45390 45390 45135 43860 42840 42840 43605 44625 44115 42840
42330 41820 42585 42840 42840 42840 44115 45135 44625 44115 44625 44370
45135 44625 39780 41055 40800 41055 40290 41055 41055 40035 39270 39525
39525 39780 39015]
Selected C1: 30
An error occurred: Error: Unable to determine the column for the right eye.
- Detect the rectangular face area from input face image using Matlab in-built object function. If number of detected face is more than one,
an error message will be displayed.- Crop the detected rectangular face area and detect the significance eye-region using Matlab in-built object function.
- The cropped rectangular face image is histogram equalized and then converted into binary image.
- The binary image of face is divided horizontally into two parts. Upper part that contains two eyes is denoted by UPART and lower part
that contains mouth is denoted by LPART.- Divide UPART vertically into two parts. One part that contains right eye is denoted by REYE and other part that contains left eye is
denoted by LEYE.- Find the row number R1 with minimum row sum of gray level in UPART. Find the column numbers C1 and C2 with minimum column sum of gray
level in REYE and LEYE. So, (R1, C1) coordinate represents middle
point of right eyeball and (R1, C2) coordinate represents middle point
of left eyeball.- Find the row number R2 with minimum row sum of gray level in LPART. So, R2 row represents the mouth row.
- Calculate the midpoint C3 of two eye ball. So, C3= (C1+ C2) /2 and the coordinate (R2, C3) is middle point of mouth.
- Draw a triangle by three coordinate points left eyeball (R1, C1), right eyeball (R1, C2) & mouth point (R2, C3).
- Calculate slope (m1) of triangle sides from mouth point (R2, C3) to right eyeball (R1, C1) and slope (m2) of triangle sides from mouth
point (R2, C3) to left eyeball (R1, C2).- Find the face angle (A) using formula: A = tan-1( (m1- m2) / (1 + m1 * m2) )
- Determine age group based on the face angle (A).
import cv2
import numpy as np
import matplotlib.pyplot as plt
def detect_face_angle(image_path):
try:
# Step 1: Load image and detect face
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml')
# Read the input image
image = cv2.imread(image_path)
if image is None:
raise ValueError("Error: Unable to read the input image. Check the file path.")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(100, 100))
if len(faces) > 1:
raise ValueError("Error: More than one face detected.")
elif len(faces) == 0:
raise ValueError("Error: No face detected.")
# Extract the face region
x, y, w, h = faces[0]
print("x: ", x, " y: ", y)
print("w: ", w, " h: ", h)
face_image = gray[y:y+h, x:x+w]
#plt.subplot(2, 3, 1)
#plt.imshow(face_image, cmap='gray')
#plt.title("Face")
# Step 2: Detect eye region
eyes = eye_cascade.detectMultiScale(face_image)
if len(eyes) < 2:
raise ValueError("Error: Less than two eyes detected in the face region.")
# Step 3: Histogram equalization and binary conversion
face_hist_eq = cv2.equalizeHist(face_image)
#plt.subplot(2, 3, 4)
#plt.imshow(face_hist_eq, cmap='gray')
#plt.title("Equalization (face_hist_eq)")
_, binary_image = cv2.threshold(face_hist_eq, 128, 255, cv2.THRESH_BINARY)
# Step 4: Divide face into UPART and LPART
h, w = binary_image.shape
UPART = binary_image[:h//2, :]
LPART = binary_image[h//2:, :]
#plt.subplot(2, 3, 2)
#plt.imshow(UPART, cmap='gray')
#plt.title("Upper Face (UPART)")
#plt.subplot(2, 3, 3)
#plt.imshow(LPART, cmap='gray')
#plt.title("Lower Face (LPART)")
# Step 5: Divide UPART into REYE and LEYE
REYE = UPART[:, :w//2]
LEYE = UPART[:, w//2:]
#plt.subplot(2, 3, 5)
#plt.imshow(REYE, cmap='gray')
#plt.title("Right Eye (REYE)")
#plt.subplot(2, 3, 6)
#plt.imshow(LEYE, cmap='gray')
#plt.title("Left Eye (LEYE)")
plt.show()
# Step 6: Find R1, C1, and C2
R1 = np.argmin(np.sum(UPART, axis=1)) # Row with minimum row sum in UPART
print("Row sums in UPART:", np.sum(UPART, axis=1))
print("Selected R1:", R1)
if np.sum(UPART[R1, :]) == 0:
raise ValueError("Error: Unable to determine the upper row for eyes.")
#column_sums = np.sum(REYE, axis=0)
# Check if there are any non-numeric values
#assert not (np.isnan(column_sums)).any(), "There are NaNs in the data"
#C1 = np.argmin(np.abs(column_sums)) # Find index of column with minimum sum
C1 = np.argmin(np.sum(REYE, axis=0)) # Column with minimum column sum in REYE
print("Column sums in REYE:", np.sum(REYE, axis=0))
print("Selected C1:", C1)
if np.sum(REYE[:, C1]) == 0:
raise ValueError("Error: Unable to determine the column for the right eye.")
C2 = np.argmin(np.sum(LEYE, axis=0)) + w//2 # Adjust C2 relative to full image
print("Column sums in LEYE:", np.sum(LEYE, axis=0))
print("Selected C2:", C2)
if np.sum(LEYE[:, C2 - w//2]) == 0:
raise ValueError("Error: Unable to determine the column for the left eye.")
# Step 7: Find R2
R2 = np.argmin(np.sum(LPART, axis=1)) + h//2 # Adjust R2 relative to full image4
print("Selected R2:", R2)
if np.sum(LPART[R2 - h//2, :]) == 0:
raise ValueError("Error: Unable to determine the row for the mouth.")
# Step 8: Calculate midpoint C3
C3 = (C1 + C2) // 2
# Step 9: Draw triangle
################## image
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
#plt.scatter([x], [y], color='blue', s=50)
#plt.scatter([w], [h], color='yellow', s=50)
plt.scatter([x + C1, x + C2, x + C3], [y + R1, y + R1, y + R2], color='red', s=50)
plt.plot([x + C1, x + C2, x + C3, x + C1], [y + R1, y + R1, y + R2, y + R1], 'g-')
plt.show()
# Step 10: Calculate slopes
m1 = (R2 - R1) / (C3 - C1) if C3 != C1 else np.inf
m2 = (R2 - R1) / (C3 - C2) if C3 != C2 else np.inf
# Step 11: Calculate face angle
A = np.degrees(np.arctan(abs((m1 - m2) / (1 + m1 * m2))))
print("A: ", A)
# Step 12: Determine age group based on the face angle (A)
# Display result
if A < 44: print("< 18")
elif 44 <= A <= 48: print("18 to 25")
elif 49 <= A <= 54: print("26 to 35")
elif 55 <= A <= 60: print("36 to 45")
elif A > 60: print("> 45")
else: print("None") # Handle invalid input if needed)
except Exception as e:
print(f"An error occurred: {e}")
# Usage
detect_face_angle("test.jpg")