Преглед на файлове

feat(image): 添加旗舰AI抠图精细模式支持

- 新增旗舰AI抠图-精细模式选项,对应cutOutMode为4
- 在主图像生成服务中实现边缘羽化处理功能
- 添加filter_2方法用于边缘过渡羽化处理
- 优化羽化算法,支持可调节羽化宽度参数
- 改进图像混合效果,减少色差问题
- 更新相关配置映射关系以支持新模式
rambo преди 3 седмици
родител
ревизия
54b340e5fe
променени са 3 файла, в които са добавени 46 реда и са изтрити 16 реда
  1. 2 0
      python/api.py
  2. 20 16
      python/mcu/capture/smart_shooter_class.py
  3. 24 0
      python/service/grenerate_main_image_test.py

+ 2 - 0
python/api.py

@@ -1825,6 +1825,8 @@ async def remove_background(params: PhotoRecordRemoveBackground):
             cutOutMode = "2"
         case "旗舰AI抠图":
             cutOutMode = "3"
+        case "旗舰AI抠图-精细":
+            cutOutMode = "4"
         case _:
             cutOutMode = "1"
     config_data = {

+ 20 - 16
python/mcu/capture/smart_shooter_class.py

@@ -13,6 +13,7 @@ import logging
 from databases import SqlQuery, CRUD, SysConfigs
 from utils.common import message_queue
 from models import SysConfigParams
+
 logger = logging.getLogger(__name__)
 
 
@@ -122,7 +123,8 @@ class SmartShooter(metaclass=SingletonType):
             context.term()
             msg_send = "相机未连接或软件未打开"
             return False, msg_send
-    def get_iso_range(self,camera_info):
+
+    def get_iso_range(self, camera_info):
         """
         从相机数据中获取 ISO 的可调范围
         :param camera_data: 相机状态数据列表 (即你提供的那个长列表)
@@ -138,6 +140,7 @@ class SmartShooter(metaclass=SingletonType):
                 return prop.get('CameraPropertyRange')
 
         return None
+
     async def GetCameraInfo(self, is_send=True, msg_type="", CameraKey=None):
         await asyncio.sleep(0.001)
         # self.msg_type = msg_type
@@ -158,13 +161,13 @@ class SmartShooter(metaclass=SingletonType):
             msg_result = json_msg.get("msg_result")
             if not msg_result:
                 self.connect_status = False
-                msg_send =  f"请检查{CameraKey},相机是否连接" if CameraKey else f"请检查相机是否连接"
+                msg_send = f"请检查{CameraKey},相机是否连接" if CameraKey else f"请检查相机是否连接"
                 if is_send:
                     message = {
                         "code": 1,
                         "msg": msg_send,
                         "data": msg_result,
-                        "CameraKey":CameraKey,
+                        "CameraKey": CameraKey,
                         "msg_type": msg_type,
                         "device_status": -1,
                     }
@@ -215,7 +218,7 @@ class SmartShooter(metaclass=SingletonType):
                         "code": 1,
                         "msg": msg_send,
                         "data": msg_result,
-                        "CameraKey":CameraKey,
+                        "CameraKey": CameraKey,
                         "msg_type": msg_type,
                         "device_status": -1,
                     }
@@ -229,7 +232,7 @@ class SmartShooter(metaclass=SingletonType):
                     "code": 0,
                     "msg": msg_send,
                     "data": msg_result,
-                    "CameraLists":CameraLists,
+                    "CameraLists": CameraLists,
                     "msg_type": msg_type,
                     "device_status": 2,
                 }
@@ -243,8 +246,8 @@ class SmartShooter(metaclass=SingletonType):
             self.connect_status = False
             socket.close()
             context.term()
-            print("获取相机信息超时,继续监听...",e)
-            msg_send =  f"请检查{CameraKey},相机是否连接" if CameraKey else f"请检查相机是否连接"
+            print("获取相机信息超时,继续监听...", e)
+            msg_send = f"请检查{CameraKey},相机是否连接" if CameraKey else f"请检查相机是否连接"
             return False, msg_send
         except Exception as e:
             print("相机状态获取异常", e)
@@ -349,7 +352,7 @@ class SmartShooter(metaclass=SingletonType):
         high_iso = Itemiso.get("high", 6400)
         return low_iso, high_iso
 
-    def initConfigIsoSettings(self, CameraLists=[],isMultCameraMode=False):
+    def initConfigIsoSettings(self, CameraLists=[], isMultCameraMode=False):
         if not CameraLists:
             return None
         """获取ISO配置信息"""
@@ -367,7 +370,7 @@ class SmartShooter(metaclass=SingletonType):
                 print("相机无变动。无需自动更改配置")
                 return None
             basic_iso = temp_A_point.get("iso", {"low": 100, "high": 6400})
-            print("isMultCameraMode======>>>>",isMultCameraMode)
+            print("isMultCameraMode======>>>>", isMultCameraMode)
             if not isMultCameraMode:
                 points = {"A": {}}
                 print("相机发生变动。需要更改配置")
@@ -384,10 +387,10 @@ class SmartShooter(metaclass=SingletonType):
                 settings.sync_sys_configs2Online()
             return None
         points = {"A": {}, "B": {}, "C": {}}
-        for idx,item in enumerate(points):
+        for idx, item in enumerate(points):
             low_iso = camera_configs.get("low", 100)
             high_iso = camera_configs.get("high", 6400)
-            if idx > len(CameraLists) -1:
+            if idx > len(CameraLists) - 1:
                 points[item] = {
                     "iso": {"low": low_iso, "high": high_iso},
                 }
@@ -400,8 +403,9 @@ class SmartShooter(metaclass=SingletonType):
         settings.updateSysConfigs(params=sys_iso_config)
         # 同步本地到线上
         settings.sync_sys_configs2Online()
+
     async def EnableCameraPreview(
-        self, enable_status=True, msg_type="", CameraKey=None,isMultCameraMode=False
+            self, enable_status=True, msg_type="", CameraKey=None, isMultCameraMode=False
     ):
         print("收到得msg_type====>>>", msg_type)
         self.msg_type = msg_type
@@ -429,14 +433,14 @@ class SmartShooter(metaclass=SingletonType):
             # 等于auto就不设置
             if enable_status == True:
                 if str(high_iso).lower() != "auto":
-                    set_state,set_msg = await self.setCameraProperty(
+                    set_state, set_msg = await self.setCameraProperty(
                         property="ISO", value=str(high_iso), CameraKey=CameraKey
                     )
                 else:
                     print("high_iso 等于auto就不设置")
             if enable_status == False:
                 if str(low_iso).lower() != "auto":
-                    set_state,set_msg = await self.setCameraProperty(
+                    set_state, set_msg = await self.setCameraProperty(
                         property="ISO", value=str(low_iso), CameraKey=CameraKey
                     )
                 else:
@@ -532,7 +536,7 @@ class SmartShooter(metaclass=SingletonType):
             return False, "相机未连接或软件未打开"
 
     async def CameraShooter(
-        self, msg_type="", goods_art_no="", id=0, is_af=False, delay=0.5, CameraKey=None
+            self, msg_type="", goods_art_no="", id=0, is_af=False, delay=0.5, CameraKey=None
     ):
         # 这里延迟一秒钟 等待前置命令完成
         await asyncio.sleep(delay)
@@ -622,7 +626,7 @@ class SmartShooter(metaclass=SingletonType):
             # await self.sendMessageSocket(message)
             return True, "拍照失败"
         except Exception as e:
-            print("拍照出错",e)
+            print("拍照出错", e)
             socket.close()
             context.term()
             msg_send = "拍照失败"

+ 24 - 0
python/service/grenerate_main_image_test.py

@@ -819,6 +819,8 @@ class GeneratePic(object):
                 backdrop_prepped, source_prepped, opacity=opacity_params / 100
             )
             im_shadow = Image.fromarray(np.uint8(blended_np)).convert("RGB")
+        # 边缘羽化处理
+        im_shadow = self.filter_2(im_shadow=im_shadow, feather=100)
         # 把原图粘贴回去,避免色差
         im_shadow.paste(cut_image, (0, 0), mask=cut_image)
         # _new_im_shadow.show()
@@ -1034,3 +1036,25 @@ 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