| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- 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_online_data import GetOnlineData
- # todo 获取密钥
- # key_id,key_secret = GetOnlineData().get_cutout_image_config()
- # 惠利玛的key
- AccessKeyId = "LTAI5tBdDVT9Wc5idJXdGHjw"
- AccessKeySecret = "bCSotQ7eAztOxx6AqHwJJPsb0hkECe"
- ALI_MAPPING = {"tops": "上衣", "coat": "外套", "skirt": "裙装", "pants": "裤装"}
- ALI_CLOTH_CLASSES = ["tops", "coat", "skirt", "pants"]
- # 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")
- request = SegmentCommodityAdvanceRequest()
- request.image_urlobject = img
- response = self.client.segment_common_image_advance(request, runtime_option)
- # 获取整体结果
- # print(response.body)
- img.close()
- return response.body
- except Exception as error:
- # 获取整体报错信息
- print("error", error)
- return None
- def get_no_bg_goods(self, file_path=None, _im=None):
- im = _im
- img = BytesIO()
- im.save(img, format="JPEG") # format: PNG or JPEG
- img.seek(0) # rewind to the start
- 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)
- return response.body
- def get_no_bg_cloths(self, _im=None):
- im = _im
- img = BytesIO()
- im.save(img, format="JPEG") # format: PNG or JPEG
- img.seek(0) # rewind to the start
- request = imageseg_20191230_models.SegmentClothAdvanceRequest()
- request.image_urlobject = img
- request.cloth_class = ALI_CLOTH_CLASSES
- client = self.create_client()
- # 5、调用api,注意,recognize_bank_card_advance需要更换为相应能力对应的方法名。方法名是根据能力名称按照一定规范形成的,如能力名称为SegmentCommonImage,对应方法名应该为segment_common_image_advance。
- runtime = util_models.RuntimeOptions()
- response = client.segment_cloth_advance(request, runtime)
- 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).convert("RGB")
- 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_cut_cloths(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)
- try:
- body = self.segment.get_no_bg_cloths(_im=new_pic.im)
- body = eval(str(body))
- clothsArray = []
- Elements = body["Data"]["Elements"]
- for idx, clothItem in enumerate(Elements):
- if idx == 0:
- ImageURL = clothItem.get("ImageURL")
- print("clothItem", clothItem)
- response = requests.get(ImageURL)
- pic = response.content
- _img_im = Image.open(BytesIO(pic))
- clothsArray.append(
- {"type": "all", "cn_name": "合并图", "pilImage": _img_im}
- )
- else:
- ClassUrl = clothItem.get("ClassUrl")
- classKeys = ClassUrl.keys()
- for classKey in classKeys:
- keyUrl = ClassUrl.get(classKey)
- response = requests.get(keyUrl)
- pic = response.content
- mask_image = Image.open(BytesIO(pic))
- if self.isEmptyMask(mask_image.convert("RGB")):
- continue
- if mask_image.mode != "L":
- mask_image = mask_image.convert("L")
- # 使用蒙版图像对原图进行抠图
- result_image = new_pic.im.copy()
- result_image.putalpha(mask_image)
- clothsArray.append(
- {
- "type": classKey,
- "cn_name": ALI_MAPPING[classKey],
- "pilImage": result_image,
- }
- )
- except BaseException as e:
- # todo 处理失败,需要删除过程图片
- return None
- image_arrs = []
- for _, item in enumerate(clothsArray):
- _img_im = item["pilImage"]
- type = item["type"]
- cn_name = item["cn_name"]
- # 原图更大,则需要执行CV处理
- if after_need_resize:
- _img_im = self.clothsDispose(
- _img_im, original_pic=original_pic, out_file_path=out_file_path
- )
- image_arrs.append({"image_obj": _img_im, "type": type, "cn_name": cn_name})
- return image_arrs
- def isEmptyMask(self, img):
- data = np.array(img)
- max_index = np.unravel_index(np.argmax(data, axis=None), data.shape)
- max_value = data[max_index]
- return True if max_value == 0 else False
- def clothsDispose(self, _img_im, original_pic, out_file_path):
- # 将抠图结果转成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")
- 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处理
- # 对mask进行放大,然后进行抠图处理
- print("对mask进行放大,然后进行抠图处理")
- transparent_im = Image.new("RGBA", original_pic.im.size, (0, 0, 0, 0))
- _img_im = _img_im.resize((original_pic.x, original_pic.y))
- transparent_im.paste(original_pic.im, (0, 0), mask=_img_im)
- _img_im = 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)
|