7 mins read

A simple yet Powerful ComfyUI Workflow to Upscale Images

Upscaling images has become a fundamental step of modern digital image processing, especially with tools like Stable Diffusion and its advanced GUIs, such as ComfyUI. In essence, upscaling refers to the process of increasing the resolution of an image, enhancing its details and overall quality. This is particularly important in the context of AI-generated images, which often start at lower resolutions and require refinement to meet today’s high-resolution standards.


The Need for Image Upscaling

The default output of Stable Diffusion v1, for example, is 512×512 pixels, a resolution that is relatively low compared to contemporary standards. An unscaled image from Stable Diffusion appears notably low in quality when viewed on high-resolution displays. Moreover, these images often lack sharpness and struggle with fine details, making upscaling not just a choice but a necessity​​. If you want to use your generated images for prints, assets, marketing or any other purpose, you need to ensure that the quality is high and details are sharp.

AI Upscaling: A Game-Changer

AI upscalers are a significant step forward. These are powered by models trained on massive datasets, where high-quality images are first degraded artificially to mimic real-world deterioration. The AI then learns to upscale and restore these images to their original state. This process embeds a vast amount of prior knowledge into the model, enabling it to fill in missing details in a way that mimics human perception. The AI doesn’t need to analyze every pixel in detail; instead, it focuses on key features to reconstruct the image​​.

Upscaling with ComfyUI

There are many options to run image upscaler on your machine, but the principles of upscaling remain consistent across different interfaces like ComfyUI or Automatic1111. The process typically involves:

  1. Uploading the image to be upscaled.
  2. Setting the desired resize factor, with common upscaling being 2x or 4x the original size.
  3. Choosing the appropriate AI upscaler, such as R-ESRGAN, which works well for most images.
  4. Generating the upscaled image, which then appears in the output window for saving​​.

Here is the workflow that I am using: you can simply drag the image in the source node, and the choose if you want to upscale by 2x or 4x. You can also choose the upscaler of your preference and the base model (4x-UltraSharp, R-ESRGAN, 4x-Nickelback…). I am using CrystalClear base model to get even sharper details. No prompt is needed for this workflow! Just set up the parameters and you are ready to go.

A ComfyUI workflow used to upscale an image

As comparison, let’s see what if this process improved the resolution of our input image:

Details of the original image
high res upscaled image with stable diffusion
Details of the upscaled image

