From acb4678251fcb3911423940eced94cb937e2559d Mon Sep 17 00:00:00 2001 From: zhouchengrong Date: Wed, 26 Jun 2024 17:52:53 +0800 Subject: [PATCH] =?UTF-8?q?feat=20print=20overall=20=E6=97=8B=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix --- .../design/items/pipelines/painting.py | 115 ++++++++++++++---- app/service/utils/oss_client.py | 2 +- 2 files changed, 91 insertions(+), 26 deletions(-) diff --git a/app/service/design/items/pipelines/painting.py b/app/service/design/items/pipelines/painting.py index 21b567f..49bbf01 100644 --- a/app/service/design/items/pipelines/painting.py +++ b/app/service/design/items/pipelines/painting.py @@ -204,7 +204,14 @@ class PrintPainting(object): result['print_image'] = result['pattern_image'] # print else: - painting_dict = self.painting_collection(painting_dict, result, print_trigger=True) + if result['print']['print_angle_list'][0] != 0: + painting_dict = self.painting_collection(painting_dict, result, print_trigger=True) + painting_dict['tile_print'] = self.rotate_crop_image(img=painting_dict['tile_print'], angle=result['print']['print_angle_list'][0], crop=True) + # resize 到sketch大小 + painting_dict['tile_print'] = self.resize_and_crop(img=painting_dict['tile_print'], target_width=painting_dict['dim_image_w'], target_height=painting_dict['dim_image_h']) + painting_dict['mask_inv_print'] = self.resize_and_crop(img=painting_dict['mask_inv_print'], target_width=painting_dict['dim_image_w'], target_height=painting_dict['dim_image_h']) + else: + painting_dict = self.painting_collection(painting_dict, result, print_trigger=True) result['print_image'] = self.printpaint(result, painting_dict, print_=True) result['final_image'] = result['print_image'] canvas = np.full_like(result['final_image'], 255) @@ -351,8 +358,13 @@ class PrintPainting(object): dim_pattern = (int(dim_max * print_['scale'] / 5), int(dim_max * print_['scale'] / 5)) if not print_['IfSingle']: self.random_seed = random.randint(0, 1000) - painting_dict['mask_inv_print'] = self.tile_image(single_mask_inv_print, dim_pattern, print_['scale'], painting_dict['dim_image_h'], painting_dict['dim_image_w'], painting_dict['location'], trigger=True) - painting_dict['tile_print'] = self.tile_image(print_['image'], dim_pattern, print_['scale'], painting_dict['dim_image_h'], painting_dict['dim_image_w'], painting_dict['location'], trigger=True) + # 如果print 模式为overall 且 有角度的话 , 组合的print为正方形,方便裁剪 + if result['print']['print_angle_list'][0] != 0: + painting_dict['mask_inv_print'] = self.tile_image(single_mask_inv_print, dim_pattern, print_['scale'], dim_max, dim_max, painting_dict['location'], trigger=True) + painting_dict['tile_print'] = self.tile_image(print_['image'], dim_pattern, print_['scale'], dim_max, dim_max, painting_dict['location'], trigger=True) + else: + painting_dict['mask_inv_print'] = self.tile_image(single_mask_inv_print, dim_pattern, print_['scale'], painting_dict['dim_image_h'], painting_dict['dim_image_w'], painting_dict['location'], trigger=True) + painting_dict['tile_print'] = self.tile_image(print_['image'], dim_pattern, print_['scale'], painting_dict['dim_image_h'], painting_dict['dim_image_w'], painting_dict['location'], trigger=True) else: painting_dict['mask_inv_print'] = self.tile_image(single_mask_inv_print, dim_pattern, print_['scale'], painting_dict['dim_image_h'], painting_dict['dim_image_w'], painting_dict['location']) painting_dict['tile_print'] = self.tile_image(print_['image'], dim_pattern, print_['scale'], painting_dict['dim_image_h'], painting_dict['dim_image_w'], painting_dict['location']) @@ -533,6 +545,52 @@ class PrintPainting(object): return rotated_img, ((rotated_img.shape[1] - image.shape[1] * scale) // 2, (rotated_img.shape[0] - image.shape[0] * scale) // 2) # return rotated_img, (0, 0) + @staticmethod + def rotate_crop_image(img, angle, crop): + """ + angle: 旋转的角度 + crop: 是否需要进行裁剪,布尔向量 + """ + crop_image = lambda img, x0, y0, w, h: img[y0:y0 + h, x0:x0 + w] + w, h = img.shape[:2] + # 旋转角度的周期是360° + angle %= 360 + # 计算仿射变换矩阵 + M_rotation = cv2.getRotationMatrix2D((w / 2, h / 2), angle, 1) + # 得到旋转后的图像 + img_rotated = cv2.warpAffine(img, M_rotation, (w, h)) + + # 如果需要去除黑边 + if crop: + # 裁剪角度的等效周期是180° + angle_crop = angle % 180 + if angle > 90: + angle_crop = 180 - angle_crop + # 转化角度为弧度 + theta = angle_crop * np.pi / 180 + # 计算高宽比 + hw_ratio = float(h) / float(w) + # 计算裁剪边长系数的分子项 + tan_theta = np.tan(theta) + numerator = np.cos(theta) + np.sin(theta) * np.tan(theta) + + # 计算分母中和高宽比相关的项 + r = hw_ratio if h > w else 1 / hw_ratio + # 计算分母项 + denominator = r * tan_theta + 1 + # 最终的边长系数 + crop_mult = numerator / denominator + + # 得到裁剪区域 + w_crop = int(crop_mult * w) + h_crop = int(crop_mult * h) + x0 = int((w - w_crop) / 2) + y0 = int((h - h_crop) / 2) + + img_rotated = crop_image(img_rotated, x0, y0, w_crop, h_crop) + + return img_rotated + @staticmethod def read_image(image_url): image = oss_get_image(bucket=image_url.split("/", 1)[0], object_name=image_url.split("/", 1)[1], data_type="cv2") @@ -544,26 +602,33 @@ class PrintPainting(object): image_mode = "RGB" return image, image_mode - # data = minio_client.get_object(image_url.split("/", 1)[0], image_url.split("/", 1)[1]) - # # data = s3.get_object(Bucket=image_url.split("/", 1)[0], Key=image_url.split("/", 1)[1])['Body'] - # - # data_bytes = BytesIO(data.read()) - # image = Image.open(data_bytes) - # image_mode = image.mode - # # 判断图片格式,如果是RGBA 则贴在一张纯白图片上 防止透明转黑 - # if image_mode == "RGBA": - # # new_background = Image.new('RGB', image.size, (255, 255, 255)) - # # new_background.paste(image, mask=image.split()[3]) - # # image = new_background - # return image, image_mode - # image = cv2.cvtColor(np.asarray(image), cv2.COLOR_RGB2BGR) - # return image, "RGB" + @staticmethod + def resize_and_crop(img, target_width, target_height): + # 获取原始图像的尺寸 + original_height, original_width = img.shape[:2] - # @staticmethod - # def read_image(image_url): - # response = requests.get(image_url) - # image_data = np.frombuffer(response.content, np.uint8) - # - # # 解码图像 - # image = cv2.imdecode(image_data, 3) - # return image + # 计算目标尺寸的宽高比 + target_ratio = target_width / target_height + + # 计算原始图像的宽高比 + original_ratio = original_width / original_height + + # 调整尺寸 + if original_ratio > target_ratio: + # 原始图像更宽,按高度resize,然后裁剪宽度 + new_height = target_height + new_width = int(original_width * (target_height / original_height)) + resized_img = cv2.resize(img, (new_width, new_height)) + # 裁剪宽度 + start_x = (new_width - target_width) // 2 + cropped_img = resized_img[:, start_x:start_x + target_width] + else: + # 原始图像更高,按宽度resize,然后裁剪高度 + new_width = target_width + new_height = int(original_height * (target_width / original_width)) + resized_img = cv2.resize(img, (new_width, new_height)) + # 裁剪高度 + start_y = (new_height - target_height) // 2 + cropped_img = resized_img[start_y:start_y + target_height, :] + + return cropped_img diff --git a/app/service/utils/oss_client.py b/app/service/utils/oss_client.py index 6b8a8bd..c2bb82c 100644 --- a/app/service/utils/oss_client.py +++ b/app/service/utils/oss_client.py @@ -63,7 +63,7 @@ if __name__ == '__main__': # url = "aida-users/87/print/956614a2-7e75-4fbe-9ed0-c1831e37a2c9-4-87.png" # url = "aida-users/89/single_logo/123-89.png" # url = "aida-users/89/product_image/string-89.png" - url = 'aida-users/89/relight_image/123-89.png' + url = "aida-results/result_c6520ce7-33a1-11ef-a8d3-b0dcefbff887.png" read_type = "PIL" if read_type == "cv2": img = oss_get_image(bucket=url.split('/')[0], object_name=url[url.find('/') + 1:], data_type=read_type)