100% found this document useful (1 vote)
21 views6 pages

Face Beauty Analysis with Golden Ratio

This document is a Python script that analyzes images for beauty based on the golden ratio by detecting faces and calculating beauty scores. It uses OpenCV for image processing and includes functions for detecting faces, drawing geometric shapes, and computing beauty metrics. The script can be run with a command line interface or through a file dialog for selecting images.

Uploaded by

Banani Pattnaik
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
21 views6 pages

Face Beauty Analysis with Golden Ratio

This document is a Python script that analyzes images for beauty based on the golden ratio by detecting faces and calculating beauty scores. It uses OpenCV for image processing and includes functions for detecting faces, drawing geometric shapes, and computing beauty metrics. The script can be run with a command line interface or through a file dialog for selecting images.

Uploaded by

Banani Pattnaik
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

import cv2

import numpy as np
import math
import argparse
import os
import sys

def choose_file_dialog():
try:
import tkinter as tk
from tkinter import filedialog
except Exception as e:
print("tkinter not available on this system. Please run with --
image <path> instead.")
raise
root = [Link]()
[Link]()
file_path = [Link](title="Select photo (from
your phone)", filetypes=[("Image files", "*.jpg *.jpeg *.png *.bmp")])
[Link]()
return file_path

# Config
MIN_FACE_SIZE = 60
GOLDEN_PHI = (1 + [Link](5)) / 2.0
SPIRAL_POINTS = 700
SPIRAL_T_MAX = 5.5 * [Link]

def get_haar_detector():
casc_path = [Link] +
"haarcascade_frontalface_default.xml"
if not [Link](casc_path):
raise FileNotFoundError("Haar cascade xml not found in
[Link]")
return [Link](casc_path)

def detect_largest_face(img, scaleFactor=1.1, minNeighbors=5,


minSize=(MIN_FACE_SIZE, MIN_FACE_SIZE)):
gray = [Link](img, cv2.COLOR_BGR2GRAY)
detector = get_haar_detector()
faces = [Link](gray, scaleFactor=scaleFactor,
minNeighbors=minNeighbors, minSize=minSize)
if len(faces) == 0:
return None
# pick the largest face (by area)
x, y, w, h = max(faces, key=lambda r: r[2] * r[3])
return (int(x), int(y), int(w), int(h))

def compute_beauty(width, height):

if width <= 0 or height <= 0:


return 0.0, 0.0, GOLDEN_PHI
ratio = max(width, height) / float(min(width, height))
score = max(0.0, 100.0 * (1.0 - abs(ratio - GOLDEN_PHI) /
GOLDEN_PHI))
return score, ratio, GOLDEN_PHI

def regular_hexagon_points(center, radius):


cx, cy = center
pts = []
# rotate by 30 degrees so it looks flat-top
for i in range(6):
theta = [Link](30) + i * ([Link] / 3.0)
x = cx + radius * [Link](theta)
y = cy + radius * [Link](theta)
[Link]((int(round(x)), int(round(y))))
return pts

def draw_hexagon(img, center, radius, color=(0,255,255), thickness=2):


pts = [Link](regular_hexagon_points(center, radius),
dtype=np.int32)
[Link](img, [pts], isClosed=True, color=color,
thickness=thickness, lineType=cv2.LINE_AA)
return pts

def draw_golden_rect(img, x, y, w, h, color=(0,150,255), thickness=2):

phi = GOLDEN_PHI
gx, gy, gw, gh = int(x), int(y), int(w), int(h)
if gw >= gh:
ideal_w = int(round(gh * phi))
if ideal_w <= gw:
gx = int(x + (gw - ideal_w) // 2)
gw = ideal_w
else:
ideal_h = int(round(gw / phi))
gy = int(y + (gh - ideal_h) // 2)
gh = ideal_h
else:
ideal_h = int(round(gw * phi))
if ideal_h <= gh:
gy = int(y + (gh - ideal_h) // 2)
gh = ideal_h
else:
ideal_w = int(round(gh / phi))
gx = int(x + (gw - ideal_w) // 2)
gw = ideal_w
[Link](img, (gx, gy), (gx + gw, gy + gh), color, thickness,
lineType=cv2.LINE_AA)
return (gx, gy, gw, gh)

def draw_golden_spiral(img, center, bbox, color=(0,200,0), thickness=2,


points_count=SPIRAL_POINTS):

cx, cy = center
gx, gy, gw, gh = bbox
max_dim = max(gw, gh, 1)
b = [Link](GOLDEN_PHI) / ([Link] / 2.0)
tmax = SPIRAL_T_MAX
Rtarget = max_dim * 0.9
a = Rtarget / [Link](b * tmax)
pts = []
for i in range(points_count):
t = (i / (points_count - 1)) * tmax
r = a * [Link](b * t)
x = cx + r * [Link](t)
y = cy + r * [Link](t)
[Link]((int(round(x)), int(round(y))))
for i in range(1, len(pts)):
[Link](img, pts[i-1], pts[i], color, thickness,
lineType=cv2.LINE_AA)
return pts

def analyze_image(img, show=True, save=True, out_path=None):


if img is None:
raise ValueError("Empty image provided.")
orig = [Link]()
face = detect_largest_face(img)
if face is None:
print("[WARN] No face detected. Try a clearer frontal face
photo.")
return None
x, y, w, h = face
# Draw face bbox
[Link](orig, (x,y), (x+w, y+h), (255,0,0), 2,
lineType=cv2.LINE_AA)
cx = x + w//2
cy = y + h//2

# Hexagon: radius ~ 0.45 * min(w,h)


radius = int(round(0.45 * min(w, h)))
hex_pts = draw_hexagon(orig, (cx, cy), radius, color=(0,255,255),
thickness=2)

# Golden rectangle inside face bbox


grect = draw_golden_rect(orig, x, y, w, h, color=(0,150,255),
thickness=2)
gx, gy, gw, gh = grect
gcenter = (gx + gw//2, gy + gh//2)

# Golden spiral centered on golden rect center


draw_golden_spiral(orig, gcenter, grect, color=(0,200,0),
thickness=2)

# Scores: bounding box & hex bounding box


score_bbox, ratio_bbox, phi = compute_beauty(w, h)
# hex bounding box
hx = [p[0] for p in hex_pts]; hy = [p[1] for p in hex_pts]
h_w = max(hx) - min(hx)
h_h = max(hy) - min(hy)
score_hex, ratio_hex, _ = compute_beauty(h_w, h_h)
final_score = (score_bbox + score_hex) / 2.0

# Put text
H = [Link][0]
[Link](orig, f"phi={phi:.3f}", (10, H-80),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (220,220,220), 2, cv2.LINE_AA)
[Link](orig, f"Face ratio:{ratio_bbox:.3f} Score:
{score_bbox:.2f}/100", (10, H-50), cv2.FONT_HERSHEY_SIMPLEX, 0.6,
(240,240,240), 2, cv2.LINE_AA)
[Link](orig, f"Hex ratio:{ratio_hex:.3f} Score:
{score_hex:.2f}/100", (10, H-25), cv2.FONT_HERSHEY_SIMPLEX, 0.6,
(240,240,240), 2, cv2.LINE_AA)
[Link](orig, f"Final score (avg): {final_score:.2f}/100", (10,
30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (10,240,10), 2, cv2.LINE_AA)

if save:
if out_path is None:
out_path = "analyzed_image.png"
[Link](out_path, orig)
print(f"[INFO] Annotated image saved to: {out_path}")

if show:
[Link]("Analysis", orig)
[Link](0)
[Link]()

return {
"face_bbox": (x,y,w,h),
"face_ratio": ratio_bbox,
"face_score": score_bbox,
"hex_ratio": ratio_hex,
"hex_score": score_hex,
"final_score": final_score,
"annotated_image": orig
}

def main():
parser = [Link](description="Analyze uploaded
phone photo for golden-ratio beauty")
parser.add_argument("--image", type=str, help="Path to input image
(preferred for phone photos)")
parser.add_argument("--no-display", action="store_true", help="Do
not show image window (headless)")
parser.add_argument("--out", type=str, default=None, help="Output
annotated filename (optional)")
args = parser.parse_args()

if [Link] is None:
# open file dialog
try:
path = choose_file_dialog()
except Exception:
print("File dialog failed. Run again with --image
<path_to_image>.")
[Link](1)
if not path:
print("No file selected. Exiting.")
[Link](0)
img_path = path
else:
img_path = [Link]
if not [Link](img_path):
print("Image path not found:", img_path)
[Link](1)

img = [Link](img_path)
if img is None:
print("Failed to load image. Is it corrupted or unsupported
format?")
[Link](1)

base = [Link](img_path)
name, ext = [Link](base)
out_name = [Link] if [Link] else f"analyzed_{name}.png"

print("[INFO] Running analysis on:", img_path)


res = analyze_image(img, show=not args.no_display, save=True,
out_path=out_name)
if res is None:
print("Analysis returned no result (likely no face detected).
Try another clearer frontal photo.")
else:
print("Result:")
print(f" Face bbox: {res['face_bbox']}")
print(f" Face ratio: {res['face_ratio']:.3f} Score:
{res['face_score']:.2f}/100")
print(f" Hex ratio: {res['hex_ratio']:.3f} Score:
{res['hex_score']:.2f}/100")
print(f" Final score (avg) = {res['final_score']:.2f}/100")

if __name__ == "__main__":
main()

You might also like