nehulagrawal commited on
Commit
78c94e9
1 Parent(s): 025f4ca

Upload 4 files

Browse files
Files changed (4) hide show
  1. README.md +119 -0
  2. final.png +0 -0
  3. main.py +160 -0
  4. workflow.json +310 -0
README.md ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Swap Cloth
2
+
3
+ This project demonstrates a Cloth Swap feature using ComfyUI, enabling users to change clothing on images seamlessly. This guide provides step-by-step instructions to set up, use, and contribute to the project.
4
+
5
+ <div align="center">
6
+ <img width="500" alt="foduucom/stockmarket-pattern-detection-yolov8" src="https://huggingface.co/foduucom/stockmarket-pattern-detection-yolov8/resolve/main/thumbnail.jpg">
7
+ </div>
8
+
9
+ ## Features
10
+
11
+ - Swap clothing on images with precision.
12
+ - Powered by ComfyUI's flexible architecture.
13
+ - Upload JSON workflows for customization.
14
+ - Simple, efficient, and open-source.
15
+ - Setup Instructions
16
+
17
+
18
+ ## 1. Clone the Cloth Swap Repository
19
+ Clone the repository containing the Cloth Swap JSON workflows and assets:
20
+
21
+ ```bash
22
+ Copy code
23
+ git clone <your-repo-url>
24
+ cd <your-repo-folder>
25
+ ```
26
+
27
+ ## 2. Clone ComfyUI Repository
28
+
29
+ Install ComfyUI by cloning its main repository:
30
+
31
+ ```bash
32
+ Copy code
33
+ git clone https://github.com/comfyanonymous/ComfyUI.git
34
+ cd ComfyUI
35
+ ```
36
+ Install dependencies:
37
+
38
+ ```bash
39
+ Copy code
40
+ pip install -r requirements.txt
41
+ ```
42
+
43
+ Install ComfyUI Manager:
44
+
45
+ goto ComfyUI/custom_nodes dir in terminal(cmd) and clone this repo:
46
+
47
+ ```bash
48
+ Copy code
49
+ git clone https://github.com/ltdrdata/ComfyUI-Manager.git
50
+ ```
51
+ Restart ComfyUI
52
+
53
+ To Start ComfyUI:
54
+
55
+ ```bash
56
+ Copy code
57
+ python3 main.py
58
+ ```
59
+ Note: ComfyUI requires Python 3.9 or above. Ensure all required dependencies are installed.
60
+
61
+ Now Go to Manager ->-> Custom Nodes Manager and install this two nodes "ComfyUI Layer Style" and "ComfyUI_CatVTON_Wrapper", restart and reload the page.
62
+
63
+ <div align="center">
64
+ <img width="500" alt="foduucom/stockmarket-pattern-detection-yolov8" src="https://huggingface.co/foduucom/stockmarket-pattern-detection-yolov8/resolve/main/thumbnail.jpg">
65
+ </div>
66
+
67
+ Make sure you have "sam_vit_h_4b8939.pth" model inside ComfyUI/models/sams directory and "groundingdino_swint_ogc.pth" model in ComfyUI/models/grounding-dino directory if not download it.
68
+ (If directory name not there in ComfyUI/models/ create new)
69
+
70
+ - For Reference you can download model by below link:
71
+ https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/groundingdino_swint_ogc.pth
72
+ https://huggingface.co/spaces/abhishek/StableSAM/resolve/main/sam_vit_h_4b8939.pth
73
+
74
+
75
+ ## 3. How to use
76
+
77
+ - Start ComfyUI (by running python3 main.py)
78
+ - Open ComfyUI in your browser (default: http://127.0.0.1:8188)
79
+ - Click on Load button in menu bar and select the workflow.json file provided in this repository
80
+ - Now click on Queue Prompt for generate output
81
+
82
+ or you can use by python script provided in this repository:
83
+ ```bash
84
+ python3 main.py
85
+
86
+ #Remember change the input paths in script here :
87
+ #prompt["2"]["inputs"]["image"] = "\\ put your input person pose image"
88
+ #prompt["3"]["inputs"]["image"] = "\\ put your input cloth image"
89
+ ```
90
+
91
+ ## 4. Using Cloth Swap
92
+
93
+ -Prepare your input images (ensure proper resolution for better results).
94
+ -Select the uploaded workflow in ComfyUI.
95
+ -Provide necessary inputs as per the workflow:
96
+ -Source Image: The base image where the clothing is to be swapped.
97
+ -Cloth Image: The image of the clothing to be applied.
98
+ -Start the process to generate swapped outputs.
99
+ -Save the generated images for further use.
100
+
101
+
102
+ ## 5. Compute Infrastructure
103
+
104
+ ## Hardware
105
+
106
+ NVIDIA GeForce RTX 3080 card
107
+
108
+ ## Model Card Contact
109
+
110
+ For inquiries and contributions, please contact us at info@foduu.com.
111
+
112
+ ```bibtex
113
+ @ModelCard{
114
+ author = {Nehul Agrawal and
115
+ Priyal Mehta},
116
+ title = {Cloth Swap},
117
+ year = {2024}
118
+ }
119
+ ```
final.png ADDED
main.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #This is an example that uses the websockets api to know when a prompt execution is done
2
+ #Once the prompt execution is done it downloads the images using the /history endpoint
3
+
4
+ import websocket #NOTE: websocket-client (https://github.com/websocket-client/websocket-client)
5
+ import uuid
6
+ import json
7
+ import urllib.request
8
+ import urllib.parse
9
+
10
+ server_address = "127.0.0.1:8188"
11
+ client_id = str(uuid.uuid4())
12
+
13
+ def queue_prompt(prompt):
14
+ p = {"prompt": prompt, "client_id": client_id}
15
+ data = json.dumps(p).encode('utf-8')
16
+ req = urllib.request.Request("http://{}/prompt".format(server_address), data=data)
17
+ return json.loads(urllib.request.urlopen(req).read())
18
+
19
+ def get_image(filename, subfolder, folder_type):
20
+ data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
21
+ url_values = urllib.parse.urlencode(data)
22
+ with urllib.request.urlopen("http://{}/view?{}".format(server_address, url_values)) as response:
23
+ return response.read()
24
+
25
+ def get_history(prompt_id):
26
+ with urllib.request.urlopen("http://{}/history/{}".format(server_address, prompt_id)) as response:
27
+ return json.loads(response.read())
28
+
29
+ def get_images(ws, prompt):
30
+ prompt_id = queue_prompt(prompt)['prompt_id']
31
+ output_images = {}
32
+ while True:
33
+ out = ws.recv()
34
+ if isinstance(out, str):
35
+ message = json.loads(out)
36
+ if message['type'] == 'executing':
37
+ data = message['data']
38
+ if data['node'] is None and data['prompt_id'] == prompt_id:
39
+ break #Execution is done
40
+ else:
41
+ continue #previews are binary data
42
+
43
+ history = get_history(prompt_id)[prompt_id]
44
+ for node_id in history['outputs']:
45
+ node_output = history['outputs'][node_id]
46
+ images_output = []
47
+ if 'images' in node_output:
48
+ for image in node_output['images']:
49
+ image_data = get_image(image['filename'], image['subfolder'], image['type'])
50
+ images_output.append(image_data)
51
+ output_images[node_id] = images_output
52
+
53
+ return output_images
54
+
55
+ prompt_text = """
56
+ {
57
+ "1": {
58
+ "inputs": {
59
+ "sam_model": "sam_vit_h (2.56GB)",
60
+ "grounding_dino_model": "GroundingDINO_SwinT_OGC (694MB)",
61
+ "threshold": 0.3,
62
+ "detail_method": "VITMatte",
63
+ "detail_erode": 6,
64
+ "detail_dilate": 6,
65
+ "black_point": 0.01,
66
+ "white_point": 0.99,
67
+ "process_detail": false,
68
+ "prompt": "shirt",
69
+ "device": "cuda",
70
+ "max_megapixels": 2,
71
+ "cache_model": true,
72
+ "image": [
73
+ "2",
74
+ 0
75
+ ]
76
+ },
77
+ "class_type": "LayerMask: SegmentAnythingUltra V2",
78
+ "_meta": {
79
+ "title": "LayerMask: SegmentAnythingUltra V2"
80
+ }
81
+ },
82
+ "2": {
83
+ "inputs": {
84
+ "image": "q.jpg",
85
+ "upload": "image"
86
+ },
87
+ "class_type": "LoadImage",
88
+ "_meta": {
89
+ "title": "Load Image"
90
+ }
91
+ },
92
+ "3": {
93
+ "inputs": {
94
+ "image": "tshirt.jpeg",
95
+ "upload": "image"
96
+ },
97
+ "class_type": "LoadImage",
98
+ "_meta": {
99
+ "title": "Load Image"
100
+ }
101
+ },
102
+ "5": {
103
+ "inputs": {
104
+ "mask_grow": 25,
105
+ "mixed_precision": "fp16",
106
+ "seed": 95593377186337,
107
+ "steps": 40,
108
+ "cfg": 2.5,
109
+ "image": [
110
+ "2",
111
+ 0
112
+ ],
113
+ "mask": [
114
+ "1",
115
+ 1
116
+ ],
117
+ "refer_image": [
118
+ "3",
119
+ 0
120
+ ]
121
+ },
122
+ "class_type": "CatVTONWrapper",
123
+ "_meta": {
124
+ "title": "CatVTON Wrapper"
125
+ }
126
+ },
127
+ "6": {
128
+ "inputs": {
129
+ "images": [
130
+ "5",
131
+ 0
132
+ ]
133
+ },
134
+ "class_type": "PreviewImage",
135
+ "_meta": {
136
+ "title": "Preview Image"
137
+ }
138
+ }
139
+ }"""
140
+
141
+ prompt = json.loads(prompt_text)
142
+
143
+ prompt["2"]["inputs"]["image"] = "\\ put your input person pose image"
144
+ prompt["3"]["inputs"]["image"] = "\\ put your input cloth image"
145
+
146
+ ws = websocket.WebSocket()
147
+ ws.connect("ws://{}/ws?clientId={}".format(server_address, client_id))
148
+ images = get_images(ws, prompt)
149
+
150
+ # Commented out code to display the output images:
151
+
152
+ for node_id in images:
153
+ for image_data in images[node_id]:
154
+ from PIL import Image
155
+ import io
156
+ image = Image.open(io.BytesIO(image_data))
157
+ image.save("output.jpg")
158
+ # image.show()
159
+
160
+
workflow.json ADDED
@@ -0,0 +1,310 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "last_node_id": 6,
3
+ "last_link_id": 6,
4
+ "nodes": [
5
+ {
6
+ "id": 1,
7
+ "type": "LayerMask: SegmentAnythingUltra V2",
8
+ "pos": {
9
+ "0": 400,
10
+ "1": 184
11
+ },
12
+ "size": [
13
+ 320.8495699999994,
14
+ 366
15
+ ],
16
+ "flags": {},
17
+ "order": 2,
18
+ "mode": 0,
19
+ "inputs": [
20
+ {
21
+ "name": "image",
22
+ "type": "IMAGE",
23
+ "link": 1
24
+ }
25
+ ],
26
+ "outputs": [
27
+ {
28
+ "name": "image",
29
+ "type": "IMAGE",
30
+ "links": null
31
+ },
32
+ {
33
+ "name": "mask",
34
+ "type": "MASK",
35
+ "links": [
36
+ 2,
37
+ 6
38
+ ],
39
+ "slot_index": 1
40
+ }
41
+ ],
42
+ "properties": {
43
+ "Node name for S&R": "LayerMask: SegmentAnythingUltra V2"
44
+ },
45
+ "widgets_values": [
46
+ "sam_vit_h (2.56GB)",
47
+ "GroundingDINO_SwinT_OGC (694MB)",
48
+ 0.3,
49
+ "VITMatte",
50
+ 6,
51
+ 6,
52
+ 0.01,
53
+ 0.99,
54
+ false,
55
+ "shirt",
56
+ "cuda",
57
+ 2,
58
+ true
59
+ ],
60
+ "color": "rgba(27, 80, 119, 0.7)"
61
+ },
62
+ {
63
+ "id": 4,
64
+ "type": "LayerMask: MaskPreview",
65
+ "pos": {
66
+ "0": 749,
67
+ "1": 293
68
+ },
69
+ "size": [
70
+ 241.8495699999994,
71
+ 249.08422000000064
72
+ ],
73
+ "flags": {},
74
+ "order": 3,
75
+ "mode": 0,
76
+ "inputs": [
77
+ {
78
+ "name": "mask",
79
+ "type": "MASK",
80
+ "link": 2
81
+ }
82
+ ],
83
+ "outputs": [],
84
+ "properties": {
85
+ "Node name for S&R": "LayerMask: MaskPreview"
86
+ },
87
+ "widgets_values": [],
88
+ "color": "rgba(27, 80, 119, 0.7)"
89
+ },
90
+ {
91
+ "id": 5,
92
+ "type": "CatVTONWrapper",
93
+ "pos": {
94
+ "0": 742,
95
+ "1": 22
96
+ },
97
+ "size": {
98
+ "0": 315,
99
+ "1": 218
100
+ },
101
+ "flags": {},
102
+ "order": 4,
103
+ "mode": 0,
104
+ "inputs": [
105
+ {
106
+ "name": "image",
107
+ "type": "IMAGE",
108
+ "link": 4
109
+ },
110
+ {
111
+ "name": "mask",
112
+ "type": "MASK",
113
+ "link": 6
114
+ },
115
+ {
116
+ "name": "refer_image",
117
+ "type": "IMAGE",
118
+ "link": 3
119
+ }
120
+ ],
121
+ "outputs": [
122
+ {
123
+ "name": "image",
124
+ "type": "IMAGE",
125
+ "links": [
126
+ 5
127
+ ],
128
+ "slot_index": 0
129
+ }
130
+ ],
131
+ "properties": {
132
+ "Node name for S&R": "CatVTONWrapper"
133
+ },
134
+ "widgets_values": [
135
+ 25,
136
+ "fp16",
137
+ 595025660139604,
138
+ "randomize",
139
+ 40,
140
+ 2.5
141
+ ]
142
+ },
143
+ {
144
+ "id": 6,
145
+ "type": "PreviewImage",
146
+ "pos": {
147
+ "0": 1079,
148
+ "1": 33
149
+ },
150
+ "size": [
151
+ 333.8495699999994,
152
+ 431.08422000000064
153
+ ],
154
+ "flags": {},
155
+ "order": 5,
156
+ "mode": 0,
157
+ "inputs": [
158
+ {
159
+ "name": "images",
160
+ "type": "IMAGE",
161
+ "link": 5
162
+ }
163
+ ],
164
+ "outputs": [],
165
+ "properties": {
166
+ "Node name for S&R": "PreviewImage"
167
+ },
168
+ "widgets_values": []
169
+ },
170
+ {
171
+ "id": 2,
172
+ "type": "LoadImage",
173
+ "pos": {
174
+ "0": 12,
175
+ "1": -81
176
+ },
177
+ "size": [
178
+ 357.84956999999935,
179
+ 383.08422000000064
180
+ ],
181
+ "flags": {},
182
+ "order": 0,
183
+ "mode": 0,
184
+ "inputs": [],
185
+ "outputs": [
186
+ {
187
+ "name": "IMAGE",
188
+ "type": "IMAGE",
189
+ "links": [
190
+ 1,
191
+ 4
192
+ ],
193
+ "slot_index": 0
194
+ },
195
+ {
196
+ "name": "MASK",
197
+ "type": "MASK",
198
+ "links": null
199
+ }
200
+ ],
201
+ "properties": {
202
+ "Node name for S&R": "LoadImage"
203
+ },
204
+ "widgets_values": [
205
+ "q.jpg",
206
+ "image"
207
+ ]
208
+ },
209
+ {
210
+ "id": 3,
211
+ "type": "LoadImage",
212
+ "pos": {
213
+ "0": 58,
214
+ "1": 297
215
+ },
216
+ "size": {
217
+ "0": 315,
218
+ "1": 314
219
+ },
220
+ "flags": {},
221
+ "order": 1,
222
+ "mode": 0,
223
+ "inputs": [],
224
+ "outputs": [
225
+ {
226
+ "name": "IMAGE",
227
+ "type": "IMAGE",
228
+ "links": [
229
+ 3
230
+ ],
231
+ "slot_index": 0
232
+ },
233
+ {
234
+ "name": "MASK",
235
+ "type": "MASK",
236
+ "links": null
237
+ }
238
+ ],
239
+ "properties": {
240
+ "Node name for S&R": "LoadImage"
241
+ },
242
+ "widgets_values": [
243
+ "tshirt.jpeg",
244
+ "image"
245
+ ]
246
+ }
247
+ ],
248
+ "links": [
249
+ [
250
+ 1,
251
+ 2,
252
+ 0,
253
+ 1,
254
+ 0,
255
+ "IMAGE"
256
+ ],
257
+ [
258
+ 2,
259
+ 1,
260
+ 1,
261
+ 4,
262
+ 0,
263
+ "MASK"
264
+ ],
265
+ [
266
+ 3,
267
+ 3,
268
+ 0,
269
+ 5,
270
+ 2,
271
+ "IMAGE"
272
+ ],
273
+ [
274
+ 4,
275
+ 2,
276
+ 0,
277
+ 5,
278
+ 0,
279
+ "IMAGE"
280
+ ],
281
+ [
282
+ 5,
283
+ 5,
284
+ 0,
285
+ 6,
286
+ 0,
287
+ "IMAGE"
288
+ ],
289
+ [
290
+ 6,
291
+ 1,
292
+ 1,
293
+ 5,
294
+ 1,
295
+ "MASK"
296
+ ]
297
+ ],
298
+ "groups": [],
299
+ "config": {},
300
+ "extra": {
301
+ "ds": {
302
+ "scale": 0.9090909090909091,
303
+ "offset": [
304
+ -31.689569999999357,
305
+ 95.6457799999993
306
+ ]
307
+ }
308
+ },
309
+ "version": 0.4
310
+ }