Pierre Chapuis commited on
Commit
e0e0fed
1 Parent(s): 7938b64
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.jpg filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
- title: Eraser
3
- emoji: 📊
4
  colorFrom: gray
5
  colorTo: blue
6
  sdk: gradio
 
1
  ---
2
+ title: Finegrain Object Eraser
3
+ emoji: 🧽
4
  colorFrom: gray
5
  colorTo: blue
6
  sdk: gradio
app.py CHANGED
@@ -1,7 +1,216 @@
 
 
 
1
  import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
  demo.launch()
 
1
+ import io
2
+ from typing import Any
3
+
4
  import gradio as gr
5
+ import httpx
6
+ from environs import Env
7
+ from gradio_image_annotation import image_annotator
8
+ from PIL import Image
9
+
10
+ env = Env()
11
+ env.read_env()
12
+
13
+ with env.prefixed("ERASER_"):
14
+ API_URL: str = str(env.str("API_URL", "https://spaces.finegrain.ai/eraser"))
15
+ API_KEY: str | None = env.str("API_KEY", None)
16
+ CA_BUNDLE: str | None = env.str("CA_BUNDLE", None)
17
+
18
+ auth = None if API_KEY is None else httpx.BasicAuth("hf", API_KEY)
19
+
20
+
21
+ def process_bbox(prompts: dict[str, Any]) -> Image.Image:
22
+ assert isinstance(img := prompts["image"], Image.Image)
23
+ assert isinstance(boxes := prompts["boxes"], list)
24
+ assert len(boxes) == 1
25
+ assert isinstance(box := boxes[0], dict)
26
+ data = {"bbox": ",".join([str(box[k]) for k in ["xmin", "ymin", "xmax", "ymax"]])}
27
+ with io.BytesIO() as f:
28
+ img.save(f, format="JPEG")
29
+ r = httpx.post(
30
+ API_URL,
31
+ data=data,
32
+ files={"file": f},
33
+ verify=CA_BUNDLE or True,
34
+ timeout=30.0,
35
+ auth=auth,
36
+ )
37
+ r.raise_for_status()
38
+ return Image.open(io.BytesIO(r.content))
39
+
40
+
41
+ def on_change_bbox(prompts: dict[str, Any]):
42
+ return gr.update(interactive=len(prompts["boxes"]) > 0)
43
+
44
+
45
+ def process_prompt(img: Image.Image, prompt: str) -> Image.Image:
46
+ data = {"prompt": prompt}
47
+ with io.BytesIO() as f:
48
+ img.save(f, format="JPEG")
49
+ r = httpx.post(
50
+ API_URL,
51
+ data=data,
52
+ files={"file": f},
53
+ verify=CA_BUNDLE or True,
54
+ timeout=30.0,
55
+ auth=auth,
56
+ )
57
+ r.raise_for_status()
58
+ return Image.open(io.BytesIO(r.content))
59
+
60
+
61
+ def on_change_prompt(img: Image.Image | None, prompt: str | None):
62
+ return gr.update(interactive=bool(img and prompt))
63
+
64
+
65
+ desc = """
66
+ <center>
67
+ <h1>Object Eraser Powered by Refiners</h1>
68
+
69
+ <p style="font-size: 1.25rem;">
70
+ <a href="https://refine.rs" target="_blank">[refiners]</a>
71
+ <a href="https://finegrain.ai/" target="_blank">[finegrain]</a>
72
+ </p>
73
+
74
+ <p>
75
+ Erase any object from your image just by naming it — no manual work required!
76
+ Not only will the object disappear, but so will its effects on the scene, like shadows or reflections.
77
+ </p>
78
+
79
+ <p>
80
+ If you enjoyed this space, please consider starring Refiners on GitHub!
81
+ &nbsp;
82
+ <a href="https://github.com/finegrain-ai/refiners" target="_blank">
83
+ <img
84
+ src="https://img.shields.io/github/stars/finegrain-ai/refiners?style=social"
85
+ style="display: inline; vertical-align: middle;"
86
+ />
87
+ </a>
88
+ </p>
89
+
90
+
91
+ </center>
92
+ """
93
+
94
+ with gr.Blocks() as demo:
95
+ gr.HTML(desc)
96
+ with gr.Tab("By prompt", id="tab_prompt"):
97
+ with gr.Row():
98
+ with gr.Column():
99
+ iimg = gr.Image(type="pil", label="Input")
100
+ prompt = gr.Textbox(label="What should we erase?")
101
+ with gr.Column():
102
+ oimg = gr.Image(show_label=False, label="Output")
103
+ with gr.Row():
104
+ btn = gr.Button("Erase Object", interactive=False)
105
+ for inp in [iimg, prompt]:
106
+ inp.change(
107
+ fn=on_change_prompt,
108
+ inputs=[iimg, prompt],
109
+ outputs=[btn],
110
+ )
111
+ btn.click(fn=process_prompt, inputs=[iimg, prompt], outputs=[oimg])
112
+
113
+ ex = gr.Examples(
114
+ examples=[
115
+ [
116
+ "examples/white-towels-rattan-basket-white-table-with-bright-room-background.jpg",
117
+ "soap",
118
+ ],
119
+ [
120
+ "examples/interior-decor-with-mirror-potted-plant.jpg",
121
+ "potted plant",
122
+ ],
123
+ [
124
+ "examples/detail-ball-basketball-court-sunset.jpg",
125
+ "basketball",
126
+ ],
127
+ [
128
+ "examples/still-life-device-table_23-2150994394.jpg",
129
+ "glass of water",
130
+ ],
131
+ [
132
+ "examples/knife-fork-green-checkered-napkin_140725-63576.jpg",
133
+ "knife and fork",
134
+ ],
135
+ [
136
+ "examples/city-night-with-architecture-vibrant-lights_23-2149836930.jpg",
137
+ "frontmost black car on right lane",
138
+ ],
139
+ [
140
+ "examples/close-up-coffee-latte-wooden-table_23-2147893063.jpg",
141
+ "coffee cup on plate",
142
+ ],
143
+ [
144
+ "examples/empty-chair-with-vase-plant_74190-2078.jpg",
145
+ "chair",
146
+ ],
147
+ ],
148
+ inputs=[iimg, prompt],
149
+ outputs=[oimg],
150
+ fn=process_prompt,
151
+ cache_examples=True,
152
+ )
153
+ with gr.Tab("By bounding box", id="tab_bb"):
154
+ with gr.Row():
155
+ with gr.Column():
156
+ annotator = image_annotator(
157
+ image_type="pil",
158
+ disable_edit_boxes=True,
159
+ show_download_button=False,
160
+ show_share_button=False,
161
+ single_box=True,
162
+ label="Input",
163
+ )
164
+ with gr.Column():
165
+ oimg = gr.Image(show_label=False, label="Output")
166
+ with gr.Row():
167
+ btn = gr.Button("Erase Object", interactive=False)
168
+ annotator.change(
169
+ fn=on_change_bbox,
170
+ inputs=[annotator],
171
+ outputs=[btn],
172
+ )
173
+ btn.click(fn=process_bbox, inputs=[annotator], outputs=[oimg])
174
 
