remove_bg_pixian.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import copy
  2. import os
  3. from PIL import Image
  4. from module.other.remove_bg_ali import RemoveBgALi
  5. import requests
  6. from io import BytesIO
  7. class Segment(object):
  8. def __init__(self):
  9. self.k = "pxnib99dbchtmdm"
  10. self.s = "ub9uj5678gs4m2bnrass1t3tn6ughlk065ianosk06akagolcr2u"
  11. def get_no_bg_goods2(self, file_path=None, _im=None):
  12. im = _im
  13. img = BytesIO()
  14. try:
  15. im.save(img, format='JPEG') # format: PNG or JPEG
  16. except:
  17. im.save(img, format='PNG') # format: PNG or JPEG
  18. img.seek(0) # rewind to the start
  19. # img = "https://ossimg.valimart.net/uploads/vali_ai/20241011/172864207036098.png"
  20. response = requests.post(
  21. 'http://47.76.110.118:27777/api/v2/remove-background',
  22. files={'image.url': img},
  23. data={
  24. # TODO: Add more upload options here
  25. },
  26. auth=(self.k, self.s)
  27. )
  28. # print(response.content)
  29. if response.status_code == requests.codes.ok:
  30. return response.content, ""
  31. else:
  32. return None, response.content
  33. def get_no_bg_goods_by_url(self, url):
  34. response = requests.post(
  35. 'https://api.pixian.ai/api/v2/remove-background',
  36. data={
  37. 'image.url': url
  38. },
  39. auth=(self.k, self.s)
  40. )
  41. if response.status_code == requests.codes.ok:
  42. return response.content, ""
  43. else:
  44. print("response.status_code:", response.status_code)
  45. return None, response.content
  46. def get_no_bg_goods(self, file_path=None, _im=None, key=None):
  47. im = _im
  48. img = BytesIO()
  49. try:
  50. im.save(img, format='JPEG') # format: PNG or JPEG
  51. except:
  52. im.save(img, format='PNG') # format: PNG or JPEG
  53. img.seek(0) # rewind to the start
  54. if key:
  55. # todo 切换key
  56. auth = key
  57. # auth = (self.k, self.s)
  58. else:
  59. auth = (self.k, self.s)
  60. try:
  61. response = requests.post(
  62. 'https://api.pixian.ai/api/v2/remove-background',
  63. files={'image': img},
  64. data={
  65. # TODO: Add more upload options here
  66. },
  67. auth=auth,
  68. timeout=40
  69. )
  70. except BaseException as e:
  71. data = {"im": None,
  72. "status_code": "time_out",
  73. "message":"{}".format(e)
  74. }
  75. return data
  76. # print(response.content)
  77. data = {"im": None,
  78. "status_code": response.status_code, }
  79. if response.status_code == requests.codes.ok:
  80. data["im"] = Image.open(BytesIO(response.content))
  81. return data
  82. class Picture:
  83. def __init__(self, in_path, im=None):
  84. if im:
  85. self.im = im
  86. else:
  87. self.im = Image.open(in_path)
  88. self.x, self.y = self.im.size
  89. # print(self.x, self.y)
  90. def save_img(self, outpath, quality=90):
  91. # self.im = self.im.convert("RGB")
  92. self.im.save(outpath, quality=quality)
  93. def resize(self, width):
  94. re_x = int(width)
  95. re_y = int(self.y * re_x / self.x)
  96. self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
  97. self.x, self.y = self.im.size
  98. def resize_by_heigh(self, heigh):
  99. re_y = int(heigh)
  100. re_x = int(self.x * re_y / self.y)
  101. self.im = self.im.resize((re_x, re_y), Image.BICUBIC)
  102. self.x, self.y = self.im.size
  103. class RemoveBgPiXian(object):
  104. def __init__(self):
  105. self.segment = Segment()
  106. self.r = RemoveBgALi()
  107. def direct_matting_image(self, image):
  108. # todo 不能超过32,000,000尺寸的数据
  109. x, y = image.size
  110. f = False
  111. if x * y > 32000000:
  112. r = 32000000 / x * y
  113. image = image.resize(size=(int(x * r), int(y * r)))
  114. f = True
  115. pic, _ = self.segment.get_no_bg_goods(file_path=None, _im=image)
  116. if not pic:
  117. return None, _
  118. _img_im = Image.open(BytesIO(pic)) # 阿里返回的抠图结果 已转PIL对象
  119. if f:
  120. _img_im = _img_im.resize(size=(x, y))
  121. return _img_im, ""
  122. def run_by_image_url(self, url):
  123. pic, _ = self.segment.get_no_bg_goods_by_url(url)
  124. if pic is not None:
  125. _img_im = Image.open(BytesIO(pic))
  126. return _img_im, None
  127. else:
  128. return None, _
  129. def run_by_image_im(self, im, key):
  130. return self.segment.get_no_bg_goods(_im=im, key=key)
  131. def get_image_cut(self, file_path, out_file_path=None, original_im=None, image_preprocessing=False, is_test=False):
  132. if original_im:
  133. original_pic = Picture(in_path=None, im=original_im)
  134. else:
  135. original_pic = Picture(file_path)
  136. if original_pic.im.mode != "RGB":
  137. print("抠图图片不能是PNG")
  138. return False, {"data": "抠图图片不能是PNG"}
  139. if is_test:
  140. cut_image = self.r.get_image_cut(file_path=None, out_file_path=None, original_im=original_pic.im)
  141. if out_file_path:
  142. cut_image.save(out_file_path)
  143. return True, {}
  144. if image_preprocessing:
  145. cut_image = self.r.get_image_cut(file_path=None, out_file_path=None, original_im=original_pic.im)
  146. image_deal_info = {}
  147. x1, y1, x2, y2 = cut_image.getbbox()
  148. image_deal_info["鞋子原始位置"] = (x1, y1, x2, y2)
  149. o_w, o_h = cut_image.size
  150. image_deal_info["鞋子原始抠图后大小"] = (o_w, o_h)
  151. # 扩边处理
  152. _w, _h = x2 - x1, y2 - y1
  153. out_px = 0.06
  154. _w, _h = int(out_px * _w), int(out_px * _h)
  155. n_x1, n_y1, n_x2, n_y2 = x1 - _w, y1 - _h, x2 + _w, y2 + _h
  156. if n_x1 < 0:
  157. n_x1 = 0
  158. if n_y1 < 0:
  159. n_y1 = 0
  160. if n_x2 > o_w:
  161. n_x2 = o_w
  162. if n_y2 > o_h:
  163. n_y2 = o_h
  164. image_deal_info["抠图扩边后位置"] = (n_x1, n_y1, n_x2, n_y2)
  165. cut_image = original_pic.im.crop(image_deal_info["抠图扩边后位置"])
  166. image_deal_info["抠图扩边后图片大小"] = cut_image.size
  167. image_deal_info["原始图片大小"] = (original_pic.x, original_pic.y)
  168. # 使用pixian进行抠图
  169. second_cut_image, _ = self.direct_matting_image(image=cut_image)
  170. if not second_cut_image:
  171. return False, {"data": _}
  172. if second_cut_image.size != image_deal_info["抠图扩边后图片大小"]:
  173. print("图片尺寸还原")
  174. second_cut_image = second_cut_image.resize(image_deal_info["抠图扩边后图片大小"])
  175. # 创建空白图片并粘贴回去
  176. _img_im = Image.new(mode="RGBA", size=image_deal_info["原始图片大小"], color=(0, 0, 0, 0))
  177. _img_im.paste(second_cut_image, box=(image_deal_info["抠图扩边后位置"][0], image_deal_info["抠图扩边后位置"][1]))
  178. else:
  179. _img_im = self.direct_matting_image(image=original_pic.im)
  180. pass
  181. if out_file_path:
  182. _img_im.save(out_file_path)
  183. return True, {}
  184. def download_picture(self, url, out_path):
  185. response = requests.get(url)
  186. pic = response.content
  187. with open(out_path, 'wb') as f:
  188. f.write(pic)
  189. if __name__ == '__main__':
  190. r = RemoveBgPiXian()
  191. path = r"C:\Users\gymmc\Desktop\白底部分品类45度\测试\eva_keai_1.png"
  192. out_path = "{}._no_bg-out.png".format(path)
  193. r.get_image_cut(path, out_file_path=out_path)