diff --git a/README.md b/README.md index df08bc0..0dec5d9 100644 --- a/README.md +++ b/README.md @@ -42,13 +42,27 @@ The main advantages of inpainting only in a masked area with these nodes are: - Forced size uses `force_width` and `force_height` and upscales the content to take that size before sampling, then downscales before stitching back. Use forced size e.g. for SDXL. - Free size uses `rescale_factor` to optionally rescale the content before sampling and eventually scale back before stitching, and `padding` to align to standard sizes. -## Example +## Example (Stable Diffusion) This example inpaints by sampling on a small section of the larger image, upscaling to fit 512x512-768x768, then stitching and blending back in the original image. Download the following example workflow from [here](inpaint-cropandstitch_example_workflow.json) or drag and drop the screenshot into ComfyUI. ![Workflow](inpaint-cropandstitch_example_workflow.png) +## Example (Flux) +This example uses Flux. Requires the GGUF nodes. + +Models used: + +- Flux Dev Q5 GGUF from [here](https://civitai.com/models/711483/flux-dev-q5km-gguf-quantization-a-nice-balance-of-speed-and-quality-in-under-9-gigabytes?modelVersionId=795785). Put it in models/unet/. This model works with 4 steps. +- `t5 GGUF Q3_K_L` from [here](https://huggingface.co/city96/t5-v1_1-xxl-encoder-gguf/tree/main). Put it in models/clip/. +- `clip_l` from [here](https://huggingface.co/comfyanonymous/flux_text_encoders/blob/main/clip_l.safetensors). Put it in models/clip/. +- ae VAE from [here](https://huggingface.co/black-forest-labs/FLUX.1-schnell/blob/main/ae.safetensors). Put it in models/vae/ + +Download the following example workflow from [here](inpaint-cropandstitch_flux_example_workflow.json) or drag and drop the screenshot into ComfyUI. + +![Workflow](inpaint-cropandstitch_flux_example_workflow.png) + # Installation Instructions Install via ComfyUI-Manager or go to the custom_nodes/ directory and run ```$ git clone https://github.com/lquesada/ComfyUI-Inpaint-CropAndStitch.git``` @@ -63,6 +77,8 @@ If you want to inpaint fast with SD 1.5, use ranged size with min width and heig If you want to inpaint with SDXL, use forced size = 1024. # Changelog +## 2024-10-28 +- Added a new example workflow for inpainting with flux. ## 2024-06-10 - Added a new node: "Resize Image Before Inpainting", which allows increasing the resolution of the input image by a factor or to a minimum width or height to obtain higher resolution inpaintings. ## 2024-06-08 diff --git a/inpaint-cropandstitch_flux_example_workflow.json b/inpaint-cropandstitch_flux_example_workflow.json new file mode 100644 index 0000000..878402e --- /dev/null +++ b/inpaint-cropandstitch_flux_example_workflow.json @@ -0,0 +1,1218 @@ +{ + "last_node_id": 54, + "last_link_id": 106, + "nodes": [ + { + "id": 16, + "type": "LoadImage", + "pos": { + "0": 40, + "1": 610 + }, + "size": { + "0": 530, + "1": 480 + }, + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [], + "slot_index": 0, + "shape": 3 + }, + { + "name": "MASK", + "type": "MASK", + "links": [ + 52 + ], + "slot_index": 1, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "clipspace/clipspace-mask-6898724.4.png [input]", + "image" + ] + }, + { + "id": 30, + "type": "BasicScheduler", + "pos": { + "0": 1610, + "1": 1610 + }, + "size": { + "0": 310, + "1": 110 + }, + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 102, + "slot_index": 0 + } + ], + "outputs": [ + { + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 75 + ], + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "BasicScheduler" + }, + "widgets_values": [ + "simple", + 4, + 1 + ] + }, + { + "id": 32, + "type": "RandomNoise", + "pos": { + "0": 1610, + "1": 1790 + }, + "size": { + "0": 315, + "1": 82 + }, + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "NOISE", + "type": "NOISE", + "links": [ + 72 + ], + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "RandomNoise" + }, + "widgets_values": [ + 663461854580115, + "randomize" + ], + "color": "#2a363b", + "bgcolor": "#3f5159" + }, + { + "id": 2, + "type": "InpaintStitch", + "pos": { + "0": 2110, + "1": 60 + }, + "size": { + "0": 210, + "1": 78 + }, + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "stitch", + "type": "STITCH", + "link": 8 + }, + { + "name": "inpainted_image", + "type": "IMAGE", + "link": 81 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 22 + ], + "slot_index": 0, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "InpaintStitch" + }, + "widgets_values": [ + "bislerp" + ] + }, + { + "id": 25, + "type": "VAELoader", + "pos": { + "0": 590, + "1": 1340 + }, + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "VAE", + "type": "VAE", + "links": [ + 70, + 84 + ], + "slot_index": 0, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "VAELoader" + }, + "widgets_values": [ + "ae.safetensors" + ] + }, + { + "id": 36, + "type": "CLIPTextEncode", + "pos": { + "0": 1040, + "1": 1200 + }, + "size": { + "0": 260, + "1": 76 + }, + "flags": { + "collapsed": true + }, + "order": 8, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 104 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 83 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "" + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 29, + "type": "KSamplerSelect", + "pos": { + "0": 1600, + "1": 1470 + }, + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "SAMPLER", + "type": "SAMPLER", + "links": [ + 74 + ], + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "KSamplerSelect" + }, + "widgets_values": [ + "euler" + ] + }, + { + "id": 28, + "type": "SamplerCustomAdvanced", + "pos": { + "0": 2030, + "1": 1250 + }, + "size": { + "0": 310, + "1": 110 + }, + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "noise", + "type": "NOISE", + "link": 72, + "slot_index": 0 + }, + { + "name": "guider", + "type": "GUIDER", + "link": 73, + "slot_index": 1 + }, + { + "name": "sampler", + "type": "SAMPLER", + "link": 74, + "slot_index": 2 + }, + { + "name": "sigmas", + "type": "SIGMAS", + "link": 75, + "slot_index": 3 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 88, + "slot_index": 4 + } + ], + "outputs": [ + { + "name": "output", + "type": "LATENT", + "links": [ + 69 + ], + "slot_index": 0, + "shape": 3 + }, + { + "name": "denoised_output", + "type": "LATENT", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "SamplerCustomAdvanced" + }, + "widgets_values": [] + }, + { + "id": 17, + "type": "InpaintExtendOutpaint", + "pos": { + "0": 640, + "1": 510 + }, + "size": { + "0": 430, + "1": 194 + }, + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 47 + }, + { + "name": "mask", + "type": "MASK", + "link": 66 + }, + { + "name": "optional_context_mask", + "type": "MASK", + "link": 67, + "shape": 7 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 39 + ], + "slot_index": 0, + "shape": 3 + }, + { + "name": "mask", + "type": "MASK", + "links": [ + 40 + ], + "slot_index": 1, + "shape": 3 + }, + { + "name": "context_mask", + "type": "MASK", + "links": [ + 41 + ], + "slot_index": 2, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "InpaintExtendOutpaint" + }, + "widgets_values": [ + "factors", + 0, + 1, + 0, + 1, + 0, + 1, + 0, + 1 + ] + }, + { + "id": 1, + "type": "InpaintCrop", + "pos": { + "0": 1160, + "1": 100 + }, + "size": { + "0": 350, + "1": 314 + }, + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 39 + }, + { + "name": "mask", + "type": "MASK", + "link": 40 + }, + { + "name": "optional_context_mask", + "type": "MASK", + "link": 41, + "shape": 7 + } + ], + "outputs": [ + { + "name": "stitch", + "type": "STITCH", + "links": [ + 8 + ], + "slot_index": 0, + "shape": 3 + }, + { + "name": "cropped_image", + "type": "IMAGE", + "links": [ + 85 + ], + "slot_index": 1, + "shape": 3 + }, + { + "name": "cropped_mask", + "type": "MASK", + "links": [ + 86 + ], + "slot_index": 2, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "InpaintCrop" + }, + "widgets_values": [ + 20, + 1, + true, + 16, + false, + 16, + "bicubic", + "forced size", + 1024, + 1024, + 1, + 512, + 512, + 1024, + 1024, + 32 + ] + }, + { + "id": 31, + "type": "BasicGuider", + "pos": { + "0": 1710, + "1": 1270 + }, + "size": { + "0": 241.79998779296875, + "1": 46 + }, + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 103, + "slot_index": 0 + }, + { + "name": "conditioning", + "type": "CONDITIONING", + "link": 87, + "slot_index": 1 + } + ], + "outputs": [ + { + "name": "GUIDER", + "type": "GUIDER", + "links": [ + 73 + ], + "slot_index": 0, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "BasicGuider" + }, + "widgets_values": [] + }, + { + "id": 35, + "type": "InpaintModelConditioning", + "pos": { + "0": 1420, + "1": 1150 + }, + "size": { + "0": 216.59999084472656, + "1": 106 + }, + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 82 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 83 + }, + { + "name": "vae", + "type": "VAE", + "link": 84 + }, + { + "name": "pixels", + "type": "IMAGE", + "link": 85 + }, + { + "name": "mask", + "type": "MASK", + "link": 86 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 87 + ], + "slot_index": 0, + "shape": 3 + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [], + "slot_index": 1, + "shape": 3 + }, + { + "name": "latent", + "type": "LATENT", + "links": [ + 88 + ], + "slot_index": 2, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "InpaintModelConditioning" + }, + "widgets_values": [] + }, + { + "id": 18, + "type": "InpaintResize", + "pos": { + "0": 640, + "1": 230 + }, + "size": { + "0": 430, + "1": 170 + }, + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 54 + }, + { + "name": "mask", + "type": "MASK", + "link": 51 + }, + { + "name": "optional_context_mask", + "type": "MASK", + "link": 52, + "shape": 7 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 47 + ], + "slot_index": 0, + "shape": 3 + }, + { + "name": "mask", + "type": "MASK", + "links": [ + 66 + ], + "slot_index": 1, + "shape": 3 + }, + { + "name": "context_mask", + "type": "MASK", + "links": [ + 67 + ], + "slot_index": 2, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "InpaintResize" + }, + "widgets_values": [ + "bicubic", + "ensure minimum size", + 1024, + 1024, + 1 + ] + }, + { + "id": 50, + "type": "DualCLIPLoaderGGUF", + "pos": { + "0": 590, + "1": 1170 + }, + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 104, + 105 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "DualCLIPLoaderGGUF" + }, + "widgets_values": [ + "t5-v1_1-xxl-encoder-Q3_K_L.gguf", + "clip_l.safetensors", + "flux" + ] + }, + { + "id": 10, + "type": "SaveImage", + "pos": { + "0": 2250, + "1": 210 + }, + "size": { + "0": 510, + "1": 640 + }, + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 22, + "slot_index": 0 + } + ], + "outputs": [], + "properties": {}, + "widgets_values": [ + "%date:yyyyMMddhhmmss%" + ] + }, + { + "id": 3, + "type": "LoadImage", + "pos": { + "0": 40, + "1": 70 + }, + "size": { + "0": 530, + "1": 480 + }, + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 54 + ], + "slot_index": 0, + "shape": 3 + }, + { + "name": "MASK", + "type": "MASK", + "links": [ + 51 + ], + "slot_index": 1, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "clipspace/clipspace-mask-6889098.2.png [input]", + "image" + ] + }, + { + "id": 22, + "type": "CLIPTextEncode", + "pos": { + "0": 1000, + "1": 990 + }, + "size": { + "0": 300, + "1": 160 + }, + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 105 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 82 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "a goat walking away from the viewer, blended with the background around" + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 52, + "type": "Note", + "pos": { + "0": 400, + "1": 1630 + }, + "size": { + "0": 640, + "1": 220 + }, + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": { + "text": "" + }, + "widgets_values": [ + "Models used:\n\n- Flux Dev Q5 GGUF from https://civitai.com/models/711483/flux-dev-q5km-gguf-quantization-a-nice-balance-of-speed-and-quality-in-under-9-gigabytes?modelVersionId=795785.\n Put it in models/unet/\n This model works with 4 steps\n\n- t5 GGUF Q3_K_L from https://huggingface.co/city96/t5-v1_1-xxl-encoder-gguf/tree/main\n Put it in models/clip/\n\n- clip_l from https://huggingface.co/comfyanonymous/flux_text_encoders/blob/main/clip_l.safetensors\n Put it in models/clip/\n\n- ae VAE from https://huggingface.co/black-forest-labs/FLUX.1-schnell/blob/main/ae.safetensors\n Put it in models/vae/\n\n" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 51, + "type": "UnetLoaderGGUF", + "pos": { + "0": 590, + "1": 1460 + }, + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 102, + 103 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "UnetLoaderGGUF" + }, + "widgets_values": [ + "fluxDevQ5KMGGUFQuantizationA_v10.gguf" + ] + }, + { + "id": 23, + "type": "VAEDecode", + "pos": { + "0": 1860, + "1": 370 + }, + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 69 + }, + { + "name": "vae", + "type": "VAE", + "link": 70 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 81, + 106 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + }, + "widgets_values": [] + }, + { + "id": 54, + "type": "PreviewImage", + "pos": { + "0": 1850, + "1": 530 + }, + "size": { + "0": 310, + "1": 320 + }, + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 106 + } + ], + "outputs": [], + "properties": { + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + } + ], + "links": [ + [ + 8, + 1, + 0, + 2, + 0, + "STITCH" + ], + [ + 22, + 2, + 0, + 10, + 0, + "IMAGE" + ], + [ + 39, + 17, + 0, + 1, + 0, + "IMAGE" + ], + [ + 40, + 17, + 1, + 1, + 1, + "MASK" + ], + [ + 41, + 17, + 2, + 1, + 2, + "MASK" + ], + [ + 47, + 18, + 0, + 17, + 0, + "IMAGE" + ], + [ + 51, + 3, + 1, + 18, + 1, + "MASK" + ], + [ + 52, + 16, + 1, + 18, + 2, + "MASK" + ], + [ + 54, + 3, + 0, + 18, + 0, + "IMAGE" + ], + [ + 66, + 18, + 1, + 17, + 1, + "MASK" + ], + [ + 67, + 18, + 2, + 17, + 2, + "MASK" + ], + [ + 69, + 28, + 0, + 23, + 0, + "LATENT" + ], + [ + 70, + 25, + 0, + 23, + 1, + "VAE" + ], + [ + 72, + 32, + 0, + 28, + 0, + "NOISE" + ], + [ + 73, + 31, + 0, + 28, + 1, + "GUIDER" + ], + [ + 74, + 29, + 0, + 28, + 2, + "SAMPLER" + ], + [ + 75, + 30, + 0, + 28, + 3, + "SIGMAS" + ], + [ + 81, + 23, + 0, + 2, + 1, + "IMAGE" + ], + [ + 82, + 22, + 0, + 35, + 0, + "CONDITIONING" + ], + [ + 83, + 36, + 0, + 35, + 1, + "CONDITIONING" + ], + [ + 84, + 25, + 0, + 35, + 2, + "VAE" + ], + [ + 85, + 1, + 1, + 35, + 3, + "IMAGE" + ], + [ + 86, + 1, + 2, + 35, + 4, + "MASK" + ], + [ + 87, + 35, + 0, + 31, + 1, + "CONDITIONING" + ], + [ + 88, + 35, + 2, + 28, + 4, + "LATENT" + ], + [ + 102, + 51, + 0, + 30, + 0, + "MODEL" + ], + [ + 103, + 51, + 0, + 31, + 0, + "MODEL" + ], + [ + 104, + 50, + 0, + 36, + 0, + "CLIP" + ], + [ + 105, + 50, + 0, + 22, + 0, + "CLIP" + ], + [ + 106, + 23, + 0, + 54, + 0, + "IMAGE" + ] + ], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 0.6209213230591553, + "offset": [ + 126.32447259250364, + 227.9315324606847 + ] + } + }, + "version": 0.4 +} \ No newline at end of file diff --git a/inpaint-cropandstitch_flux_example_workflow.png b/inpaint-cropandstitch_flux_example_workflow.png new file mode 100644 index 0000000..8a7861c Binary files /dev/null and b/inpaint-cropandstitch_flux_example_workflow.png differ