File size: 8,943 Bytes
83e35a7 |
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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
from backend.utils import convert_to_css_pixel, get_panel_type, types
import math
BUBBLE_WIDTH = 200
BUBBLE_HEIGHT = 94
def add_bubble_padding(least_roi_x, least_roi_y, crop_coord):
left,right,top,bottom = crop_coord
panel = get_panel_type(left, right, top, bottom)
image_width = types[panel]['width']
image_height = types[panel]['height']
if least_roi_x == 0:
if panel == '1' or panel == '2':
least_roi_x += 10
elif panel == '3':
least_roi_x += 30
else:
least_roi_x += 20
elif least_roi_x == image_width:
least_roi_x -= BUBBLE_WIDTH + 15
elif least_roi_x >= image_width - BUBBLE_WIDTH:
least_roi_x -= BUBBLE_WIDTH - (image_width - least_roi_x) + 15
if least_roi_y == 0:
if panel == '2':
least_roi_y += 30
else:
least_roi_y += 15
elif least_roi_y == image_height:
least_roi_y -= BUUBLE_HEIGHT + 15
elif least_roi_y >= image_height - BUUBLE_HEIGHT:
least_roi_y -= BUUBLE_HEIGHT - (image_height - least_roi_y) + 15
return least_roi_x, least_roi_y
def get_bubble_position(image_coords, CAM_data=None, lip_coords=None):
"""
Redesigned bubble placement for smart resize - positions relative to actual image content
"""
left, right, top, bottom = image_coords
# Calculate image dimensions within panel
image_width = right - left
image_height = bottom - top
print(f"Image area: {image_width:.0f}x{image_height:.0f} at ({left:.0f}, {top:.0f})")
# Define safe bubble positions relative to the actual image content
safe_positions = _get_safe_image_positions(left, right, top, bottom, image_width, image_height)
# If we have lip coordinates, create face exclusion zones
if lip_coords and lip_coords[0] != -1 and lip_coords[1] != -1:
lip_x, lip_y = lip_coords
# Lip coordinates are already in panel coordinate system
print(f"Lip detected at coords: ({lip_x}, {lip_y})")
# Filter out positions too close to the face
face_exclusion_radius = 60 # Standard exclusion radius
filtered_positions = []
for pos in safe_positions:
distance = math.sqrt((pos[0] - lip_x)**2 + (pos[1] - lip_y)**2)
if distance > face_exclusion_radius:
filtered_positions.append(pos)
if filtered_positions:
safe_positions = filtered_positions
print(f"Filtered to {len(safe_positions)} face-safe positions")
else:
print("Warning: No face-safe positions found, using all safe positions")
# Select the best position (prefer corners and edges of image)
best_position = _select_best_image_position(safe_positions, left, right, top, bottom)
print(f"Selected bubble position: {best_position}")
return best_position
def _get_safe_image_positions(left, right, top, bottom, image_width, image_height):
"""
Generate safe bubble positions relative to the actual image content
"""
positions = []
# Calculate margins to keep bubbles within image bounds
margin_x = BUBBLE_WIDTH / 2 + 20
margin_y = BUBBLE_HEIGHT / 2 + 20
# Define grid within the image area - focus on upper areas
grid_cols = 4
grid_rows = 4 # More rows for better upper area coverage
# Calculate grid cell size within image
cell_width = image_width / grid_cols
cell_height = image_height / grid_rows
# Generate grid positions within image - prioritize upper areas
for row in range(grid_rows):
for col in range(grid_cols):
x = left + col * cell_width + cell_width / 2
y = top + row * cell_height + cell_height / 2
# Ensure bubble fits within image bounds
if (left + margin_x <= x <= right - margin_x and
top + margin_y <= y <= bottom - margin_y):
positions.append((x, y))
# Add extra positions in upper areas for better coverage
upper_positions = []
upper_margin = 40
# Top edge positions
for i in range(1, grid_cols):
x = left + i * cell_width
y = top + upper_margin
if (left + margin_x <= x <= right - margin_x and
top + margin_y <= y <= bottom - margin_y):
upper_positions.append((x, y))
# Upper quarter positions
upper_quarter_y = top + (bottom - top) * 0.25
for i in range(1, grid_cols):
x = left + i * cell_width
y = upper_quarter_y
if (left + margin_x <= x <= right - margin_x and
top + margin_y <= y <= bottom - margin_y):
upper_positions.append((x, y))
positions.extend(upper_positions)
# Add corner positions relative to image - prioritize upper corners
corner_margin = 30
corners = [
(left + corner_margin, top + corner_margin), # Top-left of image (highest priority)
(right - corner_margin, top + corner_margin), # Top-right of image (highest priority)
(left + corner_margin, top + (bottom - top) * 0.2), # Upper-left area
(right - corner_margin, top + (bottom - top) * 0.2), # Upper-right area
(left + corner_margin, bottom - corner_margin), # Bottom-left of image (lower priority)
(right - corner_margin, bottom - corner_margin) # Bottom-right of image (lower priority)
]
for corner in corners:
if (left + margin_x <= corner[0] <= right - margin_x and
top + margin_y <= corner[1] <= bottom - margin_y):
positions.append(corner)
# Add edge positions along image boundaries
edge_positions = []
edge_margin = 50
# Top edge of image
for i in range(1, grid_cols):
x = left + i * cell_width
y = top + edge_margin
if (left + margin_x <= x <= right - margin_x and
top + margin_y <= y <= bottom - margin_y):
edge_positions.append((x, y))
# Right edge of image
for i in range(1, grid_rows):
x = right - edge_margin
y = top + i * cell_height
if (left + margin_x <= x <= right - margin_x and
top + margin_y <= y <= bottom - margin_y):
edge_positions.append((x, y))
positions.extend(edge_positions)
# If still no positions, use image center
if len(positions) == 0:
center_x = left + image_width / 2
center_y = top + image_height / 2
positions.append((center_x, center_y))
print(f"Warning: Image too small, using center position only")
print(f"Generated {len(positions)} safe positions for image area {image_width:.0f}x{image_height:.0f}")
return positions
def _select_best_image_position(positions, left, right, top, bottom):
"""
Select the best position relative to image content
Priority: TOP areas > corners > edges > center
"""
if not positions:
# Fallback to upper area if no positions available
return (left + (right - left) / 2, top + (bottom - top) * 0.2) # 20% from top
# Score positions based on preference
scored_positions = []
for pos in positions:
x, y = pos
score = 0
# STRONGLY prefer upper areas (highest priority)
upper_threshold = (bottom - top) * 0.4 # Top 40% of image
if y < top + upper_threshold:
score += 200 # Much higher score for upper areas
# Prefer top quarter (highest score)
top_quarter = (bottom - top) * 0.25
if y < top + top_quarter:
score += 150
# Prefer corners of image (high score)
corner_threshold = 50
if (x < left + corner_threshold or x > right - corner_threshold) and \
(y < top + corner_threshold or y > bottom - corner_threshold):
score += 100
# Prefer edges of image (medium score)
edge_threshold = 80
if (x < left + edge_threshold or x > right - edge_threshold) or \
(y < top + edge_threshold or y > bottom - edge_threshold):
score += 50
# Prefer right side (common comic bubble placement)
if x > left + (right - left) * 0.6: # Right 40% of image
score += 30
# Penalize lower areas
lower_threshold = (bottom - top) * 0.7 # Bottom 30% of image
if y > top + lower_threshold:
score -= 50 # Negative score for lower areas
scored_positions.append((pos, score))
# Sort by score (highest first) and return the best
scored_positions.sort(key=lambda x: x[1], reverse=True)
best_position = scored_positions[0][0]
print(f"Selected position with score {scored_positions[0][1]} at y={best_position[1]:.0f} (top={top:.0f}, bottom={bottom:.0f})")
return best_position |