|
@@ -0,0 +1,270 @@
|
|
|
|
|
+import copy
|
|
|
|
|
+import json
|
|
|
|
|
+import os
|
|
|
|
|
+from PIL import Image
|
|
|
|
|
+from alibabacloud_imageseg20191230.client import Client as imageseg20191230Client
|
|
|
|
|
+from alibabacloud_imageseg20191230.models import SegmentCommodityAdvanceRequest
|
|
|
|
|
+from alibabacloud_imageseg20191230 import models as imageseg_20191230_models
|
|
|
|
|
+from alibabacloud_tea_util.models import RuntimeOptions
|
|
|
|
|
+from alibabacloud_tea_openapi import models as open_api_models
|
|
|
|
|
+from alibabacloud_tea_openapi.models import Config
|
|
|
|
|
+from alibabacloud_tea_util import models as util_models
|
|
|
|
|
+import requests
|
|
|
|
|
+from io import BytesIO
|
|
|
|
|
+import cv2
|
|
|
|
|
+import numpy as np
|
|
|
|
|
+from other.module_online_data import GetOnlineData
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# todo 获取密钥
|
|
|
|
|
+# key_id,key_secret = GetOnlineData().get_cutout_image_config()
|
|
|
|
|
+# 惠利玛的key
|
|
|
|
|
+AccessKeyId = "LTAI5tBdDVT9Wc5idJXdGHjw"
|
|
|
|
|
+AccessKeySecret = "bCSotQ7eAztOxx6AqHwJJPsb0hkECe"
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# https://help.aliyun.com/zh/viapi/developer-reference/python?spm=a2c4g.11186623.0.i0#task-2252575
|
|
|
|
|
+# pip install alibabacloud_goodstech20191230
|
|
|
|
|
+# pip install alibabacloud_tea_openapi
|
|
|
|
|
+# pip install alibabacloud_tea_util
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class Segment(object):
|
|
|
|
|
+ def __init__(self):
|
|
|
|
|
+ self.client = self.create_client()
|
|
|
|
|
+
|
|
|
|
|
+ def get_no_bg_common(self, file_path):
|
|
|
|
|
+ # 初始化RuntimeObject
|
|
|
|
|
+ runtime_option = RuntimeOptions()
|
|
|
|
|
+ try:
|
|
|
|
|
+ # 场景一:文件在本地
|
|
|
|
|
+ img = open(file_path, "rb")
|
|
|
|
|
+ # 使用完成之后记得调用img.close()关闭流
|
|
|
|
|
+ # 场景二,使用任意可访问的url
|
|
|
|
|
+ # url = 'https://viapi-test-bj.oss-cn-beijing.aliyuncs.com/viapi-3.0domepic/ocr/RecognizeBankCard/yhk1.jpg'
|
|
|
|
|
+ # img = io.BytesIO(urlopen(url).read())
|
|
|
|
|
+ # 4、初始化Request,这里只是以RecognizeBankCard为例,其他能力请使用相应能力对应的类
|
|
|
|
|
+ request = SegmentCommodityAdvanceRequest()
|
|
|
|
|
+ request.image_urlobject = img
|
|
|
|
|
+
|
|
|
|
|
+ # 5、调用api,注意,recognize_bank_card_advance需要更换为相应能力对应的方法名。方法名是根据能力名称按照一定规范形成的,如能力名称为SegmentCommonImage,对应方法名应该为segment_common_image_advance。
|
|
|
|
|
+ response = self.client.segment_common_image_advance(request, runtime_option)
|
|
|
|
|
+ # 获取整体结果
|
|
|
|
|
+ # print(response.body)
|
|
|
|
|
+ img.close()
|
|
|
|
|
+ return response.body
|
|
|
|
|
+ # 获取单个字段,这里只是一个例子,具体能力下的字段需要看具体能力的文档
|
|
|
|
|
+ # print(response.body.data.card_number)
|
|
|
|
|
+ # tips: 可通过response.body.__dict__查看属性名称
|
|
|
|
|
+ except Exception as error:
|
|
|
|
|
+ # 获取整体报错信息
|
|
|
|
|
+ print("error", error)
|
|
|
|
|
+ return None
|
|
|
|
|
+ # 获取单个字段
|
|
|
|
|
+ # print(error.code)
|
|
|
|
|
+ # tips: 可通过error.__dict__查看属性名称
|
|
|
|
|
+
|
|
|
|
|
+ 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"
|
|
|
|
|
+ # if file_path:
|
|
|
|
|
+ # img = open(file_path, 'rb')
|
|
|
|
|
+ # if _im:
|
|
|
|
|
+ # https://blog.csdn.net/weixin_43411585/article/details/107780941
|
|
|
|
|
+ im = _im
|
|
|
|
|
+ # im.save(file_path)
|
|
|
|
|
+ img = BytesIO()
|
|
|
|
|
+ im.save(img, format="JPEG") # format: PNG or JPEG
|
|
|
|
|
+ img.seek(0) # rewind to the start
|
|
|
|
|
+
|
|
|
|
|
+ # img = img_byte.getvalue() # im对象转为二进制流
|
|
|
|
|
+ # with open(file_path, "wb") as binary_file:
|
|
|
|
|
+ # binary_file.write(im.tobytes())
|
|
|
|
|
+
|
|
|
|
|
+ # file_path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\change_color_2\test\1.png"
|
|
|
|
|
+ # img = open(file_path, 'rb')
|
|
|
|
|
+
|
|
|
|
|
+ request = imageseg_20191230_models.SegmentCommodityAdvanceRequest()
|
|
|
|
|
+ request.image_urlobject = img
|
|
|
|
|
+ client = self.create_client()
|
|
|
|
|
+ # 5、调用api,注意,recognize_bank_card_advance需要更换为相应能力对应的方法名。方法名是根据能力名称按照一定规范形成的,如能力名称为SegmentCommonImage,对应方法名应该为segment_common_image_advance。
|
|
|
|
|
+ runtime = util_models.RuntimeOptions()
|
|
|
|
|
+ response = client.segment_commodity_advance(request, runtime)
|
|
|
|
|
+ # img.close()
|
|
|
|
|
+ # print("1111111111111", response.body)
|
|
|
|
|
+ return response.body
|
|
|
|
|
+
|
|
|
|
|
+ def create_client(self):
|
|
|
|
|
+ """
|
|
|
|
|
+ 使用AK&SK初始化账号Client
|
|
|
|
|
+ @param access_key_id:
|
|
|
|
|
+ @param access_key_secret:
|
|
|
|
|
+ @return: Client
|
|
|
|
|
+ @throws Exception
|
|
|
|
|
+ """
|
|
|
|
|
+ config = open_api_models.Config(
|
|
|
|
|
+ # 必填,您的 AccessKey ID,
|
|
|
|
|
+ access_key_id=AccessKeyId,
|
|
|
|
|
+ # 必填,您的 AccessKey Secret,
|
|
|
|
|
+ access_key_secret=AccessKeySecret,
|
|
|
|
|
+ )
|
|
|
|
|
+ # 访问的域名
|
|
|
|
|
+ config.endpoint = f"imageseg.cn-shanghai.aliyuncs.com"
|
|
|
|
|
+ return imageseg20191230Client(config)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class Picture:
|
|
|
|
|
+ def __init__(self, in_path, im=None):
|
|
|
|
|
+ if im:
|
|
|
|
|
+ self.im = im
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.im = Image.open(in_path)
|
|
|
|
|
+ self.x, self.y = self.im.size
|
|
|
|
|
+ # print(self.x, self.y)
|
|
|
|
|
+
|
|
|
|
|
+ def save_img(self, outpath, quality=90):
|
|
|
|
|
+ # self.im = self.im.convert("RGB")
|
|
|
|
|
+ self.im.save(outpath, quality=quality)
|
|
|
|
|
+
|
|
|
|
|
+ def resize(self, width):
|
|
|
|
|
+ re_x = int(width)
|
|
|
|
|
+ re_y = int(self.y * re_x / self.x)
|
|
|
|
|
+ self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
|
|
|
|
|
+ self.x, self.y = self.im.size
|
|
|
|
|
+
|
|
|
|
|
+ def resize_by_heigh(self, heigh):
|
|
|
|
|
+ re_y = int(heigh)
|
|
|
|
|
+ re_x = int(self.x * re_y / self.y)
|
|
|
|
|
+ self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
|
|
|
|
|
+ self.x, self.y = self.im.size
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class RemoveBgALi(object):
|
|
|
|
|
+ def __init__(self):
|
|
|
|
|
+ self.segment = Segment()
|
|
|
|
|
+
|
|
|
|
|
+ def get_image_cut(self, file_path, out_file_path=None, original_im=None):
|
|
|
|
|
+ if original_im:
|
|
|
|
|
+ original_pic = Picture(in_path=None, im=original_im)
|
|
|
|
|
+ else:
|
|
|
|
|
+ original_pic = Picture(file_path)
|
|
|
|
|
+
|
|
|
|
|
+ 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)
|
|
|
|
|
+
|
|
|
|
|
+ # new_pic.im.show()
|
|
|
|
|
+ body = self.segment.get_no_bg_goods(file_path=None, _im=new_pic.im)
|
|
|
|
|
+ body = eval(str(body))
|
|
|
|
|
+ try:
|
|
|
|
|
+ image_url = body["Data"]["ImageURL"]
|
|
|
|
|
+ except BaseException as e:
|
|
|
|
|
+ print("阿里抠图错误:", e)
|
|
|
|
|
+ # todo 处理失败,需要删除过程图片
|
|
|
|
|
+ return None
|
|
|
|
|
+ # 字节流转PIL对象
|
|
|
|
|
+ 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)
|
|
|
|
|
+ # _img_im.show("11111111111111111111111")
|
|
|
|
|
+ if out_file_path:
|
|
|
|
|
+ _img_im.save(out_file_path)
|
|
|
|
|
+ return _img_im
|
|
|
|
|
+
|
|
|
|
|
+ def get_image_cut1(self, file_path, out_file_path=None):
|
|
|
|
|
+ original_pic = Picture(file_path)
|
|
|
|
|
+ new_pic = copy.copy(original_pic)
|
|
|
|
|
+ if new_pic.x > 2000:
|
|
|
|
|
+ new_pic.resize(2000)
|
|
|
|
|
+ # new_pic.im.show()
|
|
|
|
|
+ body = self.segment.get_no_bg_goods(file_path=out_file_path, _im=new_pic.im)
|
|
|
|
|
+ body = eval(str(body))
|
|
|
|
|
+ try:
|
|
|
|
|
+ image_url = body["Data"]["ImageURL"]
|
|
|
|
|
+ except BaseException as e:
|
|
|
|
|
+ print("阿里抠图错误:", e)
|
|
|
|
|
+ # todo 处理失败,需要删除过程图片
|
|
|
|
|
+ return None
|
|
|
|
|
+ # 字节流转PIL对象
|
|
|
|
|
+ response = requests.get(image_url)
|
|
|
|
|
+ pic = response.content
|
|
|
|
|
+ _img_im = Image.open(BytesIO(pic)) # 阿里返回的抠图结果 已转PIL对象
|
|
|
|
|
+
|
|
|
|
|
+ if original_pic.x > 2000:
|
|
|
|
|
+ # 原图更大,则需要执行CV处理
|
|
|
|
|
+ # _img_im.show()
|
|
|
|
|
+ # 对mask进行放大,然后进行抠图处理
|
|
|
|
|
+ print("对mask进行放大,然后进行抠图处理")
|
|
|
|
|
+ transparent_im = Image.new("RGBA", original_pic.im.size, (0, 0, 0, 0))
|
|
|
|
|
+ # original_pic.im.show()
|
|
|
|
|
+ # mask.show()
|
|
|
|
|
+ _img_im = _img_im.resize((original_pic.x, original_pic.y))
|
|
|
|
|
+ # _img_im.show()
|
|
|
|
|
+ transparent_im.paste(original_pic.im, (0, 0), mask=_img_im)
|
|
|
|
|
+ # transparent_im.show()
|
|
|
|
|
+ # transparent_im.show()
|
|
|
|
|
+ _img_im = transparent_im
|
|
|
|
|
+ # 上述抠图结果进行拼接
|
|
|
|
|
+ # _img_im.paste(transparent_im, (0, 0), transparent_im)
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ _img_im.save(out_file_path)
|
|
|
|
|
+ return _img_im
|
|
|
|
|
+
|
|
|
|
|
+ def download_picture(self, url, out_path):
|
|
|
|
|
+ response = requests.get(url)
|
|
|
|
|
+ pic = response.content
|
|
|
|
|
+ with open(out_path, "wb") as f:
|
|
|
|
|
+ f.write(pic)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if __name__ == "__main__":
|
|
|
|
|
+ r = RemoveBgALi()
|
|
|
|
|
+ path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\auto_capture_V2\IPC\test\171112057820408.png"
|
|
|
|
|
+ out_path = "{}._no_bg-out.png".format(path)
|
|
|
|
|
+ r.get_image_cut(path, out_file_path=out_path)
|