remove_bg_ali.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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_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(
  169. np.asarray(new_big_mask), cv2.COLOR_BGR2GRAY
  170. ) # 将PIL 格式转换为 CV对象
  171. mask[mask != 255] = 0
  172. # 黑白反转
  173. # mask = 255 - mask
  174. # 选区缩小10
  175. kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
  176. erode_im = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
  177. # -------再进行抠图处理
  178. mask = Image.fromarray(
  179. cv2.cvtColor(erode_im, cv2.COLOR_GRAY2RGBA)
  180. ) # CV 对象转 PIL
  181. transparent_im = Image.new("RGBA", original_pic.im.size, (0, 0, 0, 0))
  182. # original_pic.im.show()
  183. # mask.show()
  184. transparent_im.paste(original_pic.im, (0, 0), mask.convert("L"))
  185. # transparent_im.show()
  186. # 上述抠图结果进行拼接
  187. _img_im.paste(transparent_im, (0, 0), transparent_im)
  188. # _img_im.show("11111111111111111111111")
  189. if out_file_path:
  190. _img_im.save(out_file_path)
  191. return _img_im
  192. def get_image_cut1(self, file_path, out_file_path=None):
  193. original_pic = Picture(file_path)
  194. new_pic = copy.copy(original_pic)
  195. if new_pic.x > 2000:
  196. new_pic.resize(2000)
  197. # new_pic.im.show()
  198. body = self.segment.get_no_bg_goods(file_path=out_file_path, _im=new_pic.im)
  199. body = eval(str(body))
  200. try:
  201. image_url = body["Data"]["ImageURL"]
  202. except BaseException as e:
  203. print("阿里抠图错误:", e)
  204. # todo 处理失败,需要删除过程图片
  205. return None
  206. # 字节流转PIL对象
  207. response = requests.get(image_url)
  208. pic = response.content
  209. _img_im = Image.open(BytesIO(pic)) # 阿里返回的抠图结果 已转PIL对象
  210. if original_pic.x > 2000:
  211. # 原图更大,则需要执行CV处理
  212. # _img_im.show()
  213. # 对mask进行放大,然后进行抠图处理
  214. print("对mask进行放大,然后进行抠图处理")
  215. transparent_im = Image.new("RGBA", original_pic.im.size, (0, 0, 0, 0))
  216. # original_pic.im.show()
  217. # mask.show()
  218. _img_im = _img_im.resize((original_pic.x, original_pic.y))
  219. # _img_im.show()
  220. transparent_im.paste(original_pic.im, (0, 0), mask=_img_im)
  221. # transparent_im.show()
  222. # transparent_im.show()
  223. _img_im = transparent_im
  224. # 上述抠图结果进行拼接
  225. # _img_im.paste(transparent_im, (0, 0), transparent_im)
  226. pass
  227. _img_im.save(out_file_path)
  228. return _img_im
  229. def download_picture(self, url, out_path):
  230. response = requests.get(url)
  231. pic = response.content
  232. with open(out_path, "wb") as f:
  233. f.write(pic)
  234. if __name__ == "__main__":
  235. r = RemoveBgALi()
  236. path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\auto_capture_V2\IPC\test\171112057820408.png"
  237. out_path = "{}._no_bg-out.png".format(path)
  238. r.get_image_cut(path, out_file_path=out_path)