Skip to content

Commit

Permalink
Add picsart remove background provider (#1)
Browse files Browse the repository at this point in the history
* add picsart provider

* add picsart in AVAILABLES_FEATURES_AND_PROVIDERS

* export PicsartApi

* handle errors; support bg_image as file

* fixes; add version in info.json

* use the same version as API

* remove useless commented code

---------

Co-authored-by: razvan tudorica <razvan.tudorica@picsart.com>
  • Loading branch information
raztud and razvan tudorica authored Jan 2, 2025
1 parent 9b9c21d commit 39872d6
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 0 deletions.
8 changes: 8 additions & 0 deletions AVAILABLES_FEATURES_AND_PROVIDERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@
| | clipdrop |
| | microsoft |
| | photoroom |
| | picsart |
| | sentisight |
| | stabilityai |
| **generation_fine_tuning** | astria |
Expand Down Expand Up @@ -921,6 +922,13 @@
| **image** | explicit_content |
| | face_detection |

</details>
<details><summary>picsart</summary>

| Features | Subfeatures |
|----------|-------------|
| **image** | background_removal |

</details>
<details><summary>privateai</summary>

Expand Down
4 changes: 4 additions & 0 deletions edenai_apis/api_keys/picsart_settings_template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"api_key": "",
"image_api_base_url": "https://api.picsart.io/tools/1.0"
}
1 change: 1 addition & 0 deletions edenai_apis/apis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,6 @@
from .twelvelabs import TwelveLabsApi
from .clipdrop import ClipdropApi
from .leonardo import LeonardoApi
from .picsart import PicsartApi

# THIS NEEDS TO BE DONE AUTOMATICALLY
1 change: 1 addition & 0 deletions edenai_apis/apis/picsart/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .picsart_api import PicsartApi
7 changes: 7 additions & 0 deletions edenai_apis/apis/picsart/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"image": {
"background_removal": {
"version": "1.0"
}
}
}

Large diffs are not rendered by default.

106 changes: 106 additions & 0 deletions edenai_apis/apis/picsart/picsart_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import base64
import json
from typing import Dict, Optional, Any

import requests
from edenai_apis.features import ProviderInterface, ImageInterface
from edenai_apis.features.image import BackgroundRemovalDataClass
from edenai_apis.loaders.data_loader import ProviderDataEnum
from edenai_apis.loaders.loaders import load_provider
from edenai_apis.utils.exception import ProviderException
from edenai_apis.utils.types import ResponseType


class PicsartApi(ProviderInterface, ImageInterface):
provider_name = 'picsart'

def __init__(self, api_key: Optional[str] = None):
self.api_settings = load_provider(
ProviderDataEnum.KEY, self.provider_name, api_keys=api_key or {}
)
self.base_image_api_url = self.api_settings["image_api_base_url"] # "https://api.picsart.io/tools/1.0"
self.api_key = self.api_settings["api_key"]
self.headers = {
"X-Picsart-API-Key": self.api_settings["api_key"],
"Accept": "application/json",
}


def image__background_removal(
self,
file: Optional[str] = None,
file_url: Optional[str] = None,
provider_params: Optional[Dict[str, Any]] = None,
) -> ResponseType[BackgroundRemovalDataClass]:
"""
Calls the Picsart Remove Background API.
:param file: The file path of the image you want to remove the background from
:param file_url: The file url of the image you want to remove the background from
:param provider_params: Other parameters supported by the Picsart Remove Background API.
"""
url = f"{self.base_image_api_url}/removebg"

if provider_params is None:
provider_params = {}

files = None
image_file = None
if file and not file_url:
image_file = open(file, "rb")
files = {"image": image_file}
elif file_url and not file:
provider_params["image_url"] = file_url
else:
raise ProviderException("No file or file_url provided")

bg_image = provider_params.pop("bg_image", None)
if bg_image:
bg_image = open(bg_image, "rb")
files["bg_image"] = bg_image

try:
response = requests.post(url, files=files, data=provider_params, headers=self.headers)
finally:
if image_file and not image_file.closed:
image_file.close()
if bg_image and not bg_image.closed:
bg_image.close()

self._handle_errors(response=response)

result = response.json()
image_url = result["data"]["url"]
image_response = requests.get(image_url)
image_b64 = base64.b64encode(image_response.content).decode("utf-8")

return ResponseType[BackgroundRemovalDataClass](
original_response=response.text,
standardized_response=BackgroundRemovalDataClass(
image_b64=image_b64,
image_resource_url=image_url,
),
)

@staticmethod
def _handle_errors(response: requests.Response):
"""
Handles the HTTP API Response.
:param response: The HTTP API response.
:raises: ProviderException
"""
if response.status_code == 200:
return

error_message = "Internal Server Error"
error_code = response.status_code
if response.status_code == 400:
try:
response_details = response.json()
error_message = response_details.get("message", "Bad Request")
error_code = response_details.get("code", response.status_code)
except (KeyError, json.JSONDecodeError):
pass

raise ProviderException(error_message, code=error_code)

0 comments on commit 39872d6

Please sign in to comment.