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 module.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)