Jelajahi Sumber

feat(image): 更新图片合成服务中的标签位置和偏移功能

- 修改标签位置参数支持更多对齐方式包括底部左右对齐和右侧上下对齐
- 添加标签偏移量参数支持(dx, dy)坐标调整
- 实现底部标签的左对齐和右对齐功能
- 实现右侧标签的顶部对齐和底部对齐功能
- 优化标签绘制逻辑区分底部组和右侧组的不同对齐方式
- 在API调用中将标签位置从right改为bottom-right
- 添加标签偏移量参数到图像合成函数接口
rambo 1 bulan lalu
induk
melakukan
193849344b
2 mengubah file dengan 40 tambahan dan 12 penghapusan
  1. 5 2
      python/api.py
  2. 35 10
      python/service/shoe_main_image_compose.py

+ 5 - 2
python/api.py

@@ -2459,16 +2459,19 @@ async def shoeCompose(params: ShoesComposes):
         for img in item.images:
             sub_image_path = img.get("image_path")
             img['image_path'] = await cutOutImage(sub_image_path)
+        # print("item dict", item.__dict__)
         result_url = compose_shoe_main_image(template=tpl,
                                              data=item.__dict__,
-                                             label_pos="right",
+                                             label_pos="bottom-right",
                                              shoe_scale=0.9,
                                              font_path="resources/ttl/MiSans-Light.ttf",
                                              upload=True,
                                              info_bottom_margin=20,
                                              label_font_size=30,
                                              info_bar_height=40,
-                                             info_font_size=34)
+                                             info_font_size=34,
+                                             label_offset=(0, 0)
+                                             )
         postData.append({"base_image": main_image_url, "reference_image": reference_image, 'past_image': result_url})
     headers = {
         "Authorization": f"Bearer {settings.USER_TOKEN}",

+ 35 - 10
python/service/shoe_main_image_compose.py

@@ -90,7 +90,7 @@ def _detect_band_widths(canvas, band_color=None, tolerance=30):
     band_color 为 None 时,从模板左上角采样取中值作为基准色。
     """
     a = np.asarray(canvas)
-    rgb = a[:, :, :3].astype(float)                 # 只用 RGB 通道做颜色判定
+    rgb = a[:, :, :3].astype(float)  # 只用 RGB 通道做颜色判定
     alpha = a[:, :, 3] if a.shape[2] >= 4 else None  # 有透明通道时排除透明像素
     H, W = rgb.shape[:2]
     if band_color is None:
@@ -240,11 +240,14 @@ def compose_shoe_main_image(
         cell_pad=4,  # 每格上下留白
         shoe_width_limit_ratio=1.15,  # 鞋子最大宽度 = 该格浅色区域宽度 * 比例(可略溢出)
         shoe_scale=1.0,  # 鞋子最终尺寸缩放系数:1.0=自动适配大小,>1 放大,<1 缩小
-        label_pos="bottom",  # 颜色文本位置:"bottom"下方 | "right"右侧(图1样式)
+        # 颜色文本位置:下方组 bottom(居中)/bottom-left(左对齐)/bottom-right(右对齐);
+        #              右侧组 right(居中)/right-top(顶对齐)/right-bottom(底对齐)
+        label_pos="bottom",
         label_font_size=15,
         label_color=(60, 60, 60),
         label_dot=True,  # 颜色文本前是否画小圆点(取鞋子主色)
         label_gap=5,  # 鞋与颜色文本的间距
+        label_offset=(0, 0),  # 颜色文本偏移量 (dx, dy):dx 左右(>0 右移),dy 上下(>0 下移)
         shoe_center_offset=0,  # 鞋子中心相对浅色区域中心的水平偏移
         # ---- C区域:底部文本信息 ----
         info_bar=True,  # True=画圆角信息条;False=只画文字
@@ -415,6 +418,13 @@ def compose_shoe_main_image(
                 .format(area_top, area_bottom))
         cell_h = (area_bottom - area_top) / n
         lab_font = _load_font(font_path, label_font_size)
+        # 颜色文本偏移量 (dx, dy):dx 左右(>0 右移),dy 上下(>0 下移)
+        try:
+            label_dx, label_dy = int(label_offset[0]), int(label_offset[1])
+        except (TypeError, ValueError, IndexError):
+            label_dx, label_dy = 0, 0
+        # 文本位置分组:below 组在鞋下方(bottom/bottom-left/bottom-right),其余在鞋右侧
+        below = label_pos in ("bottom", "bottom-left", "bottom-right")
 
         for i, item in enumerate(shoes):
             if isinstance(item, str):
@@ -422,6 +432,7 @@ def compose_shoe_main_image(
             else:
                 shoe_src = item.get("image")
                 color_name = str(item.get("color", ""))
+            # print("shoe_src", shoe_src)
             shoe_im = _trim_alpha(_to_image(shoe_src).convert("RGBA"))
             sw0, sh0 = shoe_im.size
 
@@ -442,7 +453,7 @@ def compose_shoe_main_image(
 
             # 该格内鞋子可占用的最大盒子:已扣除留白与颜色文本,
             # 保证"鞋 + 颜色名称"整体都落在浅色区内、绝不超出。
-            if label_pos == "bottom":
+            if below:
                 box_w = bw - 2 * margin
                 box_h = cell_h - 2 * int(cell_pad) - (label_h + int(label_gap) if color_name else 0)
             else:  # right:鞋在左、文本紧跟其右,两者都要在带内
@@ -457,7 +468,7 @@ def compose_shoe_main_image(
             if (sw, sh) != (sw0, sh0):
                 shoe_im = shoe_im.resize((sw, sh), Image.LANCZOS)
 
-            if label_pos == "bottom":
+            if below:
                 sx = int(max(margin, (bw - sw) / 2 + float(shoe_center_offset)))
                 block_h = sh + (int(label_gap) + label_h if color_name else 0)
                 sy = int(cell_y0 + max(0, (cell_h - block_h) / 2))
@@ -472,13 +483,27 @@ def compose_shoe_main_image(
 
             if color_name:
                 dot_color = _dominant_color(shoe_im) if label_dot else None
-                if label_pos == "bottom":
-                    ly = sy + sh + int(label_gap)
-                    _draw_color_label(draw, lab_font, color_name, int(sx + sw / 2), ly,
-                                      label_color, dot=dot_color, align="center")
+                if below:
+                    # 鞋下方:垂直在鞋底+间距;水平按 bottom / bottom-left / bottom-right 对齐
+                    ly = sy + sh + int(label_gap) + label_dy
+                    if label_pos == "bottom-right":      # 右对齐:文本右缘贴鞋右缘
+                        lx, align = int(sx + sw - label_w) + label_dx, "left"
+                    elif label_pos == "bottom-left":     # 左对齐:文本左缘贴鞋左缘
+                        lx, align = int(sx) + label_dx, "left"
+                    else:                                 # bottom:水平居中
+                        lx, align = int(sx + sw / 2) + label_dx, "center"
+                    _draw_color_label(draw, lab_font, color_name, lx, ly,
+                                      label_color, dot=dot_color, align=align)
                 else:
-                    ly = sy + (sh - label_h) // 2
-                    _draw_color_label(draw, lab_font, color_name, label_x, ly,
+                    # 鞋右侧:水平在鞋右+间距;垂直按 right / right-top / right-bottom 对齐
+                    lx = int(label_x) + label_dx
+                    if label_pos == "right-top":         # 顶对齐:文本顶贴鞋顶
+                        ly = sy + label_dy
+                    elif label_pos == "right-bottom":    # 底对齐:文本底贴鞋底
+                        ly = sy + sh - label_h + label_dy
+                    else:                                 # right:垂直居中
+                        ly = sy + (sh - label_h) // 2 + label_dy
+                    _draw_color_label(draw, lab_font, color_name, lx, ly,
                                       label_color, dot=dot_color, align="left")
 
     # ---------- 调试叠加图 ----------