remove_bg_ali.py 11 KB

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