瀏覽代碼

style(api): 优化代码格式和增强抠图功能

- 统一代码中的空格和逗号格式
- 在多个函数间添加适当的空行提高可读性
- 重构抠图模式配置支持多种类型(普通、精细化、旗舰AI)
- 优化异步处理逻辑提高性能
- 改进错误处理和进度跟踪机制
- 修复多处字符串拼接和变量引用问题
rambo 1 周之前
父節點
當前提交
3744fd633e
共有 6 個文件被更改,包括 667 次插入455 次删除
  1. 319 279
      python/api.py
  2. 1 1
      python/config.ini
  3. 153 151
      python/service/base_deal.py
  4. 175 3
      python/service/remove_bg_ali.py
  5. 11 6
      python/sockets/message_handler.py
  6. 8 15
      python/temp.py

文件差異過大導致無法顯示
+ 319 - 279
python/api.py


+ 1 - 1
python/config.ini

@@ -10,7 +10,7 @@ app_run = api:app
 # 端口号
 port = 7074
 debug = false
-env = prod
+env = dev
 # 线程数
 works = 1
 project = 惠利玛

+ 153 - 151
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
+from .remove_bg_ali import RemoveBgALi, Picture, RemoveUltraBackground
 from .deal_cutout import DealCutout
 
 import time
@@ -24,7 +24,9 @@ import copy, asyncio
 from settings import sendSocketMessage
 from utils.common import message_queue
 from logger import logger
-def sendAsyncMessage(msg="", goods_arts=[], status="",progress={}):
+
+
+def sendAsyncMessage(msg="", goods_arts=[], status="", progress={}):
     """异步发送消息"""
     data = {
         "code": 0,
@@ -34,15 +36,15 @@ def sendAsyncMessage(msg="", goods_arts=[], status="",progress={}):
             "status": status,
             "goods_art_nos": goods_arts,
         },
-        "progress":{
-                "msg_type":"segment_progress",
-                "name":"抠图",
-                "goods_art_no":progress.get("goods_art_no",""),
-                "status":progress.get("status"),
-                "current":progress.get("current",0),
-                "total":progress.get("total",0),
-                "error":progress.get("error",0)
-            },
+        "progress": {
+            "msg_type": "segment_progress",
+            "name": "抠图",
+            "goods_art_no": progress.get("goods_art_no", ""),
+            "status": progress.get("status"),
+            "current": progress.get("current", 0),
+            "total": progress.get("total", 0),
+            "error": progress.get("error", 0)
+        },
         "msg_type": "segment_progress",
     }
     message_queue.put_nowait(data)
@@ -65,14 +67,14 @@ class BaseDealImage(object):
         pass
 
     def run_main(
-        self,
-        all_goods_art_no_folder_data,
-        callback_func=None,
-        cutout_mode=None,
-        resize_image_view=None,
-        windows=None,
-        logo_path=None,
-        image_order_list=None,
+            self,
+            all_goods_art_no_folder_data,
+            callback_func=None,
+            cutout_mode=None,
+            resize_image_view=None,
+            windows=None,
+            logo_path=None,
+            image_order_list=None,
     ):
         """
         执行主流程处理
@@ -87,7 +89,7 @@ class BaseDealImage(object):
             }
         """
         from logger import logger
