ALIMHGFY commited on
Commit
2702b53
·
verified ·
1 Parent(s): 1d1d372

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +33 -100
app.py CHANGED
@@ -1,6 +1,5 @@
1
  import gradio as gr
2
  import numpy as np
3
-
4
  import os
5
  from PIL import Image
6
  import requests
@@ -8,140 +7,74 @@ from io import BytesIO
8
  import io
9
  import base64
10
 
11
- hf_token = os.environ.get("HF_TOKEN_API_DEMO") # we get it from a secret env variable, such that it's private
 
 
 
12
  auth_headers = {"api_token": hf_token}
13
 
 
14
  def convert_mask_image_to_base64_string(mask_image):
15
  buffer = io.BytesIO()
16
- mask_image.save(buffer, format="PNG") # You can choose the format (e.g., "JPEG", "PNG")
17
- # Encode the buffer in base64
18
  image_base64_string = base64.b64encode(buffer.getvalue()).decode('utf-8')
19
- return f",{image_base64_string}" # for some reason the funciton which downloads image from base64 expects prefix of "," which is redundant in the url
20
 
 
21
  def download_image(url):
22
  response = requests.get(url)
23
  return Image.open(BytesIO(response.content)).convert("RGB")
24
 
 
25
  def eraser_api_call(image_base64_file, mask_base64_file, mask_type):
26
-
27
  url = "http://engine.prod.bria-api.com/v1/eraser"
28
-
29
  payload = {
30
- "file": image_base64_file,
31
- "mask_file": mask_base64_file,
32
- "mask_type": mask_type,
33
  }
34
  response = requests.post(url, json=payload, headers=auth_headers)
 
 
35
  response = response.json()
36
  res_image = download_image(response["result_url"])
37
-
38
  return res_image
39
 
40
-
41
  def predict(dict):
42
-
43
- init_image = Image.fromarray(dict['background'][:, :, :3], 'RGB') #dict['background'].convert("RGB")#.resize((1024, 1024))
44
- mask = Image.fromarray(dict['layers'][0][:,:,3], 'L') #dict['layers'].convert("RGB")#.resize((1024, 1024))
45
-
46
  image_base64_file = convert_mask_image_to_base64_string(init_image)
47
  mask_base64_file = convert_mask_image_to_base64_string(mask)
48
-
49
  mask_type = "manual"
50
  gen_img = eraser_api_call(image_base64_file, mask_base64_file, mask_type)
51
-
52
  return gen_img
53
 
54
-
55
  css = '''
56
- .gradio-container{max-width: 1100px !important}
57
- #image_upload{min-height:400px}
58
- #image_upload [data-testid="image"], #image_upload [data-testid="image"] > div{min-height: 400px}
59
- #mask_radio .gr-form{background:transparent; border: none}
60
- #word_mask{margin-top: .75em !important}
61
- #word_mask textarea:disabled{opacity: 0.3}
62
- .footer {margin-bottom: 45px;margin-top: 35px;text-align: center;border-bottom: 1px solid #e5e5e5}
63
- .footer>p {font-size: .8rem; display: inline-block; padding: 0 10px;transform: translateY(10px);background: white}
64
- .dark .footer {border-color: #303030}
65
- .dark .footer>p {background: #0b0f19}
66
- .acknowledgments h4{margin: 1.25em 0 .25em 0;font-weight: bold;font-size: 115%}
67
- #image_upload .touch-none{display: flex}
68
- @keyframes spin {
69
- from {
70
- transform: rotate(0deg);
71
- }
72
- to {
73
- transform: rotate(360deg);
74
- }
75
- }
76
- #share-btn-container {padding-left: 0.5rem !important; padding-right: 0.5rem !important; background-color: #000000; justify-content: center; align-items: center; border-radius: 9999px !important; max-width: 13rem; margin-left: auto;}
77
- div#share-btn-container > div {flex-direction: row;background: black;align-items: center}
78
- #share-btn-container:hover {background-color: #060606}
79
- #share-btn {all: initial; color: #ffffff;font-weight: 600; cursor:pointer; font-family: 'IBM Plex Sans', sans-serif; margin-left: 0.5rem !important; padding-top: 0.5rem !important; padding-bottom: 0.5rem !important;right:0;}
80
- #share-btn * {all: unset}
81
- #share-btn-container div:nth-child(-n+2){width: auto !important;min-height: 0px !important;}
82
- #share-btn-container .wrap {display: none !important}
83
- #share-btn-container.hidden {display: none!important}
84
- #prompt input{width: calc(100% - 160px);border-top-right-radius: 0px;border-bottom-right-radius: 0px;}
85
- #run_button {
86
- width: 100%;
87
- height: 50px; /* Set a fixed height for the button */
88
- display: flex;
89
- align-items: center;
90
- justify-content: center;
91
- }
92
- #output-img img, #image_upload img {
93
- object-fit: contain; /* Ensure aspect ratio is preserved */
94
- width: 100%;
95
- height: auto; /* Let height adjust automatically */
96
- }
97
- #prompt-container{margin-top:-18px;}
98
- #prompt-container .form{border-top-left-radius: 0;border-top-right-radius: 0}
99
- #image_upload{border-bottom-left-radius: 0px;border-bottom-right-radius: 0px}
100
  '''