175
+ ex = gr.Examples(
176
+ examples=[
177
+ {
178
+ "image": "examples/white-towels-rattan-basket-white-table-with-bright-room-background.jpg",
179
+ "boxes": [{"xmin": 836, "ymin": 475, "xmax": 1125, "ymax": 1013}],
180
+ },
181
+ {
182
+ "image": "examples/interior-decor-with-mirror-potted-plant.jpg",
183
+ "boxes": [{"xmin": 47, "ymin": 907, "xmax": 397, "ymax": 1633}],
184
+ },
185
+ {
186
+ "image": "examples/detail-ball-basketball-court-sunset.jpg",
187
+ "boxes": [{"xmin": 673, "ymin": 954, "xmax": 911, "ymax": 1186}],
188
+ },
189
+ {
190
+ "image": "examples/still-life-device-table_23-2150994394.jpg",
191
+ "boxes": [{"xmin": 429, "ymin": 586, "xmax": 571, "ymax": 834}],
192
+ },
193
+ {
194
+ "image": "examples/knife-fork-green-checkered-napkin_140725-63576.jpg",
195
+ "boxes": [{"xmin": 972, "ymin": 226, "xmax": 1092, "ymax": 1023}],
196
+ },
197
+ {
198
+ "image": "examples/city-night-with-architecture-vibrant-lights_23-2149836930.jpg",
199
+ "boxes": [{"xmin": 215, "ymin": 637, "xmax": 411, "ymax": 855}],
200
+ },
201
+ {
202
+ "image": "examples/close-up-coffee-latte-wooden-table_23-2147893063.jpg",
203
+ "boxes": [{"xmin": 255, "ymin": 456, "xmax": 1080, "ymax": 1064}],
204
+ },
205
+ {
206
+ "image": "examples/empty-chair-with-vase-plant_74190-2078.jpg",
207
+ "boxes": [{"xmin": 35, "ymin": 320, "xmax": 383, "ymax": 983}],
208
+ },
209
+ ],
210
+ inputs=[annotator],
211
+ outputs=[oimg],
212
+ fn=process_bbox,
213
+ cache_examples=True,
214
+ )
215
 
 
216
  demo.launch()
