remove_bg_pixian.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. import copy
  2. import os
  3. from PIL import Image
  4. from .remove_bg_ali import RemoveBgALi
  5. import requests
  6. from io import BytesIO
  7. import settings
  8. class Segment(object):
  9. def __init__(self):
  10. self.k = "pxnib99dbchtmdm"
  11. self.s = "ub9uj5678gs4m2bnrass1t3tn6ughlk065ianosk06akagolcr2u"
  12. def get_no_bg_goods2(self, file_path=None, _im=None):
  13. im = _im
  14. img = BytesIO()
  15. try:
  16. im.save(img, format='JPEG') # format: PNG or JPEG
  17. except:
  18. im.save(img, format='PNG') # format: PNG or JPEG
  19. img.seek(0) # rewind to the start
  20. # img = "https://ossimg.valimart.net/uploads/vali_ai/20241011/172864207036098.png"
  21. response = requests.post(
  22. 'http://47.76.110.118:27777/api/v2/remove-background',
  23. files={'image.url': img},
  24. data={
  25. # Add more upload options here
  26. },
  27. auth=(self.k, self.s)
  28. )
  29. # print(response.content)
  30. if response.status_code == requests.codes.ok:
  31. return response.content, ""
  32. else:
  33. return None, response.content
  34. def get_no_bg_goods_by_url(self, url,key):
  35. if key:
  36. # 切换key
  37. auth = key
  38. # auth = (self.k, self.s)
  39. else:
  40. auth = (self.k, self.s)
  41. response = requests.post(
  42. 'https://3api.valimart.net/api/v2/remove-background',
  43. data={
  44. 'image.url': url
  45. },
  46. auth=auth,
  47. timeout=300
  48. )
  49. data = {"im": None,
  50. "status_code": response.status_code, }
  51. try:
  52. if response.status_code == requests.codes.ok:
  53. data["im"] = Image.open(BytesIO(response.content))
  54. return data
  55. else:
  56. print("response.status_code:", response.status_code)
  57. data = {"im": None,
  58. "status_code": "time_out",
  59. "message":"处理失败;{}".format(response.status_code)
  60. }
  61. return data
  62. except BaseException as e:
  63. data = {"im": None,
  64. "status_code": "time_out",
  65. "message":"{}".format(e)
  66. }
  67. return data
  68. def get_no_bg_goods(self, file_path=None, _im=None, key=None):
  69. im = _im
  70. img = BytesIO()
  71. try:
  72. im.save(img, format='JPEG') # format: PNG or JPEG
  73. except:
  74. im.save(img, format='PNG') # format: PNG or JPEG
  75. img.seek(0) # rewind to the start
  76. if key:
  77. # 切换key
  78. auth = key
  79. # auth = (self.k, self.s)
  80. else:
  81. auth = (self.k, self.s)
  82. try:
  83. response = requests.post(
  84. 'https://3api.valimart.net/api/v2/remove-background',
  85. files={'image': img},
  86. data={
  87. # Add more upload options here
  88. },
  89. auth=auth,
  90. timeout=40
  91. )
  92. except BaseException as e:
  93. data = {"im": None,
  94. "status_code": "time_out",
  95. "message":"{}".format(e)
  96. }
  97. return data
  98. # print(response.content)
  99. data = {"im": None,
  100. "status_code": response.status_code, }
  101. if response.status_code == requests.codes.ok:
  102. data["im"] = Image.open(BytesIO(response.content))
  103. return data
  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 RemoveBgPiXian(object):
  126. def __init__(self):
  127. self.segment = Segment()
  128. self.r = RemoveBgALi()
  129. def direct_matting_image(self, image):
  130. #不能超过32,000,000尺寸的数据
  131. x, y = image.size
  132. f = False
  133. if x * y > 32000000:
  134. r = 32000000 / x * y
  135. image = image.resize(size=(int(x * r), int(y * r)))
  136. f = True
  137. pic, _ = self.segment.get_no_bg_goods(file_path=None, _im=image)
  138. if not pic:
  139. return None, _
  140. _img_im = Image.open(BytesIO(pic)) # 阿里返回的抠图结果 已转PIL对象
  141. if f:
  142. _img_im = _img_im.resize(size=(x, y))
  143. return _img_im, ""
  144. def run_by_image_url(self, url):
  145. pic, _ = self.segment.get_no_bg_goods_by_url(url)
  146. if pic is not None:
  147. _img_im = Image.open(BytesIO(pic))
  148. return _img_im, None
  149. else:
  150. return None, _
  151. def upload_image_by_io(self, image_pil:Image) -> str:
  152. # post_headers = {"Authorization": settings.Authorization}
  153. im = image_pil
  154. img = BytesIO()
  155. try:
  156. im.save(img, format='JPEG') # format: PNG or JPEG
  157. except:
  158. im.save(img, format='PNG') # format: PNG or JPEG
  159. img.seek(0) # rewind to the start
  160. try:
  161. url = settings.DOMAIN + "/api/upload"
  162. resultData = requests.post(
  163. url, files={"file": img},
  164. timeout=100
  165. ).json()
  166. return resultData["data"]["url"]
  167. except Exception as e:
  168. print("upload_image_by_io error:", e)
  169. return None
  170. def run_by_image_im(self, im, key):
  171. image_url = self.upload_image_by_io(im)
  172. if image_url is None:
  173. data = {"im": None,
  174. "status_code": "time_out",
  175. "message":"图片上传失败"
  176. }
  177. return data
  178. # image_url
  179. # 把image_url中的ossimg.valimart.net
  180. # 替换为img-cuts.valimart.net
  181. print("image_url 1:", image_url)
  182. image_url = image_url.replace('ossimg.valimart.net', 'img-cuts.valimart.net')
  183. print("image_url 2:", image_url)
  184. return self.segment.get_no_bg_goods_by_url(url=image_url,key=key)
  185. def get_image_cut(self, file_path, out_file_path=None, original_im=None, image_preprocessing=False, is_test=False):
  186. if original_im:
  187. original_pic = Picture(in_path=None, im=original_im)
  188. else:
  189. original_pic = Picture(file_path)
  190. if original_pic.im.mode != "RGB":
  191. print("抠图图片不能是PNG")
  192. return False, {"data": "抠图图片不能是PNG"}
  193. if is_test:
  194. cut_image = self.r.get_image_cut(file_path=None, out_file_path=None, original_im=original_pic.im)
  195. if out_file_path:
  196. cut_image.save(out_file_path)
  197. return True, {}
  198. if image_preprocessing:
  199. cut_image = self.r.get_image_cut(file_path=None, out_file_path=None, original_im=original_pic.im)
  200. image_deal_info = {}
  201. x1, y1, x2, y2 = cut_image.getbbox()
  202. image_deal_info["鞋子原始位置"] = (x1, y1, x2, y2)
  203. o_w, o_h = cut_image.size
  204. image_deal_info["鞋子原始抠图后大小"] = (o_w, o_h)
  205. # 扩边处理
  206. _w, _h = x2 - x1, y2 - y1
  207. out_px = 0.06
  208. _w, _h = int(out_px * _w), int(out_px * _h)
  209. n_x1, n_y1, n_x2, n_y2 = x1 - _w, y1 - _h, x2 + _w, y2 + _h
  210. if n_x1 < 0:
  211. n_x1 = 0
  212. if n_y1 < 0:
  213. n_y1 = 0
  214. if n_x2 > o_w:
  215. n_x2 = o_w
  216. if n_y2 > o_h:
  217. n_y2 = o_h
  218. image_deal_info["抠图扩边后位置"] = (n_x1, n_y1, n_x2, n_y2)
  219. cut_image = original_pic.im.crop(image_deal_info["抠图扩边后位置"])
  220. image_deal_info["抠图扩边后图片大小"] = cut_image.size
  221. image_deal_info["原始图片大小"] = (original_pic.x, original_pic.y)
  222. # 使用pixian进行抠图
  223. second_cut_image, _ = self.direct_matting_image(image=cut_image)
  224. if not second_cut_image:
  225. return False, {"data": _}
  226. if second_cut_image.size != image_deal_info["抠图扩边后图片大小"]:
  227. print("图片尺寸还原")
  228. second_cut_image = second_cut_image.resize(image_deal_info["抠图扩边后图片大小"])
  229. # 创建空白图片并粘贴回去
  230. _img_im = Image.new(mode="RGBA", size=image_deal_info["原始图片大小"], color=(0, 0, 0, 0))
  231. _img_im.paste(second_cut_image, box=(image_deal_info["抠图扩边后位置"][0], image_deal_info["抠图扩边后位置"][1]))
  232. else:
  233. _img_im = self.direct_matting_image(image=original_pic.im)
  234. pass
  235. if out_file_path:
  236. _img_im.save(out_file_path)
  237. return True, {}
  238. def download_picture(self, url, out_path):
  239. response = requests.get(url)
  240. pic = response.content
  241. with open(out_path, 'wb') as f:
  242. f.write(pic)
  243. if __name__ == '__main__':
  244. r = RemoveBgPiXian()
  245. path = r"C:\Users\gymmc\Desktop\白底部分品类45度\测试\eva_keai_1.png"
  246. out_path = "{}._no_bg-out.png".format(path)
  247. r.get_image_cut(path, out_file_path=out_path)