remove_bg_ali.py 11 KB

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