Improve eyebrow mask
parent
ab3b73631b
commit
01ef955372
|
@ -285,6 +285,65 @@ def create_eyes_mask(face: Face, frame: Frame) -> (np.ndarray, np.ndarray, tuple
|
|||
|
||||
return mask, eyes_cutout, (min_x, min_y, max_x, max_y), eyes_polygon
|
||||
|
||||
def create_curved_eyebrow(points):
|
||||
if len(points) >= 5:
|
||||
# Sort points by x-coordinate
|
||||
sorted_idx = np.argsort(points[:, 0])
|
||||
sorted_points = points[sorted_idx]
|
||||
|
||||
# Calculate dimensions
|
||||
x_min, y_min = np.min(sorted_points, axis=0)
|
||||
x_max, y_max = np.max(sorted_points, axis=0)
|
||||
width = x_max - x_min
|
||||
height = y_max - y_min
|
||||
|
||||
# Create more points for smoother curve
|
||||
num_points = 50
|
||||
x = np.linspace(x_min, x_max, num_points)
|
||||
|
||||
# Fit quadratic curve through points for more natural arch
|
||||
coeffs = np.polyfit(sorted_points[:, 0], sorted_points[:, 1], 2) # Changed to quadratic
|
||||
y = np.polyval(coeffs, x)
|
||||
|
||||
# Create points for top and bottom curves with consistent offsets
|
||||
top_offset = height * 0.3 # Simplified offset for cleaner curve
|
||||
bottom_offset = height * 0.1 # Thinner bottom curve
|
||||
|
||||
# Create smooth curves
|
||||
top_curve = y - top_offset
|
||||
bottom_curve = y + bottom_offset
|
||||
|
||||
# Create curved endpoints with slight taper
|
||||
end_points = 5
|
||||
start_x = np.linspace(x[0] - width * 0.1, x[0], end_points)
|
||||
end_x = np.linspace(x[-1], x[-1] + width * 0.1, end_points)
|
||||
|
||||
# Create tapered ends
|
||||
start_curve = np.column_stack((
|
||||
start_x,
|
||||
np.linspace(bottom_curve[0], top_curve[0], end_points)
|
||||
))
|
||||
end_curve = np.column_stack((
|
||||
end_x,
|
||||
np.linspace(bottom_curve[-1], top_curve[-1], end_points)
|
||||
))
|
||||
|
||||
# Combine all points to form a smooth contour
|
||||
contour_points = np.vstack([
|
||||
start_curve,
|
||||
np.column_stack((x, top_curve)),
|
||||
end_curve,
|
||||
np.column_stack((x[::-1], bottom_curve[::-1]))
|
||||
])
|
||||
|
||||
# Add slight padding for better coverage
|
||||
center = np.mean(contour_points, axis=0)
|
||||
vectors = contour_points - center
|
||||
padded_points = center + vectors * 1.15 # 15% padding
|
||||
|
||||
return padded_points
|
||||
return points
|
||||
|
||||
def create_eyebrows_mask(face: Face, frame: Frame) -> (np.ndarray, np.ndarray, tuple, np.ndarray):
|
||||
mask = np.zeros(frame.shape[:2], dtype=np.uint8)
|
||||
eyebrows_cutout = None
|
||||
|
@ -335,33 +394,30 @@ def create_eyebrows_mask(face: Face, frame: Frame) -> (np.ndarray, np.ndarray, t
|
|||
num_points = 50
|
||||
x = np.linspace(x_min, x_max, num_points)
|
||||
|
||||
# Fit cubic curve through points for more natural arch
|
||||
coeffs = np.polyfit(sorted_points[:, 0], sorted_points[:, 1], 3)
|
||||
# Fit quadratic curve through points for more natural arch
|
||||
coeffs = np.polyfit(sorted_points[:, 0], sorted_points[:, 1], 2) # Changed to quadratic
|
||||
y = np.polyval(coeffs, x)
|
||||
|
||||
# Create points for top and bottom curves with varying offsets
|
||||
top_offset = np.linspace(height * 0.4, height * 0.3, num_points) # Varying offset for more natural shape
|
||||
bottom_offset = np.linspace(height * 0.2, height * 0.15, num_points)
|
||||
|
||||
# Add some randomness to the offsets for more natural look
|
||||
top_offset += np.random.normal(0, height * 0.02, num_points)
|
||||
bottom_offset += np.random.normal(0, height * 0.01, num_points)
|
||||
|
||||
# Smooth the offsets
|
||||
top_offset = cv2.GaussianBlur(top_offset.reshape(-1, 1), (1, 3), 1).reshape(-1)
|
||||
bottom_offset = cv2.GaussianBlur(bottom_offset.reshape(-1, 1), (1, 3), 1).reshape(-1)
|
||||
# Create points for top and bottom curves with consistent offsets
|
||||
top_offset = height * 0.3 # Simplified offset for cleaner curve
|
||||
bottom_offset = height * 0.1 # Thinner bottom curve
|
||||
|
||||
# Create smooth curves
|
||||
top_curve = y - top_offset
|
||||
bottom_curve = y + bottom_offset
|
||||
|
||||
# Create curved endpoints
|
||||
# Create curved endpoints with slight taper
|
||||
end_points = 5
|
||||
start_x = np.linspace(x[0] - width * 0.1, x[0], end_points)
|
||||
end_x = np.linspace(x[-1], x[-1] + width * 0.1, end_points)
|
||||
|
||||
# Create tapered ends
|
||||
start_curve = np.column_stack((
|
||||
np.linspace(x[0] - width * 0.05, x[0], end_points),
|
||||
start_x,
|
||||
np.linspace(bottom_curve[0], top_curve[0], end_points)
|
||||
))
|
||||
end_curve = np.column_stack((
|
||||
np.linspace(x[-1], x[-1] + width * 0.05, end_points),
|
||||
end_x,
|
||||
np.linspace(bottom_curve[-1], top_curve[-1], end_points)
|
||||
))
|
||||
|
||||
|
@ -373,13 +429,10 @@ def create_eyebrows_mask(face: Face, frame: Frame) -> (np.ndarray, np.ndarray, t
|
|||
np.column_stack((x[::-1], bottom_curve[::-1]))
|
||||
])
|
||||
|
||||
# Add padding and smooth the shape
|
||||
# Add slight padding for better coverage
|
||||
center = np.mean(contour_points, axis=0)
|
||||
vectors = contour_points - center
|
||||
padded_points = center + vectors * 1.2 # 20% padding
|
||||
|
||||
# Convert to integer coordinates and draw
|
||||
cv2.fillPoly(mask_roi, [padded_points.astype(np.int32)], 255)
|
||||
padded_points = center + vectors * 1.15 # 15% padding
|
||||
|
||||
return padded_points
|
||||
return points
|
||||
|
|
Loading…
Reference in New Issue