examples/README.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ Image sources:
2
+
3
+ https://www.freepik.com/free-photo/still-life-device-table_94957277.htm
4
+ https://www.freepik.com/free-photo/empty-chair-with-vase-plant_3661088.htm
5
+ https://www.freepik.com/free-photo/close-up-coffee-latte-wooden-table_3074737.htm
6
+ https://www.freepik.com/free-photo/top-view-round-platter-dinner-knife-fork-green-white-checkered-napkin-notebook-black-table_12137094.htm
7
+ https://www.freepik.com/free-photo/city-night-with-architecture-vibrant-lights_33756725.htm
examples/city-night-with-architecture-vibrant-lights_23-2149836930.jpg ADDED

Git LFS Details

  • SHA256: 447561652b27676f7502f69c553eacb7891b16ea57ff860c2272925d04ce9b66
  • Pointer size: 131 Bytes
  • Size of remote file: 212 kB
examples/close-up-coffee-latte-wooden-table_23-2147893063.jpg ADDED

Git LFS Details

  • SHA256: 904e30c75bdadbbf2a7ba348a5b032c19c7dd7f0c2bf319e348561b36079b27a
  • Pointer size: 131 Bytes
  • Size of remote file: 139 kB
examples/detail-ball-basketball-court-sunset.jpg ADDED

Git LFS Details

  • SHA256: c738fdfe7fbad897d77e865af633c6886412282c794764b7e8da3909987eaf5a
  • Pointer size: 132 Bytes
  • Size of remote file: 1.73 MB
examples/empty-chair-with-vase-plant_74190-2078.jpg ADDED

Git LFS Details

  • SHA256: 6680f32b5552b46dc6cf69d4410b7a31e2a31e30994426008e4329de66231fb8
  • Pointer size: 130 Bytes
  • Size of remote file: 75.5 kB
examples/interior-decor-with-mirror-potted-plant.jpg ADDED

Git LFS Details

  • SHA256: 6d269bb837391ec731c99f06794cb11b1197c7d1d9f7bdee92bced8d11b1019f
  • Pointer size: 132 Bytes
  • Size of remote file: 1.26 MB
examples/knife-fork-green-checkered-napkin_140725-63576.jpg ADDED

Git LFS Details

  • SHA256: 0036c79059a69e0d4807c535b229529f1e6b506d757d370199831acb2649e5e2
  • Pointer size: 131 Bytes
  • Size of remote file: 611 kB
examples/still-life-device-table_23-2150994394.jpg ADDED

Git LFS Details

  • SHA256: 93a1e36b8aeb836d8e893c54acf6f60ebfcfc099cff288dc1c55406dc7a4f18f
  • Pointer size: 130 Bytes
  • Size of remote file: 94.2 kB
examples/white-towels-rattan-basket-white-table-with-bright-room-background.jpg ADDED

Git LFS Details

  • SHA256: f306d7beaa97266a102d46d24f4eb6f07f3d66eee7570774561877227a6ce3cf
  • Pointer size: 132 Bytes
  • Size of remote file: 1.21 MB
gradio_image_annotation-0.2.2-py3-none-any.whl ADDED
Binary file (85.2 kB). View file
 
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ https://huggingface.co/spaces/finegrain/finegrain-object-eraser/resolve/main/gradio_image_annotation-0.2.2-py3-none-any.whl?b=1
2
+ environs>=11.0.0
3
+ httpx>=0.27.0
4
+ pillow>=10.4.0