diff --git a/app/service/design_fast/pipeline/no_seg_print_painting.py b/app/service/design_fast/pipeline/no_seg_print_painting.py index 0ffaa93..a1db587 100644 --- a/app/service/design_fast/pipeline/no_seg_print_painting.py +++ b/app/service/design_fast/pipeline/no_seg_print_painting.py @@ -418,6 +418,9 @@ class NoSegPrintPainting: def tile_image(pattern, mask, dim, gap_x, gap_y, canvas_h, canvas_w, location, angle=0): """ 按照指定的 X/Y 间距平铺印花,并支持旋转 + 【修改版】以被平铺图案的【中心】作为平铺基准点 + + :param location: [[center_y, center_x]] → 第一个图案中心的坐标 :param angle: 旋转角度 (度数, 逆时针) """ # 1. 确保输入是 RGBA @@ -429,44 +432,52 @@ def tile_image(pattern, mask, dim, gap_x, gap_y, canvas_h, canvas_w, location, a rotated_p = rotate_image(resized_p, angle) p_h, p_w = rotated_p.shape[:2] - # 3. 创建透明单元格 - cell_h, cell_w = p_h + gap_y, p_w + gap_x + # 3. 创建透明单元格(图案放在单元格中心) + cell_h = p_h + gap_y + cell_w = p_w + gap_x + unit_cell = np.zeros((cell_h, cell_w, 4), dtype=np.uint8) - unit_cell[:p_h, :p_w, :] = rotated_p + + # 计算图案在单元格中的左上角位置(让图案居中) + start_y = (cell_h - p_h) // 2 + start_x = (cell_w - p_w) // 2 + unit_cell[start_y:start_y + p_h, start_x:start_x + p_w, :] = rotated_p # 4. 执行平铺 - tiles_y = (canvas_h // cell_h) + 2 - tiles_x = (canvas_w // cell_w) + 2 + tiles_y = (canvas_h // cell_h) + 3 # 多加一点余量更安全 + tiles_x = (canvas_w // cell_w) + 3 full_tiled = np.tile(unit_cell, (tiles_y, tiles_x, 1)) - # 5. 裁剪平铺层 - offset_x = int(location[0][1] % cell_w) - offset_y = int(location[0][0] % cell_h) + # 5. 计算偏移(关键修改:以中心为基准) + center_y, center_x = location[0][0], location[0][1] # 第一个图案的中心位置 + + # 计算从哪个位置开始裁剪,才能让中心落在指定坐标 + offset_y = int((center_y - (p_h // 2)) % cell_h) + offset_x = int((center_x - (p_w // 2)) % cell_w) + tiled_layer = full_tiled[offset_y: offset_y + canvas_h, offset_x: offset_x + canvas_w] - # 6. 创建纯白色背景并合成 - # 创建一个纯白色的 BGR 画布 + # 6. 创建纯白色背景并合成(保持你原来的风格) white_background = np.full((canvas_h, canvas_w, 3), 255, dtype=np.uint8) - # 分离平铺层的颜色通道和 Alpha 通道 tiled_bgr = tiled_layer[:, :, :3] - alpha_mask = tiled_layer[:, :, 3] / 255.0 # 归一化到 0-1 - alpha_mask = cv2.merge([alpha_mask, alpha_mask, alpha_mask]) # 扩展到 3 通道 + alpha_mask = tiled_layer[:, :, 3] / 255.0 + alpha_mask = cv2.merge([alpha_mask, alpha_mask, alpha_mask]) - # 执行 Alpha 混合:结果 = 平铺层 * alpha + 背景 * (1 - alpha) tiled_print = (tiled_bgr * alpha_mask + white_background * (1 - alpha_mask)).astype(np.uint8) - resized_mask = cv2.resize(mask, dim, interpolation=cv2.INTER_NEAREST) # mask用最近邻,不模糊 - rotated_mask = rotate_image(resized_mask, angle) + # ====================== 处理 Mask ====================== + # Mask 也同样居中处理 + resized_mask = cv2.resize(mask, dim, interpolation=cv2.INTER_NEAREST) + rotated_mask = rotate_image(resized_mask, angle) # 注意:mask也需要旋转 - # 创建mask单元 unit_mask = np.zeros((cell_h, cell_w), dtype=np.uint8) - unit_mask[:p_h, :p_w] = rotated_mask + unit_mask[start_y:start_y + p_h, start_x:start_x + p_w] = rotated_mask - # 平铺mask full_mask_tiled = np.tile(unit_mask, (tiles_y, tiles_x)) - tiled_mask = full_mask_tiled[offset_y: offset_y + canvas_h, offset_x: offset_x + canvas_w] + tiled_mask = full_mask_tiled[offset_y: offset_y + canvas_h, + offset_x: offset_x + canvas_w] return tiled_print, cv2.bitwise_not(tiled_mask) diff --git a/app/service/design_fast/pipeline/print_painting.py b/app/service/design_fast/pipeline/print_painting.py index c9f4653..ebf5856 100644 --- a/app/service/design_fast/pipeline/print_painting.py +++ b/app/service/design_fast/pipeline/print_painting.py @@ -479,6 +479,9 @@ class PrintPainting: def tile_image(pattern, mask, dim, gap_x, gap_y, canvas_h, canvas_w, location, angle=0): """ 按照指定的 X/Y 间距平铺印花,并支持旋转 + 【修改版】以被平铺图案的【中心】作为平铺基准点 + + :param location: [[center_y, center_x]] → 第一个图案中心的坐标 :param angle: 旋转角度 (度数, 逆时针) """ # 1. 确保输入是 RGBA @@ -490,45 +493,52 @@ def tile_image(pattern, mask, dim, gap_x, gap_y, canvas_h, canvas_w, location, a rotated_p = rotate_image(resized_p, angle) p_h, p_w = rotated_p.shape[:2] - # 3. 创建透明单元格 - cell_h, cell_w = p_h + gap_y, p_w + gap_x + # 3. 创建透明单元格(图案放在单元格中心) + cell_h = p_h + gap_y + cell_w = p_w + gap_x + unit_cell = np.zeros((cell_h, cell_w, 4), dtype=np.uint8) - unit_cell[:p_h, :p_w, :] = rotated_p + + # 计算图案在单元格中的左上角位置(让图案居中) + start_y = (cell_h - p_h) // 2 + start_x = (cell_w - p_w) // 2 + unit_cell[start_y:start_y + p_h, start_x:start_x + p_w, :] = rotated_p # 4. 执行平铺 - tiles_y = (canvas_h // cell_h) + 2 - tiles_x = (canvas_w // cell_w) + 2 + tiles_y = (canvas_h // cell_h) + 3 # 多加一点余量更安全 + tiles_x = (canvas_w // cell_w) + 3 full_tiled = np.tile(unit_cell, (tiles_y, tiles_x, 1)) - # 5. 裁剪平铺层 - offset_x = int(location[0][1] % cell_w) - offset_y = int(location[0][0] % cell_h) + # 5. 计算偏移(关键修改:以中心为基准) + center_y, center_x = location[0][0], location[0][1] # 第一个图案的中心位置 + + # 计算从哪个位置开始裁剪,才能让中心落在指定坐标 + offset_y = int((center_y - (p_h // 2)) % cell_h) + offset_x = int((center_x - (p_w // 2)) % cell_w) + tiled_layer = full_tiled[offset_y: offset_y + canvas_h, offset_x: offset_x + canvas_w] - # 6. 创建纯白色背景并合成 - # 创建一个纯白色的 BGR 画布 + # 6. 创建纯白色背景并合成(保持你原来的风格) white_background = np.full((canvas_h, canvas_w, 3), 255, dtype=np.uint8) - # 分离平铺层的颜色通道和 Alpha 通道 tiled_bgr = tiled_layer[:, :, :3] - alpha_mask = tiled_layer[:, :, 3] / 255.0 # 归一化到 0-1 - alpha_mask = cv2.merge([alpha_mask, alpha_mask, alpha_mask]) # 扩展到 3 通道 + alpha_mask = tiled_layer[:, :, 3] / 255.0 + alpha_mask = cv2.merge([alpha_mask, alpha_mask, alpha_mask]) - # 执行 Alpha 混合:结果 = 平铺层 * alpha + 背景 * (1 - alpha) tiled_print = (tiled_bgr * alpha_mask + white_background * (1 - alpha_mask)).astype(np.uint8) - # 处理mask的平铺 - resized_mask = cv2.resize(mask, dim, interpolation=cv2.INTER_NEAREST) # mask用最近邻,不模糊 - rotated_mask = rotate_image(resized_mask, angle) + # ====================== 处理 Mask ====================== + # Mask 也同样居中处理 + resized_mask = cv2.resize(mask, dim, interpolation=cv2.INTER_NEAREST) + rotated_mask = rotate_image(resized_mask, angle) # 注意:mask也需要旋转 - # 创建mask单元 unit_mask = np.zeros((cell_h, cell_w), dtype=np.uint8) - unit_mask[:p_h, :p_w] = rotated_mask + unit_mask[start_y:start_y + p_h, start_x:start_x + p_w] = rotated_mask - # 平铺mask full_mask_tiled = np.tile(unit_mask, (tiles_y, tiles_x)) - tiled_mask = full_mask_tiled[offset_y: offset_y + canvas_h, offset_x: offset_x + canvas_w] + tiled_mask = full_mask_tiled[offset_y: offset_y + canvas_h, + offset_x: offset_x + canvas_w] return tiled_print, cv2.bitwise_not(tiled_mask)