101
 
 
102
  image_blocks = gr.Blocks(css=css, elem_id="total-container")
103
  with image_blocks as demo:
104
  with gr.Column(elem_id="col-container"):
105
  gr.Markdown("## BRIA Eraser API")
106
- gr.HTML('''
107
- <p style="margin-bottom: 10px; font-size: 94%">
108
- This demo showcases the BRIA Eraser capability, which allows users to remove specific elements or objects from images.<br>
109
- The pipeline comprises multiple components, including <a href="https://huggingface.co/briaai/BRIA-2.3" target="_blank">briaai/BRIA-2.3</a>,
110
- <a href="https://huggingface.co/briaai/BRIA-2.3-ControlNet-Inpainting" target="_blank">briaai/BRIA-2.3-ControlNet-Inpainting</a>,
111
- and <a href="https://huggingface.co/briaai/BRIA-2.3-FAST-LORA" target="_blank">briaai/BRIA-2.3-FAST-LORA</a>, all trained on licensed data.<br>
112
- This ensures full legal liability coverage for copyright and privacy infringement.<br>
113
- Notes:<br>
114
- - High-resolution images may take longer to process.<br>
115
- - For multiple masks, results are better if all masks are included in inference.<br><br>
116
- </p>
117
- <p style="margin-bottom: 10px; font-size: 94%">
118
- API Endpoint available on: <a href="https://fal.ai/models/fal-ai/bria/eraser" target="_blank">fal.ai</a><br>
119
- ComfyUI node is available here: <a href="https://github.com/Bria-AI/ComfyUI-BRIA-API" target="_blank">ComfyUI Node</a>
120
- </p>
121
- ''')
122
  with gr.Row():
123
  with gr.Column():
124
- image = gr.ImageEditor(sources=["upload"], layers=False, transforms=[],
125
- brush=gr.Brush(colors=["#000000"], color_mode="fixed"),
126
- )
 
 
 
127
  with gr.Row(elem_id="prompt-container", equal_height=True):
128
- with gr.Column(): # Wrap the button inside a Column
129
- btn = gr.Button("Erase!", elem_id="run_button")
130
-
131
  with gr.Column():
132
  image_out = gr.Image(label="Output", elem_id="output-img")
133
-
134
- # Button click will trigger the inpainting function (no prompt required)
135
- btn.click(fn=predict, inputs=[image], outputs=[image_out], api_name='run')
136
-
137
-
138
- gr.HTML(
139
- """
140
- <div class="footer">
141
- <p>Model by <a href="https://huggingface.co/diffusers" style="text-decoration: underline;" target="_blank">Diffusers</a> - Gradio Demo by 🤗 Hugging Face
142
- </p>
143
- </div>
144
- """
145
- )
146
-
147
- image_blocks.queue(max_size=25,api_open=False).launch(show_api=False)
 
