remove_bg_ali.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import copy
  2. import json
  3. import os
  4. from PIL import Image
  5. from alibabacloud_imageseg20191230.client import Client as imageseg20191230Client
  6. from alibabacloud_imageseg20191230.models import SegmentCommodityAdvanceRequest
  7. from alibabacloud_imageseg20191230 import models as imageseg_20191230_models
  8. from alibabacloud_tea_util.models import RuntimeOptions
  9. from alibabacloud_tea_openapi import models as open_api_models
  10. from alibabacloud_tea_openapi.models import Config
  11. from alibabacloud_tea_util import models as util_models
  12. import requests
  13. from io import BytesIO
  14. import cv2
  15. import numpy as np
  16. from module.other.module_online_data import GetOnlineData
  17. # todo 获取密钥
  18. # key_id,key_secret = GetOnlineData().get_cutout_image_config()
  19. # 惠利玛的key
  20. AccessKeyId = 'LTAI5tBdDVT9Wc5idJXdGHjw'
  21. AccessKeySecret = 'bCSotQ7eAztOxx6AqHwJJPsb0hkECe'
  22. # https://help.aliyun.com/zh/viapi/developer-reference/python?spm=a2c4g.11186623.0.i0#task-2252575
  23. # pip install alibabacloud_goodstech20191230
  24. # pip install alibabacloud_tea_openapi
  25. # pip install alibabacloud_tea_util
  26. class Segment(object):
  27. def __init__(self):
  28. self.client = self.create_client()
  29. def get_no_bg_common(self, file_path):
  30. # 初始化RuntimeObject
  31. runtime_option = RuntimeOptions()
  32. try:
  33. # 场景一:文件在本地
  34. img = open(file_path, 'rb')
  35. # 使用完成之后记得调用img.close()关闭流
  36. # 场景二,使用任意可访问的url
  37. # url = 'https://viapi-test-bj.oss-cn-beijing.aliyuncs.com/viapi-3.0domepic/ocr/RecognizeBankCard/yhk1.jpg'
  38. # img = io.BytesIO(urlopen(url).read())
  39. # 4、初始化Request,这里只是以RecognizeBankCard为例,其他能力请使用相应能力对应的类
  40. request = SegmentCommodityAdvanceRequest()
  41. request.image_urlobject = img
  42. # 5、调用api,注意,recognize_bank_card_advance需要更换为相应能力对应的方法名。方法名是根据能力名称按照一定规范形成的,如能力名称为SegmentCommonImage,对应方法名应该为segment_common_image_advance。
  43. response = self.client.segment_common_image_advance(request, runtime_option)
  44. # 获取整体结果
  45. # print(response.body)
  46. img.close()
  47. return response.body
  48. # 获取单个字段,这里只是一个例子,具体能力下的字段需要看具体能力的文档
  49. # print(response.body.data.card_number)
  50. # tips: 可通过response.body.__dict__查看属性名称
  51. except Exception as error:
  52. # 获取整体报错信息
  53. print("error", error)
  54. return None
  55. # 获取单个字段
  56. # print(error.code)
  57. # tips: 可通过error.__dict__查看属性名称
  58. def get_no_bg_goods(self, file_path=None, _im=None):
  59. # file_path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\change_color_2\test\_MG_9061.jpg"
  60. # file_path_1 = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\change_color_2\test\_MG_9061_resize.png"
  61. # if file_path:
  62. # img = open(file_path, 'rb')
  63. # if _im:
  64. # https://blog.csdn.net/weixin_43411585/article/details/107780941
  65. im = _im
  66. # im.save(file_path)
  67. img = BytesIO()
  68. im.save(img, format='JPEG') # format: PNG or JPEG
  69. img.seek(0) # rewind to the start
  70. # img = img_byte.getvalue() # im对象转为二进制流
  71. # with open(file_path, "wb") as binary_file:
  72. # binary_file.write(im.tobytes())
  73. # file_path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\change_color_2\test\1.png"
  74. # img = open(file_path, 'rb')
  75. request = imageseg_20191230_models.SegmentCommodityAdvanceRequest()
  76. request.image_urlobject = img
  77. client = self.create_client()
  78. # 5、调用api,注意,recognize_bank_card_advance需要更换为相应能力对应的方法名。方法名是根据能力名称按照一定规范形成的,如能力名称为SegmentCommonImage,对应方法名应该为segment_common_image_advance。
  79. runtime = util_models.RuntimeOptions()
  80. response = client.segment_commodity_advance(request, runtime)
  81. # img.close()
  82. # print("1111111111111", response.body)
  83. return response.body
  84. def create_client(self):
  85. """
  86. 使用AK&SK初始化账号Client
  87. @param access_key_id:
  88. @param access_key_secret:
  89. @return: Client
  90. @throws Exception
  91. """
  92. config = open_api_models.Config(
  93. # 必填,您的 AccessKey ID,
  94. access_key_id=AccessKeyId,
  95. # 必填,您的 AccessKey Secret,
  96. access_key_secret=AccessKeySecret
  97. )
  98. # 访问的域名
  99. config.endpoint = f'imageseg.cn-shanghai.aliyuncs.com'
  100. return imageseg20191230Client(config)
  101. class Picture:
  102. def __init__(self, in_path, im=None):
  103. if im:
  104. self.im = im
  105. else:
  106. self.im = Image.open(in_path)
  107. self.x, self.y = self.im.size
  108. # print(self.x, self.y)
  109. def save_img(self, outpath, quality=90):
  110. # self.im = self.im.convert("RGB")
  111. self.im.save(outpath, quality=quality)
  112. def resize(self, width):
  113. re_x = int(width)
  114. re_y = int(self.y * re_x / self.x)
  115. self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
  116. self.x, self.y = self.im.size
  117. def resize_by_heigh(self, heigh):
  118. re_y = int(heigh)
  119. re_x = int(self.x * re_y / self.y)
  120. self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
  121. self.x, self.y = self.im.size
  122. class RemoveBgALi(object):
  123. def __init__(self):
  124. self.segment = Segment()
  125. def get_image_cut(self, file_path, out_file_path=None, original_im=None):
  126. if original_im:
  127. original_pic = Picture(in_path=None, im=original_im)
  128. else:
  129. original_pic = Picture(file_path)
  130. if original_pic.im.mode != "RGB":
  131. print("抠图图片不能是PNG")
  132. return None
  133. new_pic = copy.copy(original_pic)
  134. after_need_resize = False
  135. if new_pic.x > new_pic.y:
  136. if new_pic.x > 2000:
  137. after_need_resize = True
  138. new_pic.resize(2000)
  139. else:
  140. if new_pic.y > 2000:
  141. after_need_resize = True
  142. new_pic.resize_by_heigh(heigh=2000)
  143. # new_pic.im.show()
  144. body = self.segment.get_no_bg_goods(file_path=None, _im=new_pic.im)
  145. body = eval(str(body))
  146. try:
  147. image_url = body["Data"]["ImageURL"]
  148. except BaseException as e:
  149. print("阿里抠图错误:", e)
  150. # todo 处理失败,需要删除过程图片
  151. return None
  152. # 字节流转PIL对象
  153. response = requests.get(image_url)
  154. pic = response.content
  155. _img_im = Image.open(BytesIO(pic)) # 阿里返回的抠图结果 已转PIL对象
  156. # 原图更大,则需要执行CV处理
  157. if after_need_resize:
  158. # 将抠图结果转成mask
  159. # _img_im = Image.open(_path)
  160. # 将抠图结果放大到原始图大小
  161. _img_im = _img_im.resize(original_pic.im.size)
  162. new_big_mask = Image.new('RGB', _img_im.size, (0, 0, 0))
  163. white = Image.new('RGB', _img_im.size, (255, 255, 255))
  164. new_big_mask.paste(white, mask=_img_im.split()[3])
  165. # ---------制作选区缩小的mask
  166. # mask = cv2.imread(mask_path)
  167. # mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
  168. mask = cv2.cvtColor(np.asarray(new_big_mask), cv2.COLOR_BGR2GRAY) # 将PIL 格式转换为 CV对象
  169. mask[mask != 255] = 0
  170. # 黑白反转
  171. # mask = 255 - mask
  172. # 选区缩小10
  173. kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
  174. erode_im = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
  175. # -------再进行抠图处理
  176. mask = Image.fromarray(cv2.cvtColor(erode_im, cv2.COLOR_GRAY2RGBA)) # CV 对象转 PIL
  177. transparent_im = Image.new('RGBA', original_pic.im.size, (0, 0, 0, 0))
  178. # original_pic.im.show()
  179. # mask.show()
  180. transparent_im.paste(original_pic.im, (0, 0), mask.convert('L'))
  181. # transparent_im.show()
  182. # 上述抠图结果进行拼接
  183. _img_im.paste(transparent_im, (0, 0), transparent_im)
  184. # _img_im.show("11111111111111111111111")
  185. if out_file_path:
  186. _img_im.save(out_file_path)
  187. return _img_im
  188. def get_image_cut1(self, file_path, out_file_path=None):
  189. original_pic = Picture(file_path)
  190. new_pic = copy.copy(original_pic)
  191. if new_pic.x > 2000:
  192. new_pic.resize(2000)
  193. # new_pic.im.show()
  194. body = self.segment.get_no_bg_goods(file_path=out_file_path, _im=new_pic.im)
  195. body = eval(str(body))
  196. try:
  197. image_url = body["Data"]["ImageURL"]
  198. except BaseException as e:
  199. print("阿里抠图错误:", e)
  200. # todo 处理失败,需要删除过程图片
  201. return None
  202. # 字节流转PIL对象
  203. response = requests.get(image_url)
  204. pic = response.content
  205. _img_im = Image.open(BytesIO(pic)) # 阿里返回的抠图结果 已转PIL对象
  206. if original_pic.x > 2000:
  207. # 原图更大,则需要执行CV处理
  208. # _img_im.show()
  209. # 对mask进行放大,然后进行抠图处理
  210. print("对mask进行放大,然后进行抠图处理")
  211. transparent_im = Image.new('RGBA', original_pic.im.size, (0, 0, 0, 0))
  212. # original_pic.im.show()
  213. # mask.show()
  214. _img_im = _img_im.resize((original_pic.x, original_pic.y))
  215. # _img_im.show()
  216. transparent_im.paste(original_pic.im, (0, 0), mask=_img_im)
  217. # transparent_im.show()
  218. # transparent_im.show()
  219. _img_im = transparent_im
  220. # 上述抠图结果进行拼接
  221. # _img_im.paste(transparent_im, (0, 0), transparent_im)
  222. pass
  223. _img_im.save(out_file_path)
  224. return _img_im
  225. def download_picture(self, url, out_path):
  226. response = requests.get(url)
  227. pic = response.content
  228. with open(out_path, 'wb') as f:
  229. f.write(pic)
  230. if __name__ == '__main__':
  231. r = RemoveBgALi()
  232. path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\auto_capture_V2\IPC\test\171112057820408.png"
  233. out_path = "{}._no_bg-out.png".format(path)
  234. r.get_image_cut(path, out_file_path=out_path)