针对不同基础形状的特定取色和边框算法。 - 对于矩形类形状,使用动态边框宽度检测 - 对于非矩形形状(椭圆、菱形等),使用Mask提取更准确的填充色
(image: np.ndarray, bbox: list, shape_type: str)
| 391 | |
| 392 | |
| 393 | def extract_style_specific(image: np.ndarray, bbox: list, shape_type: str) -> dict: |
| 394 | """ |
| 395 | 针对不同基础形状的特定取色和边框算法。 |
| 396 | |
| 397 | - 对于矩形类形状,使用动态边框宽度检测 |
| 398 | - 对于非矩形形状(椭圆、菱形等),使用Mask提取更准确的填充色 |
| 399 | """ |
| 400 | fill_hex, stroke_hex, stroke_w = extract_style_colors(image, bbox) |
| 401 | |
| 402 | # 针对非矩形形状,使用 Mask 提取更准确的填充色 |
| 403 | if shape_type in ["ellipse", "cloud", "circle", "diamond", "triangle", "hexagon"]: |
| 404 | x1, y1, x2, y2 = map(int, bbox) |
| 405 | h_img, w_img = image.shape[:2] |
| 406 | x1, y1 = max(0, x1), max(0, y1) |
| 407 | x2, y2 = min(w_img, x2), min(h_img, y2) |
| 408 | |
| 409 | roi = image[y1:y2, x1:x2] |
| 410 | if roi.size > 0: |
| 411 | h, w = roi.shape[:2] |
| 412 | mask = np.zeros((h, w), dtype=np.uint8) |
| 413 | |
| 414 | if shape_type in ["ellipse", "cloud", "circle"]: |
| 415 | cv2.ellipse(mask, (w//2, h//2), (w//2, h//2), 0, 0, 360, 255, -1) |
| 416 | elif shape_type == "diamond": |
| 417 | pts = np.array([[w//2, 0], [w, h//2], [w//2, h], [0, h//2]], dtype=np.int32) |
| 418 | cv2.fillPoly(mask, [pts], 255) |
| 419 | elif shape_type == "triangle": |
| 420 | pts = np.array([[w//2, 0], [w, h], [0, h]], dtype=np.int32) |
| 421 | cv2.fillPoly(mask, [pts], 255) |
| 422 | elif shape_type == "hexagon": |
| 423 | pts = np.array([ |
| 424 | [w//4, 0], [w*3//4, 0], |
| 425 | [w, h//2], |
| 426 | [w*3//4, h], [w//4, h], |
| 427 | [0, h//2] |
| 428 | ], dtype=np.int32) |
| 429 | cv2.fillPoly(mask, [pts], 255) |
| 430 | |
| 431 | # 腐蚀掉边缘区域 |
| 432 | kernel_size = max(3, stroke_w * 2 + 1) |
| 433 | kernel = np.ones((kernel_size, kernel_size), np.uint8) |
| 434 | mask = cv2.erode(mask, kernel) |
| 435 | |
| 436 | if cv2.countNonZero(mask) > 0: |
| 437 | roi_rgb = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB) |
| 438 | masked_pixels = roi_rgb[mask > 0] |
| 439 | masked_pixels = masked_pixels.reshape(-1, 3) |
| 440 | |
| 441 | if masked_pixels.size > 0: |
| 442 | fill_rgb = np.median(masked_pixels, axis=0).astype(int) |
| 443 | fill_hex = "#{:02x}{:02x}{:02x}".format(*map(int, fill_rgb)) |
| 444 | |
| 445 | geo_params = extract_geometric_params(image, bbox, shape_type) |
| 446 | |
| 447 | return { |
| 448 | "fill_color": fill_hex, |
| 449 | "stroke_color": stroke_hex, |
| 450 | "stroke_width": stroke_w, |
no test coverage detected