1
  import gradio as gr
2
  import numpy as np
 
3
  import os
4
  from PIL import Image
5
  import requests
 
7
  import io
8
  import base64
9
 
10
+ # الحصول على التوكن من متغير البيئة
11
+ hf_token = os.environ.get("HF_TOKEN_API_DEMO")
12
+ if not hf_token:
13
+ raise ValueError("HF_TOKEN_API_DEMO is not set. Please set it as an environment variable.")
14
  auth_headers = {"api_token": hf_token}
15
 
16
+ # تحويل الصورة إلى Base64
17
  def convert_mask_image_to_base64_string(mask_image):
18
  buffer = io.BytesIO()
19
+ mask_image.save(buffer, format="PNG")
 
20
  image_base64_string = base64.b64encode(buffer.getvalue()).decode('utf-8')
21
+ return f",{image_base64_string}"
22
 
23
+ # تنزيل الصورة من رابط
24
  def download_image(url):
25
  response = requests.get(url)
26
  return Image.open(BytesIO(response.content)).convert("RGB")
27
 
28
+ # استدعاء API الخاص بالإزالة
29
  def eraser_api_call(image_base64_file, mask_base64_file, mask_type):
 
30
  url = "http://engine.prod.bria-api.com/v1/eraser"
 
31
  payload = {
32
+ "file": image_base64_file,
33
+ "mask_file": mask_base64_file,
34
+ "mask_type": mask_type,
35
  }
36
  response = requests.post(url, json=payload, headers=auth_headers)
37
+ if response.status_code != 200:
38
+ raise ValueError(f"API request failed with status code {response.status_code}: {response.text}")
39
  response = response.json()
40
  res_image = download_image(response["result_url"])
 
41
  return res_image
42
 
43
+ # دالة التنبؤ
44
  def predict(dict):
45
+ if 'background' not in dict or 'layers' not in dict:
46
+ raise ValueError("Invalid input format. Missing 'background' or 'layers' keys.")
47
+ init_image = Image.fromarray(dict['background'][:, :, :3], 'RGB')
48
+ mask = Image.fromarray(dict['layers'][0][:, :, 3], 'L')
49
  image_base64_file = convert_mask_image_to_base64_string(init_image)
50
  mask_base64_file = convert_mask_image_to_base64_string(mask)
 
51
  mask_type = "manual"
52
  gen_img = eraser_api_call(image_base64_file, mask_base64_file, mask_type)
 
53
  return gen_img
54
 
55
+ # CSS مخصص
56
  css = '''
57
+ /* محتوى CSS كما هو */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  '''
59
 
60
+ # واجهة Gradio
61
  image_blocks = gr.Blocks(css=css, elem_id="total-container")
62
  with image_blocks as demo:
63
  with gr.Column(elem_id="col-container"):
64
  gr.Markdown("## BRIA Eraser API")
65
+ gr.HTML('''<p>Demo description here...</p>''')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  with gr.Row():
67
  with gr.Column():
68
+ image = gr.ImageEditor(
69
+ sources=["upload"],
70
+ layers=False,
71
+ transforms=[],
72
+ brush=gr.Brush(colors=["#000000"], color_mode="fixed")
73
+ )
74
  with gr.Row(elem_id="prompt-container", equal_height=True):
75
+ btn = gr.Button("Erase!", elem_id="run_button")
 
 
76
  with gr.Column():
77
  image_out = gr.Image(label="Output", elem_id="output-img")
78
+ btn.click(fn=predict, inputs=image, outputs=image_out, api_name='run')
79
+ gr.HTML("<div class='footer'><p>Footer text here...</p></div>")
80
+ image_blocks.queue(max_size=25, api_open=False).launch(show_api=False)