Ver Fonte

Merge remote-tracking branch 'origin/anheng' into anheng

panqiuyao há 2 dias atrás
pai
commit
07a539bc95

+ 4 - 0
python/api.py

@@ -505,6 +505,8 @@ async def _build_config_data(params, goods_art_no_arrays):
             cutOutMode = "3"
         case "旗舰AI抠图-精细":
             cutOutMode = "4"
+        case "旗舰AI抠图-透明物品":
+            cutOutMode = "5"
         case _:
             cutOutMode = "1"
 
@@ -1836,6 +1838,8 @@ async def remove_background(params: PhotoRecordRemoveBackground):
             cutOutMode = "3"
         case "旗舰AI抠图-精细":
             cutOutMode = "4"
+        case "旗舰AI抠图-透明物品":
+            cutOutMode = "5"
         case _:
             cutOutMode = "1"
     config_data = {

+ 13 - 3
python/service/base_deal.py

@@ -6,7 +6,7 @@ from threading import Lock
 from middleware import UnicornException
 import settings
 from collections import defaultdict
-from .remove_bg_ali import RemoveBgALi, Picture, RemoveUltraBackground
+from .remove_bg_ali import RemoveBgALi, Picture, RemoveUltraBackground, RemoveBgGlasses
 from .deal_cutout import DealCutout
 
 import time
@@ -582,8 +582,12 @@ class BaseDealImage(object):
                 cutout_mode_str = "精细化抠图"
             case "3":
                 cutout_mode_str = "旗舰AI抠图"
-            case "旗舰AI抠图-精细":
-                cutout_mode_str = "4"
+            case "4":
+                cutout_mode_str = "旗舰AI抠图-精细"
+            case "5":
+                cutout_mode_str = "旗舰AI抠图-透明物品"
+            case _:
+                cutout_mode_str = "普通抠图"
         logger.info(f"当前抠图模式:{cutout_mode_str}")
         """
         处理所有的抠图
@@ -675,6 +679,12 @@ class BaseDealImage(object):
                                         file_path=original_image_path,
                                         out_file_path=original_move_bg_image_path,
                                     )
+                                if cutout_mode == "5":
+                                    remove_pic_ins = RemoveBgGlasses()
+                                    im = remove_pic_ins.glasses_segment(
+                                        file_path=original_image_path,
+                                        out_file_path=original_move_bg_image_path,
+                                    )
                             except FunctionTimedOut as f:
                                 callback_func(
                                     "货号图{} 抠图处理超时~".format(file_name)

+ 21 - 0
python/service/grenerate_main_image_test.py

@@ -1036,3 +1036,24 @@ class GeneratePic(object):
         else:
             scale = box_height / height
         return scale
+
+    def filter_2(self, im_shadow, feather=100):
+        # feather 羽化宽度,400 图建议 40~120,越大越柔和
+        background = Image.new(mode="RGB", size=im_shadow.size, color=(255, 255, 255))
+        # 遮罩边缘做羽化处理,设计一个蒙版
+        w, h = im_shadow.size
+        mask = Image.new(mode="L", size=im_shadow.size, color=0)
+        draw = ImageDraw.Draw(mask)
+
+        # x0, y0:矩形左上角坐标
+        # x1, y1:矩形右下角坐标
+        draw.rectangle([feather, feather, w - feather, h - feather], fill=255)
+
+        # 高斯模糊,让边缘从白到黑渐变
+        mask = mask.filter(ImageFilter.GaussianBlur(feather / 2))
+        # if self.is_test:
+        #     mask.show()
+        background.paste(im=im_shadow, mask=mask)
+        im_shadow = background
+
+        return im_shadow

+ 120 - 39
python/service/remove_bg_ali.py

@@ -165,6 +165,37 @@ class Segment(object):
             return None
         return cutout_image
 
+    def get_bo_bg_goods_glasses(self, im, is_shadow=False, api_url=None):
+        imageUrl = uploadImage(im)
+        # imageUrl = imageUrl + "?x-oss-process=image/auto-orient,1"
+        if not settings.USER_TOKEN:
+            print("错误:USER_TOKEN 未配置或为空")
+            return None
+        # print("图片上传成功", imageUrl)
+        post_headers = {"Authorization": "Bearer " + settings.USER_TOKEN}
+        data = {
+            "image_url": imageUrl,
+            "is_shadow": is_shadow
+        }
+        response = requests.post(
+            api_url, json=data, headers=post_headers
+        )
+        # print(f"响应状态码: {response.status_code}")
+        # print(f"响应内容: {response.text[:500]}")  # 只打印前500字符
+
+        resultData = response.json()
+        print("旗舰版抠图请求", resultData)
+        # 安全地获取返回值
+        data = resultData.get("data")
+        if data is None:
+            # print("旗舰版抠图返回的data为空")
+            return None
+        cutout_image = data.get("cutout_image")
+        if cutout_image is None:
+            # print("旗舰版抠图返回的cutout_image为空")
+            return None
+        return cutout_image
+
     def get_platform_shadow(self, original_image, api_url=None):
         image_original_url = uploadImage(original_image)
         if not settings.USER_TOKEN:
@@ -291,6 +322,95 @@ class Picture:
         self.x, self.y = self.im.size
 
 
+class RemoveBgGlasses(object):
+    """
+    玻璃制品抠图
+    """
+
+    def __init__(self):
+        self.api_url = '/api/ai_image/segment_shadow/transparent_segment'
+        self.headers = {
+            'Content-Type': 'application/json',
+            'Accept': 'application/json'
+        }
+        self.saver = ImageSaver()
+        self.segment = Segment()
+        self.logger = logger
+
+    @func_set_timeout(40)
+    def glasses_segment(self, file_path, out_file_path=None):
+        '''
+        玻璃/透明制品抠图
+        '''
+        original_pic = Picture(file_path)
+        original_pic.im = self.segment.get_image_orientation(original_pic.im)
+        original_pic.x, original_pic.y = original_pic.im.size
+        if original_pic.im.mode != "RGB":
+            print("抠图图片不能是PNG")
+            return None
+
+        new_pic = copy.copy(original_pic)
+        basic_width_size = 4000
+        after_need_resize = False
+        if new_pic.x > new_pic.y:
+            if new_pic.x > basic_width_size:
+                after_need_resize = True
+                new_pic.resize(basic_width_size)
+        else:
+            if new_pic.y > basic_width_size:
+                after_need_resize = True
+                new_pic.resize_by_heigh(heigh=basic_width_size)
+        print("使用玻璃制品抠图")
+        try:
+            api_url = f"{settings.DOMAIN}{self.api_url}"
+            image_url = self.segment.get_bo_bg_goods_glasses(im=new_pic.im, api_url=api_url)
+        except BaseException as e:
+            print("玻璃制品抠图异常:", e)
+            # 处理失败,需要删除过程图片
+            return None
+        if image_url is None:
+            return None
+        # 字节流转PIL对象
+        print("image_url", image_url)
+        response = requests.get(image_url)
+        pic = response.content
+        _img_im = Image.open(BytesIO(pic))  # 阿里返回的抠图结果 已转PIL对象
+        # 原图更大,则需要执行CV处理
+        if after_need_resize:
+            # 将抠图结果转成mask
+            # 将抠图结果放大到原始图大小
+            _img_im = _img_im.resize(original_pic.im.size)
+            new_big_mask = Image.new('RGB', _img_im.size, (0, 0, 0))
+            white = Image.new('RGB', _img_im.size, (255, 255, 255))
+            new_big_mask.paste(white, mask=_img_im.split()[3])
+
+            # ---------制作选区缩小的mask
+            mask = cv2.cvtColor(np.asarray(new_big_mask), cv2.COLOR_BGR2GRAY)  # 将PIL 格式转换为 CV对象
+            mask[mask != 255] = 0
+            # 黑白反转
+            # mask = 255 - mask
+            # 选区缩小10
+            kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
+            erode_im = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
+
+            # -------再进行抠图处理
+            mask = Image.fromarray(cv2.cvtColor(erode_im, cv2.COLOR_GRAY2RGBA))  # CV 对象转 PIL
+            transparent_im = Image.new('RGBA', original_pic.im.size, (0, 0, 0, 0))
+            # original_pic.im.show()
+            # mask.show()
+            transparent_im.paste(original_pic.im, (0, 0), mask.convert('L'))
+            # transparent_im.show()
+            # 上述抠图结果进行拼接
+            _img_im.paste(transparent_im, (0, 0), transparent_im)
+        # 原图更大,则需要执行CV处理
+        if out_file_path:
+            self.saver.save_image(
+                image=_img_im, file_path=out_file_path,
+                quality=100, dpi=(350, 350), _format="PNG"
+            )
+        return _img_im
+
+
 class RemoveBgALi(object):
     def __init__(self):
         self.saver = ImageSaver()
@@ -480,15 +600,6 @@ class RemoveUltraBackground:
             return None
 
         new_pic = copy.copy(original_pic)
-        # after_need_resize = False
-        # if new_pic.x > new_pic.y:
-        #     if new_pic.x > 2000:
-        #         after_need_resize = True
-        #         new_pic.resize(2000)
-        # else:
-        #     if new_pic.y > 2000:
-        #         after_need_resize = True
-        #         new_pic.resize_by_heigh(heigh=2000)
         print("使用旗舰版抠图")
         try:
             api_url = f"{settings.DOMAIN}{self.api_url}"
@@ -504,36 +615,6 @@ class RemoveUltraBackground:
         response = requests.get(image_url)
         pic = response.content
         _img_im = Image.open(BytesIO(pic))  # 阿里返回的抠图结果 已转PIL对象
-        # # 原图更大,则需要执行CV处理
-        # if after_need_resize:
-        #     # 将抠图结果转成mask
-        #     # _img_im = Image.open(_path)
-        #     # 将抠图结果放大到原始图大小
-        #     _img_im = _img_im.resize(original_pic.im.size)
-        #     new_big_mask = Image.new('RGB', _img_im.size, (0, 0, 0))
-        #     white = Image.new('RGB', _img_im.size, (255, 255, 255))
-        #     new_big_mask.paste(white, mask=_img_im.split()[3])
-        #
-        #     # ---------制作选区缩小的mask
-        #     # mask = cv2.imread(mask_path)
-        #     # mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
-        #     mask = cv2.cvtColor(np.asarray(new_big_mask), cv2.COLOR_BGR2GRAY)  # 将PIL 格式转换为 CV对象
-        #     mask[mask != 255] = 0
-        #     # 黑白反转
-        #     # mask = 255 - mask
-        #     # 选区缩小10
-        #     kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
-        #     erode_im = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
-        #
-        #     # -------再进行抠图处理
-        #     mask = Image.fromarray(cv2.cvtColor(erode_im, cv2.COLOR_GRAY2RGBA))  # CV 对象转 PIL
-        #     transparent_im = Image.new('RGBA', original_pic.im.size, (0, 0, 0, 0))
-        #     # original_pic.im.show()
-        #     # mask.show()
-        #     transparent_im.paste(original_pic.im, (0, 0), mask.convert('L'))
-        #     # transparent_im.show()
-        #     # 上述抠图结果进行拼接
-        #     _img_im.paste(transparent_im, (0, 0), transparent_im)
         return _img_im
 
     def add_log(self, text, _type="info"):

+ 2 - 0
python/sockets/message_handler.py

@@ -762,6 +762,8 @@ async def handlerSend(
                     cutOutMode = "3"
                 case "旗舰AI抠图-精细":
                     cutOutMode = "4"
+                case "旗舰AI抠图-透明物品":
+                    cutOutMode = "5"
                 case _:
                     cutOutMode = "1"
             config_data = {