Files

115 lines
4.4 KiB
Python
Raw Permalink Normal View History

import cv2
import numpy as np
from PIL import Image
from minio import Minio
from app.core.config import settings
from app.schemas.mannequin_edit import MannequinModel
from app.service.utils.new_oss_client import oss_get_image, oss_upload_image
minio_client = Minio(settings.MINIO_URL, access_key=settings.MINIO_ACCESS, secret_key=settings.MINIO_SECRET, secure=settings.MINIO_SECURE)
class MannequinEditService:
def __init__(self, request_data):
self.resize_pixel = request_data.resize_pixel
self.top = request_data.top
self.bottom = request_data.bottom
self.image = oss_get_image(oss_client=minio_client, bucket=request_data.mannequins.split('/')[0], object_name=request_data.mannequins[request_data.mannequins.find('/') + 1:], data_type="cv2")
self.mannequin_name = request_data.mannequin_name
self.bucket_name = request_data.bucket_name
if self.image.shape[2] == 4:
self.bgr = self.image[:, :, :3]
self.alpha = self.image[:, :, 3]
self.bgr = cv2.bitwise_and(self.bgr, self.bgr, mask=cv2.normalize(self.alpha, None, 0, 1, cv2.NORM_MINMAX))
self.h, self.w, _ = self.bgr.shape
else:
self.bgr = self.image
self.h, self.w, _ = self.bgr.shape
self.alpha = None
def __call__(self, *args, **kwargs):
new_mannequin = self.resize_leg(self.top, self.bottom)
_, encoded_image = cv2.imencode('.png', new_mannequin)
image_bytes = encoded_image.tobytes()
req = oss_upload_image(oss_client=minio_client, bucket=self.bucket_name, object_name=f"{self.mannequin_name}.png", image_bytes=image_bytes)
return req.bucket_name + "/" + req.object_name
def post_processing(self, image):
# 原始图片的尺寸
original_width, original_height = image.size
# 计算宽度和高度的缩放比例
width_ratio = self.w / original_width
height_ratio = self.h / original_height
# 选择较小的缩放比例,确保图片能完整放入目标图片中
scale_ratio = min(width_ratio, height_ratio)
# 计算调整后的尺寸
new_width = int(original_width * scale_ratio)
new_height = int(original_height * scale_ratio)
# 调整图片大小
resized_image = image.resize((new_width, new_height))
# 创建一个 512x768 的透明图片
result_image = Image.new("RGBA", (self.w, self.h), (255, 255, 255, 0))
# 计算需要粘贴的位置,使图片居中
x_offset = (self.w - new_width) // 2
y_offset = (self.h - new_height) // 2
# 将调整大小后的图片粘贴到透明图片上
if resized_image.mode == "RGBA":
result_image.paste(resized_image, (x_offset, y_offset), mask=resized_image.split()[3])
else:
result_image.paste(resized_image, (x_offset, y_offset))
image = np.array(result_image)
return image
def resize_leg(self, top, bottom):
# 上部
top_part = self.bgr[:top, :]
top_part_alpha = self.alpha[:top, :]
# 需要resize 部分
part_resize = self.bgr[top:bottom, :]
part_resize_alpha = self.alpha[top:bottom, :]
# 下部
part_bottom = self.bgr[bottom:, :]
part_bottom_alpha = self.alpha[bottom:, :]
new_height = int((bottom - top) + self.resize_pixel)
resized_thigh = cv2.resize(part_resize, (self.w, new_height), interpolation=cv2.INTER_LINEAR)
resized_thigh_alpha = cv2.resize(part_resize_alpha, (self.w, new_height), interpolation=cv2.INTER_LINEAR)
# 组合
new_bgr = np.vstack((top_part, resized_thigh, part_bottom))
new_bgr_alpha = np.vstack((top_part_alpha, resized_thigh_alpha, part_bottom_alpha))
if self.alpha is not None:
# 拼接 alpha 通道
# 合并 BGR 通道和 alpha 通道
new_image = np.dstack((new_bgr, new_bgr_alpha))
else:
new_image = new_bgr
new_image = self.post_processing(Image.fromarray(new_image))
return new_image
if __name__ == '__main__':
request_data = MannequinModel(
mannequins="aida-sys-image/models/male/dc36ce58-46c3-4b6f-8787-5ca7d6fc26e6.png",
resize_pixel=-100,
bucket_name="test",
mannequin_name="mannequin_name",
top=270,
bottom=432
)
service = MannequinEditService(request_data)
print(service())