If you need to increase the resolution even more, you can replace the first upscaled image in the source node and repeat the process, to double again the size of the image and get even sharper details. You can download this workflow here:

        {
  "last_node_id": 26,
  "last_link_id": 29,
  "nodes": [
    {
      "id": 10,
      "type": "LoadImage",
      "pos": [
        39,
        175
      ],
      "size": [
        508.0225834428712,
        617.3864883906253
      ],
      "flags": {},
      "order": 1,
      "mode": 0,
      "outputs": [
        {
          "name": "IMAGE",
          "type": "IMAGE",
          "links": [
            10,
            18
          ],
          "shape": 3,
          "slot_index": 0
        },
        {
          "name": "MASK",
          "type": "MASK",
          "links": null,
          "shape": 3
        }
      ],
      "properties": {
        "Node name for S&R": "LoadImage"
      },
      "widgets_values": [
        "_60ddfa32-285f-44b7-8d95-01cbfe90cd65.jpg",
        "image"
      ]
    },
    {
      "id": 17,
      "type": "CM_NearestSDXLResolution",
      "pos": [
        297,
        849
      ],
      "size": {
        "0": 210,
        "1": 46
      },
      "flags": {},
      "order": 6,
      "mode": 0,
      "inputs": [
        {
          "name": "image",
          "type": "IMAGE",
          "link": 18
        }
      ],
      "outputs": [
        {
          "name": "width",
          "type": "INT",
          "links": [
            22
          ],
          "shape": 3,
          "slot_index": 0
        },
        {
          "name": "height",
          "type": "INT",
          "links": [
            23
          ],
          "shape": 3,
          "slot_index": 1
        }
      ],
      "properties": {
        "Node name for S&R": "CM_NearestSDXLResolution"
      }
    },
    {
      "id": 13,
      "type": "CLIPTextEncode",
      "pos": [
        838,
        40
      ],
      "size": {
        "0": 400,
        "1": 200
      },
      "flags": {
        "collapsed": true
      },
      "order": 4,
      "mode": 0,
      "inputs": [
        {
          "name": "clip",
          "type": "CLIP",
          "link": 13
        }
      ],
      "outputs": [
        {
          "name": "CONDITIONING",
          "type": "CONDITIONING",
          "links": [
            14
          ],
          "shape": 3,
          "slot_index": 0
        }
      ],
      "properties": {
        "Node name for S&R": "CLIPTextEncode"
      },
      "widgets_values": [
        ""
      ]
    },
    {
      "id": 14,
      "type": "CLIPTextEncode",
      "pos": [
        838,
        89
      ],
      "size": {
        "0": 400,
        "1": 200
      },
      "flags": {
        "collapsed": true
      },
      "order": 5,
      "mode": 0,
      "inputs": [
        {
          "name": "clip",
          "type": "CLIP",
          "link": 16
        }
      ],
      "outputs": [
        {
          "name": "CONDITIONING",
          "type": "CONDITIONING",
          "links": [
            17
          ],
          "shape": 3,
          "slot_index": 0
        }
      ],
      "properties": {
        "Node name for S&R": "CLIPTextEncode"
      },
      "widgets_values": [
        ""
      ]
    },
    {
      "id": 23,
      "type": "CM_IntBinaryOperation",
      "pos": [
        594,
        922
      ],
      "size": {
        "0": 315,
        "1": 106
      },
      "flags": {},
      "order": 8,
      "mode": 0,
      "inputs": [
        {
          "name": "a",
          "type": "INT",
          "link": 23,
          "widget": {
            "name": "a",
            "config": [
              "INT",
              {
                "default": 0
              }
            ]
          },
          "slot_index": 0
        },
        {
          "name": "b",
          "type": "INT",
          "link": 21,
          "widget": {
            "name": "b",
            "config": [
              "INT",
              {
                "default": 0
              }
            ]
          }
        }
      ],
      "outputs": [
        {
          "name": "INT",
          "type": "INT",
          "links": [
            28
          ],
          "shape": 3,
          "slot_index": 0
        }
      ],
      "properties": {
        "Node name for S&R": "CM_IntBinaryOperation"
      },
      "widgets_values": [
        "Mul",
        0,
        4
      ]
    },
    {
      "id": 18,
      "type": "CM_IntBinaryOperation",
      "pos": [
        594,
        756
      ],
      "size": [
        315,
        106
      ],
      "flags": {},
      "order": 7,
      "mode": 0,
      "inputs": [
        {
          "name": "a",
          "type": "INT",
          "link": 22,
          "widget": {
            "name": "a",
            "config": [
              "INT",
              {
                "default": 0
              }
            ]
          },
          "slot_index": 0
        },
        {
          "name": "b",
          "type": "INT",
          "link": 20,
          "widget": {
            "name": "b",
            "config": [
              "INT",
              {
                "default": 0
              }
            ]
          }
        }
      ],
      "outputs": [
        {
          "name": "INT",
          "type": "INT",
          "links": [
            27
          ],
          "shape": 3,
          "slot_index": 0
        }
      ],
      "properties": {
        "Node name for S&R": "CM_IntBinaryOperation"
      },
      "widgets_values": [
        "Mul",
        0,
        4
      ]
    },
    {
      "id": 15,
      "type": "RecommendedResCalc",
      "pos": [
        955,
        840
      ],
      "size": [
        315,
        162
      ],
      "flags": {},
      "order": 9,
      "mode": 0,
      "inputs": [
        {
          "name": "desiredXSIZE",
          "type": "INT",
          "link": 27,
          "widget": {
            "name": "desiredXSIZE",
            "config": [
              "INT",
              {
                "default": 1024,
                "min": 0,
                "max": 8192,
                "step": 2
              }
            ]
          }
        },
        {
          "name": "desiredYSIZE",
          "type": "INT",
          "link": 28,
          "widget": {
            "name": "desiredYSIZE",
            "config": [
              "INT",
              {
                "default": 1024,
                "min": 0,
                "max": 8192,
                "step": 2
              }
            ]
          }
        }
      ],
      "outputs": [
        {
          "name": "recomm width",
          "type": "INT",
          "links": null,
          "shape": 3
        },
        {
          "name": "recomm height",
          "type": "INT",
          "links": null,
          "shape": 3
        },
        {
          "name": "upscale factor",
          "type": "FLOAT",
          "links": [
            26
          ],
          "shape": 3,
          "slot_index": 2
        },
        {
          "name": "reverse upscale for 4x",
          "type": "FLOAT",
          "links": null,
          "shape": 3
        },
        {
          "name": "reverse upscale for 2x",
          "type": "FLOAT",
          "links": null,
          "shape": 3
        }
      ],
      "properties": {
        "Node name for S&R": "RecommendedResCalc"
      },
      "widgets_values": [
        1024,
        1024
      ]
    },
    {
      "id": 11,
      "type": "CheckpointLoaderSimple",
      "pos": [
        570,
        178
      ],
      "size": {
        "0": 315,
        "1": 98
      },
      "flags": {},
      "order": 0,
      "mode": 0,
      "outputs": [
        {
          "name": "MODEL",
          "type": "MODEL",
          "links": [
            11
          ],
          "shape": 3,
          "slot_index": 0
        },
        {
          "name": "CLIP",
          "type": "CLIP",
          "links": [
            13,
            16
          ],
          "shape": 3,
          "slot_index": 1
        },
        {
          "name": "VAE",
          "type": "VAE",
          "links": [
            12
          ],
          "shape": 3,
          "slot_index": 2
        }
      ],
      "properties": {
        "Node name for S&R": "CheckpointLoaderSimple"
      },
      "widgets_values": [
        "crystalClearXL_ccxl.safetensors"
      ]
    },
    {
      "id": 25,
      "type": "Upscale Model Loader",
      "pos": [
        576,
        330
      ],
      "size": {
        "0": 315,
        "1": 78
      },
      "flags": {},
      "order": 3,
      "mode": 0,
      "outputs": [
        {
          "name": "UPSCALE_MODEL",
          "type": "UPSCALE_MODEL",
          "links": [
            25
          ],
          "shape": 3
        },
        {
          "name": "MODEL_NAME_TEXT",
          "type": "STRING",
          "links": null,
          "shape": 3
        }
      ],
      "properties": {
        "Node name for S&R": "Upscale Model Loader"
      },
      "widgets_values": [
        "4x-UltraSharp.pth"
      ]
    },
    {
      "id": 22,
      "type": "PrimitiveNode",
      "pos": [
        580,
        466
      ],
      "size": {
        "0": 210,
        "1": 82
      },
      "flags": {},
      "order": 2,
      "mode": 0,
      "outputs": [
        {
          "name": "INT",
          "type": "INT",
          "links": [
            20,
            21
          ],
          "widget": {
            "name": "b",
            "config": [
              "INT",
              {
                "default": 0
              }
            ]
          },
          "slot_index": 0
        }
      ],
      "properties": {},
      "widgets_values": [
        4,
        "fixed"
      ]
    },
    {
      "id": 12,
      "type": "UltimateSDUpscale",
      "pos": [
        950,
        185
      ],
      "size": [
        315,
        590
      ],
      "flags": {},
      "order": 10,
      "mode": 0,
      "inputs": [
        {
          "name": "image",
          "type": "IMAGE",
          "link": 10
        },
        {
          "name": "model",
          "type": "MODEL",
          "link": 11
        },
        {
          "name": "positive",
          "type": "CONDITIONING",
          "link": 14
        },
        {
          "name": "negative",
          "type": "CONDITIONING",
          "link": 17
        },
        {
          "name": "vae",
          "type": "VAE",
          "link": 12
        },
        {
          "name": "upscale_model",
          "type": "UPSCALE_MODEL",
          "link": 25,
          "slot_index": 5
        },
        {
          "name": "upscale_by",
          "type": "FLOAT",
          "link": 26,
          "widget": {
            "name": "upscale_by",
            "config": [
              "FLOAT",
              {
                "default": 2,
                "min": 0.05,
                "max": 4,
                "step": 0.05
              }
            ]
          }
        }
      ],
      "outputs": [
        {
          "name": "IMAGE",
          "type": "IMAGE",
          "links": [
            29
          ],
          "shape": 3,
          "slot_index": 0
        }
      ],
      "properties": {
        "Node name for S&R": "UltimateSDUpscale"
      },
      "widgets_values": [
        2,
        229329186677676,
        "randomize",
        30,
        8,
        "euler",
        "normal",
        0.25,
        "Linear",
        1024,
        1024,
        8,
        32,
        "None",
        1,
        64,
        8,
        16,
        "enable"
      ]
    },
    {
      "id": 26,
      "type": "SaveImage",
      "pos": [
        1417,
        174
      ],
      "size": [
        722.724821777344,
        725.4237010192873
      ],
      "flags": {},
      "order": 11,
      "mode": 0,
      "inputs": [
        {
          "name": "images",
          "type": "IMAGE",
          "link": 29
        }
      ],
      "properties": {},
      "widgets_values": [
        "ComfyUI"
      ]
    }
  ],
  "links": [
    [
      10,
      10,
      0,
      12,
      0,
      "IMAGE"
    ],
    [
      11,
      11,
      0,
      12,
      1,
      "MODEL"
    ],
    [
      12,
      11,
      2,
      12,
      4,
      "VAE"
    ],
    [
      13,
      11,
      1,
      13,
      0,
      "CLIP"
    ],
    [
      14,
      13,
      0,
      12,
      2,
      "CONDITIONING"
    ],
    [
      16,
      11,
      1,
      14,
      0,
      "CLIP"
    ],
    [
      17,
      14,
      0,
      12,
      3,
      "CONDITIONING"
    ],
    [
      18,
      10,
      0,
      17,
      0,
      "IMAGE"
    ],
    [
      20,
      22,
      0,
      18,
      1,
      "INT"
    ],
    [
      21,
      22,
      0,
      23,
      1,
      "INT"
    ],
    [
      22,
      17,
      0,
      18,
      0,
      "INT"
    ],
    [
      23,
      17,
      1,
      23,
      0,
      "INT"
    ],
    [
      25,
      25,
      0,
      12,
      5,
      "UPSCALE_MODEL"
    ],
    [
      26,
      15,
      2,
      12,
      6,
      "FLOAT"
    ],
    [
      27,
      18,
      0,
      15,
      0,
      "INT"
    ],
    [
      28,
      23,
      0,
      15,
      1,
      "INT"
    ],
    [
      29,
      12,
      0,
      26,
      0,
      "IMAGE"
    ]
  ],
  "groups": [],
  "config": {},
  "extra": {},
  "version": 0.4
}
    

Depending on the performances of your machine, you could upscale an image up to 8k or even more! As long as you have a powerful GPU, the VRAM is the only limit!

Conclusion

In summary, AI upscaling has transformed the landscape of digital image processing. Tools like ComfyUI leverage these advancements, offering flexibility and high-quality results regardless of the initial image format. This makes them indispensable when dealing with AI-generated art or low-resolution sources.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.