-        
+
         # 对所有缺失已抠图的进行抠图处理
         self.run_cutout_image(
             all_goods_art_no_folder_data=all_goods_art_no_folder_data,
@@ -99,7 +101,7 @@ class BaseDealImage(object):
         successful_num = 0
         successful_folders = []
         failed_folders = []
-        
+
         for goods_art_no_folder_data in all_goods_art_no_folder_data:
             if goods_art_no_folder_data["label"] != "待处理":
                 continue
@@ -108,7 +110,7 @@ class BaseDealImage(object):
                     break
             folder_name = goods_art_no_folder_data["folder_name"]
             callback_func("开始处理文件夹==========  {} ".format(folder_name))
-            
+
             flag = None
             if settings.IS_TEST:
                 flag = self.shoes_run_one_folder_to_deal(
@@ -139,7 +141,7 @@ class BaseDealImage(object):
                     )
                     failed_folders.append(goods_art_no_folder_data)
                     continue
-            
+
             # 判断处理结果
             if flag is None:
                 callback_func("货号:{} 数据异常".format(folder_name))
@@ -154,9 +156,9 @@ class BaseDealImage(object):
                     error_num += 1
                     callback_func("货号:{} 图片生成处理失败".format(folder_name))
                     failed_folders.append(goods_art_no_folder_data)
-        
+
         callback_func("处理成功:{}个,失败:{}个".format(successful_num, error_num))
-        
+
         # 返回详细的处理结果
         result = {
             'success': error_num == 0,
@@ -165,15 +167,15 @@ class BaseDealImage(object):
             'successful_num': successful_num,
             'error_num': error_num
         }
-        
+
         logger.info(f"[主流程完成] 成功: {successful_num}, 失败: {error_num}")
         if failed_folders:
             logger.warning(f"[主流程完成] 失败货号列表: {[f['folder_name'] for f in failed_folders]}")
-        
+
         return result
 
     def checkImageAmount(
-        self, image_dir: str, amount: int, todo_goods_art_no_folder_name_list=None
+            self, image_dir: str, amount: int, todo_goods_art_no_folder_name_list=None
     ) -> dict:
         result = {"code": 0, "msg": "", "data": {}}
         for goods_art_no_folder in self.list_dir(image_dir):
@@ -189,7 +191,7 @@ class BaseDealImage(object):
             if "无法" in goods_art_no_folder:
                 continue
             if "原始图" not in self.list_dir(
-                "{}/{}".format(image_dir, goods_art_no_folder)
+                    "{}/{}".format(image_dir, goods_art_no_folder)
             ):
                 result["data"][goods_art_no_folder] = "文件夹下,没有 原始图 文件夹\n"
                 continue
@@ -218,7 +220,7 @@ class BaseDealImage(object):
         return result
 
     def check_folders_image_amount(
-        self, all_goods_art_no_folder_data, image_order_list
+            self, all_goods_art_no_folder_data, image_order_list
     ):
         print("*****************check_folders_image_amount************************")
         amount = len(image_order_list)
@@ -268,7 +270,7 @@ class BaseDealImage(object):
         imageOrderList = (
             image_order.replace(",", ",").replace(" ", "").replace("图", "").split(",")
         )
-        print("imageOrderList",imageOrderList)
+        print("imageOrderList", imageOrderList)
         if len(set(imageOrderList)) != len(imageOrderList):
             return {"code": 1, "msg": "图片位置与顺序重复,请检查您的输入"}
 
@@ -307,7 +309,7 @@ class BaseDealImage(object):
                 "组合26",
             ]
             if val not in image_orders:
-                print("val",val)
+                print("val", val)
                 image_orders_str = ','.join(map(str, image_orders))
                 return {
                     "code": 1,
@@ -320,13 +322,13 @@ class BaseDealImage(object):
         return {"code": 0, "msg": "sucess", "imageOrderList": imageOrderList}
 
     def shoes_run_one_folder_to_deal(
-        self,
-        goods_art_no_folder_data,
-        image_order_list: list,
-        resize_image_view: str,
-        logo_path="",
-        windows=None,
-        callback_func=None,
+            self,
+            goods_art_no_folder_data,
+            image_order_list: list,
+            resize_image_view: str,
+            logo_path="",
+            windows=None,
+            callback_func=None,
     ):
         """
         操作步骤:
@@ -396,11 +398,11 @@ class BaseDealImage(object):
 
         # 删除目录再新建
         try:
-          if os.path.exists("{}/阴影图处理".format(folder_path)):
-            shutil.rmtree("{}/阴影图处理".format(folder_path),onerror=settings.handle_remove_readonly)
+            if os.path.exists("{}/阴影图处理".format(folder_path)):
+                shutil.rmtree("{}/阴影图处理".format(folder_path), onerror=settings.handle_remove_readonly)
         except Exception as e:
-          print('An exception occurred')
-          logger.info(f"base deal 抠图前目录删除出现问题:{str(e)}")
+            print('An exception occurred')
+            logger.info(f"base deal 抠图前目录删除出现问题:{str(e)}")
 
         self.crate_all_folders(folder_path)
         print(
@@ -439,7 +441,7 @@ class BaseDealImage(object):
                     is_image_deal_mode = 0
                     print("开始识别左右脚=========>")
                     if OnePicDeal(self.token).check_shoe_is_right(
-                        image_path=original_move_bg_image_path
+                            image_path=original_move_bg_image_path
                     ):
                         is_image_deal_mode = 1  # 1表示要镜像,0表示不做镜像
             print(
@@ -479,14 +481,14 @@ class BaseDealImage(object):
                 resize_mode = 2
 
             if (
-                settings.getSysConfigs("other_configs", "product_type", "鞋类")
-                == "皮具"
+                    settings.getSysConfigs("other_configs", "product_type", "鞋类")
+                    == "皮具"
             ):
                 max_box = (1000, 1200)
             out_pic_size = (
                 [1600]
                 if settings.getSysConfigs("basic_configs", "main_image_size", [1600])
-                == ""
+                   == ""
                 else settings.getSysConfigs("basic_configs", "main_image_size", [1600])
             )  # 主图大小
             if resize_mode == 2:
@@ -502,19 +504,19 @@ class BaseDealImage(object):
             curve_mask = True if "俯视" in image_order_list else False
             try:
                 if not generate_pic.run(
-                    image_path=original_image_path,
-                    cut_image_path=original_move_bg_image_path,
-                    out_path=out_path,
-                    image_deal_mode=is_image_deal_mode,
-                    # resize_mode=resize_mode,
-                    resize_mode=1,#将这里得缩放模式改为强制不缩放 2025-10-22
-                    out_pic_size=out_pic_size,
-                    is_logo=True if i_n == 1 else False,
-                    out_process_path_1=out_process_path_1,
-                    out_process_path_2=out_process_path_2,
-                    max_box=max_box,
-                    logo_path=logo_path,
-                    curve_mask=curve_mask,
+                        image_path=original_image_path,
+                        cut_image_path=original_move_bg_image_path,
+                        out_path=out_path,
+                        image_deal_mode=is_image_deal_mode,
+                        # resize_mode=resize_mode,
+                        resize_mode=1,  # 将这里得缩放模式改为强制不缩放 2025-10-22
+                        out_pic_size=out_pic_size,
+                        is_logo=True if i_n == 1 else False,
+                        out_process_path_1=out_process_path_1,
+                        out_process_path_2=out_process_path_2,
+                        max_box=max_box,
+                        logo_path=logo_path,
+                        curve_mask=curve_mask,
                 ):
                     print("**********222222222222222222222222222********************")
                     is_successful = False
@@ -575,12 +577,21 @@ class BaseDealImage(object):
             self.check_path(path)
 
     def run_cutout_image(
-        self,
-        all_goods_art_no_folder_data,
-        callback_func=None,
-        cutout_mode=1,
-        windows=None,
+            self,
+            all_goods_art_no_folder_data,
+            callback_func=None,
+            cutout_mode=1,
+            windows=None,
     ):
+        cutout_mode_str = "普通抠图"
+        match cutout_mode:
+            case "1":
+                cutout_mode_str = "普通抠图"
+            case "2":
+                cutout_mode_str = "精细化抠图"
+            case "3":
+                cutout_mode_str = "旗舰AI抠图"
+        logger.info(f"当前抠图模式:{cutout_mode_str}")
         """
         处理所有的抠图
         """
@@ -592,12 +603,12 @@ class BaseDealImage(object):
         total_progress = len(all_goods_art_no_folder_data)
         finish_progress = 0
         error_progress = 0
-        progress = {"status":"正在处理",
-                "current":finish_progress,
-                "total":total_progress,
-                "error":error_progress}
+        progress = {"status": "正在处理",
+                    "current": finish_progress,
+                    "total": total_progress,
+                    "error": error_progress}
         sendAsyncMessage(
-            msg="开始处理抠图", goods_arts=goods_art_nos, status="开始处理",progress=progress
+            msg="开始处理抠图", goods_arts=goods_art_nos, status="开始处理", progress=progress
         )
         error_goods_art_no_folder = []
         for goods_art_no_folder_data in all_goods_art_no_folder_data:
@@ -609,12 +620,12 @@ class BaseDealImage(object):
             images = [x for x in self.list_dir("{}/原始图".format(folder_path))]
             cutImageList = []
             goods_art_floder_name = goods_art_no_folder_data["folder_name"]
-            progress = {"status":"正在处理",
-                "current":finish_progress,
-                "total":total_progress,
-                "error":error_progress,
-                "goods_art_no":goods_art_floder_name
-                }
+            progress = {"status": "正在处理",
+                        "current": finish_progress,
+                        "total": total_progress,
+                        "error": error_progress,
+                        "goods_art_no": goods_art_floder_name
+                        }
             sendAsyncMessage(
                 msg="正在抠图",
                 goods_arts=[goods_art_floder_name],
@@ -637,6 +648,7 @@ class BaseDealImage(object):
                     if not os.path.exists(original_move_bg_image_path):
                         # 没有抠图文件,进行抠图生成
                         callback_func("正在抠图 货号:{}".format(file_name))
+                        print("cutout_mode=============>", cutout_mode)
                         if cutout_mode == "2":
                             cutImageList.append(
                                 {
@@ -651,33 +663,29 @@ class BaseDealImage(object):
                                 }
                             )
                         else:
-                            remove_pic_ins = RemoveBgALi()
-                            if settings.IS_TEST:
+                            if cutout_mode == "1":
+                                remove_pic_ins = RemoveBgALi()
+                            if cutout_mode == "3":
+                                remove_pic_ins = RemoveUltraBackground()
+                            try:
                                 im = remove_pic_ins.get_image_cut(
                                     file_path=original_image_path,
                                     out_file_path=original_move_bg_image_path,
                                 )
-                            else:
-                                try:
-                                    im = remove_pic_ins.get_image_cut(
-                                        file_path=original_image_path,
-                                        out_file_path=original_move_bg_image_path,
-                                    )
-                                except FunctionTimedOut as f:
-                                    callback_func(
-                                        "货号图{} 抠图处理超时~".format(file_name)
-                                    )
-                                    error_goods_art_no_folder.append(folder_path)
-                                    im = None
-                                except BaseException as e:
-                                    callback_func(
-                                        "货号图{} 抠图处理失败,原因{}".format(
-                                            file_name, e
-                                        )
+                            except FunctionTimedOut as f:
+                                callback_func(
+                                    "货号图{} 抠图处理超时~".format(file_name)
+                                )
+                                error_goods_art_no_folder.append(folder_path)
+                                im = None
+                            except BaseException as e:
+                                callback_func(
+                                    "货号图{} 抠图处理失败,原因{}".format(
+                                        file_name, e
                                     )
-                                    error_goods_art_no_folder.append(folder_path)
-                                    im = None
-
+                                )
+                                error_goods_art_no_folder.append(folder_path)
+                                im = None
                             if not im:
                                 callback_func(
                                     "货号图{} 抠图处理失败~".format(file_name)
@@ -687,14 +695,14 @@ class BaseDealImage(object):
                             else:
                                 callback_func("货号图{} 抠图完成~".format(file_name))
             progress = {
-                "status":"正在处理",
-                "current":finish_progress,
-                "total":total_progress,
-                "error":error_progress,
-                "goods_art_no":goods_art_floder_name
-                }
+                "status": "正在处理",
+                "current": finish_progress,
+                "total": total_progress,
+                "error": error_progress,
+                "goods_art_no": goods_art_floder_name
+            }
             if goods_art_floder_name not in error_goods_art_no_folder:
-                finish_progress+=1
+                finish_progress += 1
                 sendAsyncMessage(
                     msg="正在处理",
                     goods_arts=[goods_art_floder_name],
@@ -721,11 +729,11 @@ class BaseDealImage(object):
                         break
         error_progress = len(error_goods_art_no_folder)
         progress = {
-                "status":"处理完成",
-                "current":finish_progress,
-                "total":total_progress,
-                "error":error_progress
-                }
+            "status": "处理完成",
+            "current": finish_progress,
+            "total": total_progress,
+            "error": error_progress
+        }
         if error_goods_art_no_folder:
             print("以下货号抠图失败~\n {}".format(error_goods_art_no_folder))
             callback_func("以下货号抠图失败~\n {}".format(error_goods_art_no_folder))
@@ -738,12 +746,6 @@ class BaseDealImage(object):
         else:
             pass
         progress["status"] = "处理失败" if error_progress == total_progress else "处理完成"
-        # sendAsyncMessage(
-        #             msg="抠图完成",
-        #             goods_arts=[],
-        #             status="抠图完成",
-        #             progress=progress
-        #         )
 
     def checkCutoutImage(self, image_dir: str, todo_goods_art_no_folder_name_list=None):
         """
@@ -765,7 +767,7 @@ class BaseDealImage(object):
             if "无法" in goods_art_no_folder:
                 continue
             if "原始图" not in self.list_dir(
-                "{}/{}".format(image_dir, goods_art_no_folder)
+                    "{}/{}".format(image_dir, goods_art_no_folder)
             ):
                 error_goods_art_no_folder.append(goods_art_no_folder)
                 continue
@@ -869,15 +871,15 @@ class BaseDealImage(object):
                             print("550 文件夹重名命失败:{}".format(e))
 
     def cutImagePiju(
-        self,
-        image_dir: str,
-        image_order="",
-        is_check_number=True,
-        is_filter=True,
-        resize_image_view="后跟",
-        callback_func=None,
-        event=None,
-        todo_goods_art_no_folder_name_list=None,
+            self,
+            image_dir: str,
+            image_order="",
+            is_check_number=True,
+            is_filter=True,
+            resize_image_view="后跟",
+            callback_func=None,
+            event=None,
+            todo_goods_art_no_folder_name_list=None,
     ):
         """
         1、遍历文件夹,基于生成的结果图看哪些需要进行抠图等处理
@@ -997,13 +999,13 @@ class BaseDealImage(object):
         return {"code": 0, "msg": "ok"}
 
     def run_one_folder_to_deal(
-        self,
-        goods_art_no_folder,
-        image_dir,
-        image_order,
-        resize_image_view,
-        callback_func=None,
-        logo_path="",
+            self,
+            goods_art_no_folder,
+            image_dir,
+            image_order,
+            resize_image_view,
+            callback_func=None,
+            logo_path="",
     ):
 
         _img_all = self.list_dir("{}/{}/原始图".format(image_dir, goods_art_no_folder))
@@ -1030,7 +1032,7 @@ class BaseDealImage(object):
                 all_original_images.append(new_file_name)
 
         if os.path.exists(
-            "{}/{}/原始图/镜像.txt".format(image_dir, goods_art_no_folder)
+                "{}/{}/原始图/镜像.txt".format(image_dir, goods_art_no_folder)
         ):
             file_mirror_mark = True
         else:
@@ -1112,7 +1114,7 @@ class BaseDealImage(object):
                         goods_class = "鞋"
                         # 如果图片已存在,则需要通过加载图片判断是否为左右脚
                         if OnePicDeal().check_shoe_is_right(
-                            image_path=original_move_bg_image_path
+                                image_path=original_move_bg_image_path
                         ):
                             image_deal_mode = 1  # 1表示要镜像,0表示不做镜像
                             is_image_deal_mode = 1
@@ -1191,24 +1193,24 @@ class BaseDealImage(object):
                     if settings.getSysConfigs(
                         "basic_configs", "main_image_size", [1600]
                     )
-                    == ""
+                       == ""
                     else settings.getSysConfigs(
                         "basic_configs", "main_image_size", [1600]
                     )
                 )  # 主图大小
                 if generate_pic.run(
-                    image_path=original_image_path,
-                    cut_image_path=original_move_bg_image_path,
-                    out_path=out_path,
-                    image_deal_mode=is_image_deal_mode,
-                    image_index=image_index,
-                    out_pic_size=out_pic_size,
-                    is_logo=True if i_n == 1 else False,
-                    out_process_path_1=out_process_path_1,
-                    out_process_path_2=out_process_path_2,
-                    max_box=max_box,
-                    logo_path=logo_path,
-                    curve_mask=curve_mask,
+                        image_path=original_image_path,
+                        cut_image_path=original_move_bg_image_path,
+                        out_path=out_path,
+                        image_deal_mode=is_image_deal_mode,
+                        image_index=image_index,
+                        out_pic_size=out_pic_size,
+                        is_logo=True if i_n == 1 else False,
+                        out_process_path_1=out_process_path_1,
+                        out_process_path_2=out_process_path_2,
+                        max_box=max_box,
+                        logo_path=logo_path,
+                        curve_mask=curve_mask,
                 ):
                     # self.show_progress_detail("货号图{} _{} 已完成800*800图片制作~".format(image_index, file_name))
                     callback_func(
@@ -1248,7 +1250,7 @@ class BaseDealImage(object):
             return None
 
     def get_goods_art_no_info(
-        self, numbers_list=None, goods_art_list=None, headers=None
+            self, numbers_list=None, goods_art_list=None, headers=None
     ):
         # 获取商品基础信息,入参为商品的编号
         url = "{domain}/api/backend/goods_client/goods_query".format(
@@ -1301,7 +1303,7 @@ class BaseDealImage(object):
         return goods_art_no_dict
 
     def get_goods_art_no_info(
-        self, numbers_list=None, goods_art_list=None, headers=None
+            self, numbers_list=None, goods_art_list=None, headers=None
     ):
         # 获取商品基础信息,入参为商品的编号
         url = "{domain}/api/backend/goods_client/goods_query".format(
@@ -1572,7 +1574,7 @@ class BaseDealImage(object):
         shutil.move(old_image_path, original_image_path)
 
     def pixianRemoveImageBg(
-        self, file_path: str, out_file_path: str, callbackek_func=None
+            self, file_path: str, out_file_path: str, callbackek_func=None
     ):
         url = self.dataModeMatchPhoto.get_online_data.uploadImage(local_path=file_path)
 

+ 175 - 3
python/service/remove_bg_ali.py

@@ -16,11 +16,35 @@ import numpy as np
 from func_timeout import func_set_timeout
 from func_timeout import FunctionTimedOut
 from .multi_threaded_image_saving import ImageSaver
+import settings
 
 # 自己的
 AccessKeyId = "LTAI5tCk4p881X8hymj2FYFk"
 AccessKeySecret = "yBYIYzX8CL24r5ZgEx2AgZyDBmFkIK"
 
+
+def uploadImage(im: Image) -> str:
+    img_byte_io = BytesIO()
+    # 根据图片模式选择保存格式
+    if im.mode == 'RGBA':
+        im.save(img_byte_io, format='PNG')
+    else:
+        im.save(img_byte_io, format='JPEG')
+    img_byte_io.seek(0)  # 重置指针到开头
+
+    post_headers = {"Authorization": settings.USER_TOKEN}
+    url = settings.DOMAIN + "/api/upload"
+
+    # 使用字节流上传
+    resultData = requests.post(
+        url,
+        files={"file": ("image.jpg", img_byte_io, "image/jpeg")},
+        headers=post_headers
+    ).json()
+
+    return resultData["data"]["url"]
+
+
 # 惠利玛公司的KEY
 # AccessKeyId = 'LTAI5tCk4p881X8hymj2FYFk'
 # AccessKeySecret = 'rQMgHwciTN4Gusbpt8CM8tflgsxh1V'
@@ -66,6 +90,71 @@ class Segment(object):
             # print(error.code)
             # tips: 可通过error.__dict__查看属性名称
 
+    def get_image_orientation(self, img):
+        # 获取EXIF数据
+        exif = img._getexif()
+        if exif is not None:
+            # EXIF标签274对应的是Orientation
+            orientation = exif.get(0x0112)
+            print("orientation", orientation)
+            if orientation == 2:
+                # 水平翻转
+                img = img.transpose(Image.FLIP_LEFT_RIGHT)
+            elif orientation == 3:
+                # 旋转180度
+                img = img.rotate(180, expand=True)
+            elif orientation == 4:
+                # 垂直翻转
+                img = img.transpose(Image.FLIP_TOP_BOTTOM)
+            elif orientation == 5:
+                # 水平翻转后顺时针旋转90度
+                img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_270)
+            elif orientation == 6:
+                # 顺时针旋转90度
+                img = img.transpose(Image.ROTATE_270)
+            elif orientation == 7:
+                # 水平翻转后逆时针旋转90度
+                img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
+            elif orientation == 8:
+                # 逆时针旋转90度
+                img = img.transpose(Image.ROTATE_90)
+        else:
+            print("没有EXIF数据或没有方向信息")
+            orientation = 1
+
+        return img
+
+    def get_bo_bg_goods_ultra_background(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_no_bg_goods(self, file_path=None, _im=None):
         # file_path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\change_color_2\test\_MG_9061.jpg"
         # file_path_1 = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\change_color_2\test\_MG_9061_resize.png"
@@ -145,6 +234,7 @@ class RemoveBgALi(object):
     def __init__(self):
         self.saver = ImageSaver()
         self.segment = Segment()
+
     @func_set_timeout(40)
     def get_image_cut_new(self, file_path, out_file_path=None, original_im=None):
         if original_im:
@@ -185,6 +275,7 @@ class RemoveBgALi(object):
         new_pp4_im.save(byte_io, format='PNG')  # 将图像保存为 PNG 格式到 BytesIO 对象
         byte_io.seek(0)  # 将指针重置到流的开头,以便后续读取
         return byte_io
+
     @func_set_timeout(40)
     def get_image_cut(self, file_path, out_file_path=None, original_im=None):
         if original_im:
@@ -254,7 +345,7 @@ class RemoveBgALi(object):
         if out_file_path:
             self.saver.save_image(
                 image=_img_im, file_path=out_file_path,
-                quality=100,dpi=(350, 350), _format="PNG"
+                quality=100, dpi=(350, 350), _format="PNG"
             )
             # _img_im.save(out_file_path)
         return _img_im
@@ -306,8 +397,89 @@ class RemoveBgALi(object):
             f.write(pic)
 
 
+class RemoveUltraBackground:
+    def __init__(self):
+        self.api_url = '/api/ai_image/segment_shadow/segment_service'
+        self.headers = {
+            'Content-Type': 'application/json',
+            'Accept': 'application/json'
+        }
+        self.saver = ImageSaver()
+        self.segment = Segment()
+
+    @func_set_timeout(40)
+    def get_image_cut(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)
+        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}"
+            image_url = self.segment.get_bo_bg_goods_ultra_background(im=new_pic.im, api_url=api_url)
+        except BaseException as e:
+            print("旗舰版抠图异常:", e)
+            # 处理失败,需要删除过程图片
+            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 = 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)
+        # 原图更大,则需要执行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
+
+
 if __name__ == '__main__':
-    r = RemoveBgALi()
-    path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\auto_capture_V2\IPC\test\171112057820408.png"
+    r = RemoveUltraBackground()
+    path = r"C:\Users\15001\Desktop\miniso\hb\原始图\hb(1).JPG"
     out_path = "{}._no_bg-out.png".format(path)
     r.get_image_cut(path, out_file_path=out_path)

+ 11 - 6
python/sockets/message_handler.py

@@ -682,6 +682,7 @@ async def handlerSend(
             msg_type = "segment_progress"
             obj = None
             token = data.get("token", "")
+            settings.USER_TOKEN = token
             token = "Bearer " + token
             uuid = data.get("uuid", "")
             run_main = RunMain(obj, token, uuid)
@@ -746,12 +747,16 @@ async def handlerSend(
                         return
             session.close()
             # try:
-            cutOutMode = (
-                "1"
-                if settings.getSysConfigs("other_configs", "cutout_mode", "普通抠图")
-                   == "普通抠图"
-                else "2"
-            )
+            cutout_mode = settings.getSysConfigs("other_configs", "cutout_mode", "普通抠图")
+            match cutout_mode:
+                case "普通抠图":
+                    cutOutMode = "1"
+                case "精细化抠图":
+                    cutOutMode = "2"
+                case "旗舰AI抠图":
+                    cutOutMode = "3"
+                case _:
+                    cutOutMode = "1"
             config_data = {
                 "image_dir": limit_path,
                 "image_order": (

+ 8 - 15
python/temp.py

@@ -1,4 +1,4 @@
-import zmq,json
+import zmq, json
 # def __send_tcp_message(socket, msg):
 #     socket.send_string(json.dumps(msg, ensure_ascii=False))
 #     rep = socket.recv()
@@ -24,18 +24,11 @@ import zmq,json
 # json_msg = __send_tcp_message(req_socket,req)
 # cameraInfo = json_msg.get("CameraInfo")
 # print("cameraInfo",json_msg)
-import zmq, json
-import asyncio, settings
-
-# # ... existing code ...
-from mcu.capture.smart_shooter_class import SmartShooter
-
-
-async def main():
-    sm = SmartShooter(None)
-    await sm.GetCameraInfo()
-
-
-if __name__ == "__main__":
-    asyncio.run(main())
+from service.remove_bg_ali import RemoveUltraBackground
+import settings
 
+settings.USER_TOKEN = "c2f44c4c1171b84d13ee21f770fd32e773b910f2"
+r = RemoveUltraBackground()
+path = r"C:\Users\15001\Desktop\miniso\hb\原始图\hb(1).JPG"
+out_path = "{}._no_bg-out.png".format(path)
+r.get_image_cut(path, out_file_path=out_path)

部分文件因文件數量過多而無法顯示