rsamf commited on
Commit
e7f01f9
·
1 Parent(s): 09219ef

Adding initial files

Browse files
Dockerfile ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ FROM rsamf/graphbook:10.0.0
2
+
3
+ RUN pip install graphbook_huggingface
4
+
5
+ COPY config.yaml .
6
+ COPY workflow workflow
7
+
8
+ CMD ["python", "-m", "graphbook.main", "--web_dir", "web/dist", "--isolate_users", "--no_sample"]
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Rmbg Graphbook
3
  emoji: 🏢
4
  colorFrom: red
5
  colorTo: pink
@@ -7,6 +7,10 @@ sdk: docker
7
  pinned: false
8
  license: mit
9
  short_description: An ML app to remove the background from image datasets
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: RMBG Graphbook
3
  emoji: 🏢
4
  colorFrom: red
5
  colorTo: pink
 
7
  pinned: false
8
  license: mit
9
  short_description: An ML app to remove the background from image datasets
10
+ app_port: 8005
11
+ thumbnail: https://cdn.prod.website-files.com/6620137e5938f28a7e4eef8a/662013b554ec4c6bf1306445_Graphbook_Logo_Final_Borderless-512.png
12
  ---
13
 
14
+ This is a Graphbook app that allows users to remove the background from any image dataset from Hugging Face. You may swap different datasets using the Hugging Face extension.
15
+
16
+ Check out our documentation at https://docs.graphbook.ai/.
config.yaml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ plugins:
2
+ - "graphbook_huggingface"
workflow/BackgroundRemoval.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version": "0", "type": "workflow", "nodes": [{"id": "0", "type": "step", "position": {"x": 253.6139923086571, "y": 59.52037501520965}, "data": {"name": "RemoveBackground", "parameters": {"model": {"type": "resource"}, "batch_size": {"type": "number", "default": 8, "value": 8}, "item_key": {"type": "string", "default": "image", "value": "image"}, "output_dir": {"type": "string", "value": "/media/sam/shared/alternative/pokemon_masks"}}, "inputs": ["in"], "outputs": ["out"], "category": "Custom", "label": "RemoveBackground", "key": 12, "isCollapsed": false}, "width": 174, "height": 175, "selected": false, "positionAbsolute": {"x": 671.1501153288792, "y": 288.1274724574072}, "dragging": true, "parentId": "2", "hidden": false}, {"id": "2", "type": "group", "position": {"x": 417.53612302022213, "y": 228.60709744219753}, "width": 487, "height": 306, "data": {"label": "Group", "exports": {"inputs": [{"id": "1", "name": "in", "type": "step"}, {"id": "0", "name": "resource", "type": "resource"}], "outputs": [{"id": "0", "name": "out", "type": "step"}]}, "isCollapsed": false}, "style": {"width": 487, "height": 306}, "resizing": false, "selected": false, "positionAbsolute": {"x": 417.53612302022213, "y": 228.60709744219753}, "dragging": true}, {"id": "3", "type": "export", "position": {"x": 171.28302237599206, "y": 307.94365582341436}, "data": {"label": "split_fn", "exportType": "input", "isResource": true, "isCollapsed": false, "isEditing": false}, "width": 150, "height": 24, "selected": false, "positionAbsolute": {"x": 171.28302237599206, "y": 307.94365582341436}, "dragging": true}, {"id": "4", "type": "export", "position": {"x": 169.3283191390251, "y": 276.5582983666894}, "data": {"label": "Input", "exportType": "input", "isResource": false, "isCollapsed": false, "isEditing": false}, "width": 150, "height": 24, "selected": false, "positionAbsolute": {"x": 169.3283191390251, "y": 276.5582983666894}, "dragging": true}, {"id": "5", "type": "export", "position": {"x": 980.069924178094, "y": 281.42455113963734}, "data": {"label": "Output", "exportType": "output", "isResource": false, "isCollapsed": false}, "width": 150, "height": 24, "positionAbsolute": {"x": 980.069924178094, "y": 281.42455113963734}}, {"id": "6", "type": "resource", "position": {"x": 65.7467508136707, "y": 199.57544189414847}, "data": {"name": "RMBGModel", "parameters": {"model_name": {"type": "string", "description": "The name of the image processor.", "value": "briaai/RMBG-1.4"}}, "category": "Custom", "label": "RMBGModel", "key": 19, "isCollapsed": true}, "width": 150, "height": 24, "selected": false, "positionAbsolute": {"x": 483.28287383389284, "y": 428.182539336346}, "dragging": true, "parentId": "2", "hidden": false}, {"id": "7", "type": "step", "position": {"x": 78.30458080504991, "y": 20.95433445659424}, "data": {"name": "Split", "parameters": {"split_fn": {"type": "resource"}}, "inputs": ["in"], "outputs": ["A", "B"], "category": "Filtering", "label": "Split", "key": 2, "isCollapsed": false}, "width": 150, "height": 120, "selected": false, "positionAbsolute": {"x": 495.84070382527204, "y": 249.56143189879177}, "dragging": true, "parentId": "2", "hidden": false}], "edges": [{"source": "4", "sourceHandle": "in", "target": "2", "targetHandle": "1", "data": {}, "id": "reactflow__edge-4in-21"}, {"source": "6", "sourceHandle": "resource", "target": "0", "targetHandle": "model", "data": {}, "id": "reactflow__edge-6resource-0model"}, {"source": "0", "sourceHandle": "out", "target": "2", "targetHandle": "0_inner", "data": {}, "id": "reactflow__edge-0out-20_inner"}, {"source": "2", "sourceHandle": "0", "target": "5", "targetHandle": "out", "data": {}, "id": "reactflow__edge-20-5out"}, {"source": "3", "sourceHandle": "in", "target": "2", "targetHandle": "0", "data": {}, "id": "reactflow__edge-3in-20"}, {"source": "2", "sourceHandle": "1_inner", "target": "7", "targetHandle": "in", "data": {}, "id": "reactflow__edge-21_inner-7in"}, {"source": "2", "sourceHandle": "0_inner", "target": "7", "targetHandle": "split_fn", "data": {}, "id": "reactflow__edge-20_inner-7split_fn"}, {"source": "7", "sourceHandle": "A", "target": "0", "targetHandle": "in", "data": {}, "id": "reactflow__edge-7A-0in"}]}
workflow/custom_nodes/model.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from graphbook import param, resource
2
+ from transformers import AutoModelForImageSegmentation
3
+
4
+
5
+ @resource("BackgroundRemoval/RMBGModel")
6
+ @param(
7
+ "model_name",
8
+ "string",
9
+ description="The name of the RMBG model.",
10
+ default="briaai/RMBG-1.4",
11
+ )
12
+ @param(
13
+ "use_cuda",
14
+ "boolean",
15
+ description="Whether to use CUDA acceleration.",
16
+ default=True,
17
+ )
18
+ def rmbg_model(self):
19
+ model = AutoModelForImageSegmentation.from_pretrained(
20
+ self.model_name, trust_remote_code=True
21
+ )
22
+ if self.use_cuda:
23
+ return model.to("cuda")
24
+ return model
workflow/custom_nodes/rmbg.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from graphbook import steps
2
+ from transformers import AutoModelForImageSegmentation
3
+ import torchvision.transforms.functional as F
4
+ import torch.nn.functional
5
+ import torch
6
+ import os
7
+ import os.path as osp
8
+
9
+
10
+ class RemoveBackground(steps.BatchStep):
11
+ RequiresInput = True
12
+ Outputs = ["out"]
13
+ Parameters = {
14
+ "batch_size": {
15
+ "type": "number",
16
+ "description": "The batch size for background removal.",
17
+ "default": 8,
18
+ },
19
+ "model": {
20
+ "type": "resource",
21
+ "description": "The model to use for background removal.",
22
+ },
23
+ "output_dir": {
24
+ "type": "string",
25
+ "description": "The directory to save the output images.",
26
+ "default": "/tmp/output",
27
+ },
28
+ }
29
+ Category = "BackgroundRemoval"
30
+
31
+ def __init__(self, batch_size: int, model: AutoModelForImageSegmentation, output_dir: str):
32
+ super().__init__(batch_size, "image")
33
+ self.model = model
34
+ self.output_dir = output_dir
35
+ if self.output_dir:
36
+ os.makedirs(self.output_dir, exist_ok=True)
37
+
38
+ def load_fn(self, item: dict) -> torch.Tensor:
39
+ return load_image_as_tensor(item)
40
+
41
+ def dump_fn(self, t: torch.Tensor, output_path: str):
42
+ save_image_to_disk(t, output_path)
43
+
44
+ @torch.no_grad()
45
+ def on_item_batch(self, tensors, items, notes):
46
+ def get_output_path(note):
47
+ label = ""
48
+ if note["labels"] == 0:
49
+ label = "cat"
50
+ else:
51
+ label = "dog"
52
+ return osp.join(self.output_dir, label, f"{note['image']['shm_id']}.jpg")
53
+
54
+ og_sizes = [t.shape[1:] for t in tensors]
55
+
56
+ images = [
57
+ F.normalize(
58
+ torch.nn.functional.interpolate(
59
+ torch.unsqueeze(image, 0), size=[1024, 1024], mode="bilinear"
60
+ ),
61
+ [0.5, 0.5, 0.5],
62
+ [1.0, 1.0, 1.0],
63
+ )
64
+ for image in tensors
65
+ ]
66
+ images = torch.stack(images).to("cuda")
67
+ images = torch.squeeze(images, 1)
68
+ tup = self.model(images)
69
+ result = tup[0][0]
70
+ ma = torch.max(result)
71
+ mi = torch.min(result)
72
+ result = (result - mi) / (ma - mi)
73
+ resized = [
74
+ torch.squeeze(
75
+ torch.nn.functional.interpolate(
76
+ torch.unsqueeze(image, 0), size=og_size, mode="bilinear"
77
+ ),
78
+ 0,
79
+ ).cpu()
80
+ for image, og_size in zip(result, og_sizes)
81
+ ]
82
+ paths = [
83
+ get_output_path(note) for note in notes
84
+ ]
85
+ removed_bg = list(zip(resized, paths))
86
+ for path, note in zip(paths, notes):
87
+ masks = note["masks"]
88
+ if masks is None:
89
+ masks = []
90
+ masks.append({"value": path, "type": "image"})
91
+ note["masks"] = masks
92
+
93
+ return removed_bg
94
+
95
+
96
+ def load_image_as_tensor(item: dict) -> torch.Tensor:
97
+ im = item["value"]
98
+ image = F.to_tensor(im)
99
+ if image.shape[0] == 1:
100
+ image = image.repeat(3, 1, 1)
101
+ elif image.shape[0] == 4:
102
+ image = image[:3]
103
+
104
+ return image
105
+
106
+
107
+ def save_image_to_disk(t: torch.Tensor, output_path: str):
108
+ dir = osp.dirname(output_path)
109
+ os.makedirs(dir, exist_ok=True)
110
+ img = F.to_pil_image(t)
111
+ img.save(output_path)