Compare commits

...
Author SHA1 Message Date
Your Name fe10d6990e fix image preprocess 2025-03-10 17:27:35 +04:00
Your Name d5b7d2550c fix import 2025-03-10 15:40:25 +04:00
Xenia 80db13454c Merge remote-tracking branch 'origin/main' into comfy_tailored_portrait 2025-03-10 08:53:57 +00:00
Xenia ae89bb1aa0 tailored portrait 2025-03-10 08:52:49 +00:00
xenia-kra 07827ef34f tailored portrait (#18) 2025-03-10 12:45:44 +04:00
Xenia da131c5a49 tailored portrait 2025-03-10 08:26:15 +00:00
MishaFein 00dccbb17a Update Readme.md 2025-02-10 18:11:40 +02:00
MishaFein 1cb9ce4394 Update Readme.md 2025-02-10 18:10:57 +02:00
MishaFein b2f8b8d0e3 Update Readme.md 2025-02-10 18:05:56 +02:00
MishaFein 129bc599d0 Update Readme.md 2025-02-10 18:04:28 +02:00
MishaFein 28c2631581 Update Readme.md 2025-02-10 17:57:11 +02:00
ori-liberman baadbc02bc Add content moderation option to background removal and image generation nodes 2025-02-10 12:49:02 +00:00
or a73045f8e6 Added workflow sample to readme 2025-02-09 14:21:38 +02:00
tairBria dd74d03fd0 Merge pull request #17 from Bria-AI/t2i-tailored-content-moderation
content moderation t2i reimagime tailored
2025-02-09 13:12:30 +02:00
or bfc83da41f added text-to-image workflow and updated version 2025-02-04 17:40:08 +02:00
BriaOr 499ec5d104 Update Readme.md 2025-02-04 13:44:48 +02:00
BriaOr fef2e49902 Update Readme.md with new API URL 2025-02-04 13:39:36 +02:00
BriaOr 2eae6dae46 Merge pull request #16 from Bria-AI/feature/content-moderation-expansion-removefg
image expansion & remove fg- content moderation
2025-02-03 16:10:11 +02:00
israelweiss90 28c0cdf8d5 image expansion & remove fg- content moderation 2025-02-02 16:14:02 +00:00
15 changed files with 298 additions and 22 deletions
+15 -6
View File
@@ -4,14 +4,22 @@
<img src="./images/Bria Logo.svg" alt="BRIA Logo" width="200"/>
</p>
This repository provides custom nodes for ComfyUI, enabling direct access to **BRIA's API endpoints** for image generation workflows. **API documentation** is available [**here**](https://bria-ai-api-docs.redoc.ly/#operation//generation/bria-v2/text-to-image).
This repository provides custom nodes for ComfyUI, enabling direct access to **BRIA's API endpoints** for image generation and editing workflows. **API documentation** is available [**here**](https://docs.bria.ai/).
BRIA's APIs and models are built for commercial use and trained on 100% licensed data and does not contain copyrighted materials, such as fictional characters, logos, trademarks, public figures, harmful content, or privacy-infringing content.
An API token is required to use the nodes in your workflows. Get started quickly here
<a href="https://bria.ai/api/" style="text-decoration:none; vertical-align:middle;">
<img src="https://img.shields.io/badge/GET%20YOUR%20TOKEN-1000%20Free%20Calls-blue?style=flat-square" alt="Get Your Token" height="20">
</a>.
For direct API Endpoint use, look for the endpoint in our of our API partners like: [**fal.ai**](https://fal.ai/models?keywords=bria).
For source code and weigths access, go to our [**Hugging Face**](https://huggingface.co/briaai) space.
To load a workflow, import the compatible workflow.json files from this [folder](workflows).
<p align="center">
<img src="./images/background_workflow.png" width="1200"/>
</p>
<!-- Placeholder image of cool workflows. -->
@@ -22,16 +30,17 @@ To load a workflow, import the compatible workflow.json files from this [folder]
# Available Nodes
## Image Generation Nodes
These nodes create high-quality images from text or image prompts, generating photorealistic or artistic results with support for various aspect ratios. [[API docs](https://bria-ai-api-docs.redoc.ly/tag/Image-Generation)].
These nodes create high-quality images from text or image prompts, generating photorealistic or artistic results with support for various aspect ratios.
| Node | Description |
|------------------------|--------------------------------------------------------------------|
| **Text2Image Base** | Generates images from text prompts, serving as the foundation for text-based image creation. |
| **Text2Image Fast** | Optimized for speed, this node generates images from text prompts with faster results while maintaining quality. |
| **Text2Image HD** | Optimized for high-resolution outputs, this node generates detailed and sharp visuals from text prompts. |
| **Reimagine** | Guides image generation using both prompts and an input image. Preserve the original structure and depth while introducing new materials, colors, and textures. |
## Tailored Generation Nodes
These nodes use pre-trained tailored models to generate images that faithfully reproduce specific visual IP elements or guidelines. [[API docs](https://bria-ai-api-docs.redoc.ly/tag/Tailored-Generation)].
These nodes use pre-trained tailored models to generate images that faithfully reproduce specific visual IP elements or guidelines.
| Node | Description |
|------------------------|--------------------------------------------------------------------|
@@ -39,7 +48,7 @@ These nodes use pre-trained tailored models to generate images that faithfully r
| **Tailored Model Info** | Retrieves the default settings and prompt prefix of a trained tailored model, which can be used to configure the Tailored Gen node. |
## Image Editing Nodes
These nodes modify specific parts of images, enabling adjustments while maintaining the integrity of the rest of the image. [[API docs](https://bria-ai-api-docs.redoc.ly/tag/Image-Editing)].
These nodes modify specific parts of images, enabling adjustments while maintaining the integrity of the rest of the image.
| Node | Description |
|------------------------|--------------------------------------------------------------------|
@@ -50,8 +59,8 @@ These nodes modify specific parts of images, enabling adjustments while maintain
| **GenFill** | Generates objects by prompt in a specific region of an image. |
| **Erase Foreground** | Removes the foreground from an image, isolating the background. |
## Product Shot Generation Nodes
These nodes create high-quality product images for eCommerce workflows. [[API docs](https://bria-ai-api-docs.redoc.ly/tag/Product-Shots-Generation)].
## Product Shot Editing Nodes
These nodes create high-quality product images for eCommerce workflows.
| Node | Description |
|------------------------|--------------------------------------------------------------------|
+2 -1
View File
@@ -1,5 +1,5 @@
from .nodes import (EraserNode, GenFillNode, ImageExpansionNode, ReplaceBgNode, RmbgNode, RemoveForegroundNode, ShotByTextNode, ShotByImageNode, TailoredGenNode,
TailoredModelInfoNode, Text2ImageBaseNode, Text2ImageFastNode, Text2ImageHDNode,
TailoredModelInfoNode, Text2ImageBaseNode, Text2ImageFastNode, Text2ImageHDNode, TailoredPortraitNode,
ReimagineNode)
# Map the node class to a name used internally by ComfyUI
NODE_CLASS_MAPPINGS = {
@@ -13,6 +13,7 @@ NODE_CLASS_MAPPINGS = {
"ShotByImageNode": ShotByImageNode,
"BriaTailoredGen": TailoredGenNode,
"TailoredModelInfoNode": TailoredModelInfoNode,
"TailoredPortraitNode": TailoredPortraitNode,
"Text2ImageBaseNode": Text2ImageBaseNode,
"Text2ImageFastNode": Text2ImageFastNode,
"Text2ImageHDNode": Text2ImageHDNode,
Binary file not shown.

After

Width:  |  Height:  |  Size: 634 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 714 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

+1
View File
@@ -8,6 +8,7 @@ from .shot_by_text_node import ShotByTextNode
from .shot_by_image_node import ShotByImageNode
from .tailored_gen_node import TailoredGenNode
from .tailored_model_info_node import TailoredModelInfoNode
from .tailored_portrait_node import TailoredPortraitNode
from .text_2_image_base_node import Text2ImageBaseNode
from .text_2_image_fast_node import Text2ImageFastNode
from .text_2_image_hd_node import Text2ImageHDNode
+4 -2
View File
@@ -23,6 +23,7 @@ class ImageExpansionNode():
"prompt": ("STRING", {"default": ""}),
"seed": ("INT", {"default": 681794}),
"negative_prompt": ("STRING", {"default": "Ugly, mutated"}),
"content_moderation": ("BOOLEAN", {"default": False}),
}
}
@@ -42,6 +43,7 @@ class ImageExpansionNode():
prompt,
seed,
negative_prompt,
content_moderation,
api_key):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
@@ -70,8 +72,8 @@ class ImageExpansionNode():
"canvas_size": canvas_size,
"prompt": prompt,
"negative_prompt": negative_prompt,
"seed": seed
# "sync": True
"seed": seed,
"content_moderation": content_moderation
}
headers = {
+5 -2
View File
@@ -15,6 +15,9 @@ class RemoveForegroundNode():
"image": ("IMAGE",), # Input image from another node
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}), # API Key input with a default value
},
"optional": {
"content_moderation": ("BOOLEAN", {"default": False}),
}
}
RETURN_TYPES = ("IMAGE",)
@@ -26,7 +29,7 @@ class RemoveForegroundNode():
self.api_url = "https://engine.internal.prod.bria-api.com/v1/erase_foreground" # remove foreground API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, api_key):
def execute(self, image, content_moderation, api_key):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
@@ -41,7 +44,7 @@ class RemoveForegroundNode():
# files=[('file',('temp_img.jpeg', open(temp_img_path, 'rb'),'image/jpeg'))
# ]
payload = {"file": image_to_base64(image)}
payload = {"file": image_to_base64(image), "content_moderation": content_moderation}
headers = {
"Content-Type": "application/json",
+5 -2
View File
@@ -24,7 +24,8 @@ class ReplaceBgNode():
"original_quality": ("BOOLEAN", {"default": False}),
"force_rmbg": ("BOOLEAN", {"default": False}),
"negative_prompt": ("STRING", {"default": None}),
"seed": ("INT", {"default": 681794})
"seed": ("INT", {"default": 681794}),
"content_moderation": ("BOOLEAN", {"default": False}),
}
}
@@ -45,6 +46,7 @@ class ReplaceBgNode():
negative_prompt,
seed,
api_key,
content_moderation,
bg_prompt=None,
ref_image=None,):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
@@ -74,7 +76,8 @@ class ReplaceBgNode():
"negative_prompt": negative_prompt,
"seed": seed,
"sync": True,
"num_results": 1
"num_results": 1,
"content_moderation": content_moderation
}
headers = {
+6 -2
View File
@@ -15,6 +15,9 @@ class RmbgNode():
"image": ("IMAGE",), # Input image from another node
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}), # API Key input with a default value
},
"optional": {
"content_moderation": ("BOOLEAN", {"default": False}),
}
}
RETURN_TYPES = ("IMAGE",)
@@ -26,7 +29,7 @@ class RmbgNode():
self.api_url = "https://engine.prod.bria-api.com/v1/background/remove" # RMBG API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, api_key):
def execute(self, image, content_moderation, api_key):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
@@ -43,9 +46,10 @@ class RmbgNode():
binary_data = image_buffer.read()
files=[('file',('temp_img.jpeg', BytesIO(binary_data),'image/jpeg'))]
payload = {"content_moderation": content_moderation}
try:
response = requests.post(self.api_url, data={}, headers={"api_token": api_key}, files=files)
response = requests.post(self.api_url, data=payload, headers={"api_token": api_key}, files=files)
# Check for successful response
if response.status_code == 200:
print('response is 200')
+7 -3
View File
@@ -12,7 +12,10 @@ class ShotByImageNode():
"ref_image": ("IMAGE",), # ref image from another node
"enhance_ref_image": ("INT", {"default": 1}),
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}) # API Key input with a default value
}
},
"optional": {
"content_moderation": ("BOOLEAN", {"default": False}),
}
}
RETURN_TYPES = ("IMAGE",)
@@ -24,7 +27,7 @@ class ShotByImageNode():
self.api_url = "https://engine.prod.bria-api.com/v1/product/lifestyle_shot_by_image" # Eraser API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, ref_image, api_key, enhance_ref_image, ):
def execute(self, image, ref_image, api_key, enhance_ref_image, content_moderation):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
@@ -45,7 +48,8 @@ class ShotByImageNode():
"enhance_ref_image": enhance_ref_image,
"placement_type": "original",
"original_quality": True,
"sync": True
"sync": True,
"content_moderation": content_moderation
}
headers = {
"Content-Type": "application/json",
+8 -3
View File
@@ -12,7 +12,10 @@ class ShotByTextNode():
"scene_description": ("STRING",),
"optimize_description": ("INT", {"default": 1}),
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}) # API Key input with a default value
}
},
"optional": {
"content_moderation": ("BOOLEAN", {"default": False}),
}
}
RETURN_TYPES = ("IMAGE",)
@@ -24,7 +27,7 @@ class ShotByTextNode():
self.api_url = "https://engine.prod.bria-api.com/v1/product/lifestyle_shot_by_text" # Eraser API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, api_key, scene_description, optimize_description, ):
def execute(self, image, api_key, scene_description, optimize_description, content_moderation):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
@@ -40,7 +43,9 @@ class ShotByTextNode():
"optimize_description": optimize_description,
"placement_type": "original",
"original_quality": True,
"sync": True
"sync": True,
"content_moderation": content_moderation
}
headers = {
"Content-Type": "application/json",
+75
View File
@@ -0,0 +1,75 @@
import numpy as np
import requests
from PIL import Image
import io
import torch
from .common import image_to_base64, preprocess_image
class TailoredPortraitNode():
@classmethod
def INPUT_TYPES(self):
return {
"required": {
"image": ("IMAGE",), # Input image from another node
"tailored_model_id": ("INT",),
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}), # API Key input with a default value
},
"optional": {
"seed": ("INT", {"default": 123456}),
"tailored_model_influence": ("FLOAT", {"default": 0.9}),
"id_strength": ("FLOAT", {"default": 0.7}),
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("output_image",)
CATEGORY = "API Nodes"
FUNCTION = "execute" # This is the method that will be executed
def __init__(self):
self.api_url = "https://engine.prod.bria-api.com/v1/tailored-gen/restyle_portrait" # Eraser API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, tailored_model_id, api_key, seed, tailored_model_influence, id_strength):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
# Convert the image and mask directly to if isinstance(image, torch.Tensor):
if isinstance(image, torch.Tensor):
image = preprocess_image(image)
image_base64 = image_to_base64(image)
# Prepare the API request payload
payload = {
"id_image_file": f"{image_base64}",
"tailored_model_id": tailored_model_id,
"tailored_model_influence": tailored_model_influence,
"id_strength": id_strength,
"seed": seed
}
headers = {
"Content-Type": "application/json",
"api_token": f"{api_key}"
}
try:
response = requests.post(self.api_url, json=payload, headers=headers)
# Check for successful response
if response.status_code == 200:
print('response is 200')
# Process the output image from API response
response_dict = response.json()
image_response = requests.get(response_dict['image_res'])
result_image = Image.open(io.BytesIO(image_response.content))
result_image = result_image.convert("RGB")
result_image = np.array(result_image).astype(np.float32) / 255.0
result_image = torch.from_numpy(result_image)[None,]
return (result_image,)
else:
raise Exception(f"Error: API request failed with status code {response.status_code}")
except Exception as e:
raise Exception(f"{e}")
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-bria-api"
description = "Custom nodes for ComfyUI using BRIA's API."
version = "2.0.1"
version = "2.0.3"
license = {file = "LICENSE"}
[project.urls]
+169
View File
@@ -0,0 +1,169 @@
{
"last_node_id": 13,
"last_link_id": 11,
"nodes": [
{
"id": 12,
"type": "LoadImage",
"pos": [
669.7035522460938,
136.97129821777344
],
"size": [
315,
314
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
10
],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"pexels-photo-3246665.png",
"image"
]
},
{
"id": 11,
"type": "PreviewImage",
"pos": [
1587.27001953125,
97.39167022705078
],
"size": [
210,
246
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 11
}
],
"outputs": [],
"properties": {
"Node name for S&R": "PreviewImage"
}
},
{
"id": 10,
"type": "Text2ImageFastNode",
"pos": [
1058.320556640625,
96.64427185058594
],
"size": [
438.71258544921875,
394.27716064453125
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "guidance_method_1_image",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "guidance_method_2_image",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "image_prompt_image",
"type": "IMAGE",
"link": 10,
"shape": 7
}
],
"outputs": [
{
"name": "output_image",
"type": "IMAGE",
"links": [
11
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "Text2ImageFastNode"
},
"widgets_values": [
"BRIA_API_TOKEN",
"A drawing of a lion on a table.\t",
"4:3",
990,
"randomize",
8,
0,
"controlnet_canny",
1,
"controlnet_canny",
1,
"regular",
1
]
}
],
"links": [
[
10,
12,
0,
10,
2,
"IMAGE"
],
[
11,
10,
0,
11,
0,
"IMAGE"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 0.7513148009015777,
"offset": [
11.112206386364164,
66.47311795454547
]
},
"node_versions": {
"comfy-core": "v0.3.10-42-gff83865",
"comfyui-bria-api": "499ec5d104cc5110407eafce468ce1d47ac168b3"
},
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0
},
"version": 0.4
}