image2imageとは?

image2imageは 参考画像を下書きにして、その上から絵を描いてもらう 方法です。
下書きにするといっても、完璧にトレスしてしまったらただのコピーです。なんのオリジナリティもありません。
そこで、元の画像が分かる程度にノイズを追加してから、ノイズを除去することで、元画像の構図や雰囲気はほどよく引き継ぎつつ、プロンプトに沿った別バージョンの絵を描いてもらいましょう。
image2imageの仕組み
ここでもう一度、拡散モデルとSamplingのおさらいです。
ComfyUIでは、KSamplerがまず「空の latent」をノイズで埋め、そこから少しずつノイズを取り除くことで画像を生成していました。
image2imageでは、この「空の latent」を参照画像をエンコードした latentに置き換えます。そして、どの時点からノイズを足し始めるかを start_at_step で調整します。
では、steps: 20 の KSampler (Advanced) で start_at_step を変えてみたときの様子を見てみましょう。
start_at_step: 0
- 最初からノイズで埋められます。
- 下書きの画像は全く見えません。ほぼ通常のtext2imageと同じです。
-
※Stable Diffusion 1.5に限り少し挙動が違います。
→ denoise 1.0のときのimage2imageとtext2image
start_at_step: 1
- 1step進んだ場所からスタートします。
- そのため、下書きに追加されるノイズの量(=これから除去するノイズ量)が少し減ります。
- とはいえ、まだ下書きの画像はほとんど見えません。
start_at_step: 9
- 下書きに追加されるノイズの量(=これから除去するノイズ量)がかなり減ります。
- 下書きの輪郭や構図が、そのまま分かる程度に残っています
start_at_step: 20
- 20ステップあるうち、最後のステップから始める指定なので、実質「何もしない」のと同じです。
- つまり、実際には一切サンプリングせず、ノイズも追加されません。
- そのため、入力した画像がそのまま出力されます。
このように、start_at_step を 1 ~ (steps - 1) のどこかに設定すると、元の絵を残しつつサンプリングしている状態になります。
これを image2image と呼びます。
KSampler (Advanced)でのworkflow

{
"id": "8b9f7796-0873-4025-be3c-0f997f67f866",
"revision": 0,
"last_node_id": 15,
"last_link_id": 32,
"nodes": [
{
"id": 8,
"type": "VAEDecode",
"pos": [
1209,
186
],
"size": [
210,
46
],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 28
},
{
"name": "vae",
"type": "VAE",
"link": 10
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"slot_index": 0,
"links": [
9
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
},
{
"id": 7,
"type": "CLIPTextEncode",
"pos": [
416.1970166015625,
392.37848510742185
],
"size": [
410.75801513671877,
158.82607910156253
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 5
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
12
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark"
]
},
{
"id": 10,
"type": "VAELoader",
"pos": [
464.1892561983473,
736.7997591425777
],
"size": [
210,
58
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "VAE",
"type": "VAE",
"links": [
10,
30
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "VAELoader"
},
"widgets_values": [
"vae-ft-mse-840000-ema-pruned.safetensors"
]
},
{
"id": 13,
"type": "LoadImage",
"pos": [
145.97903082644623,
611.5931484814206
],
"size": [
272.2618963068182,
377.6363636363636
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
18
]
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"vivi (1).png",
"image"
],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 9,
"type": "SaveImage",
"pos": [
1451,
186
],
"size": [
354.2876035004722,
433.23967321788405
],
"flags": {},
"order": 8,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33"
},
"widgets_values": [
"ComfyUI"
]
},
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
415,
186
],
"size": [
411.95503173828126,
151.0030493164063
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
11
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"high quality, cute clay figure of a small humanoid character with long pink hair, yellow curved horns, purple boots, simple flat colors, minimal facial features, soft studio lighting, clean background"
]
},
{
"id": 12,
"type": "VAEEncode",
"pos": [
685.9517580991734,
611.5931484814206
],
"size": [
140,
46
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "pixels",
"type": "IMAGE",
"link": 18
},
{
"name": "vae",
"type": "VAE",
"link": 30
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [
32
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "VAEEncode"
},
"widgets_values": [],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 11,
"type": "KSamplerAdvanced",
"pos": [
867.0434936363629,
186
],
"size": [
306.34804687500014,
334
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 14
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 11
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 12
},
{
"name": "latent_image",
"type": "LATENT",
"link": 32
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [
28
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "KSamplerAdvanced"
},
"widgets_values": [
"enable",
123,
"fixed",
20,
8,
"euler",
"normal",
6,
20,
"enable"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 4,
"type": "CheckpointLoaderSimple",
"pos": [
38.43636363636362,
363.0864500000007
],
"size": [
315,
98
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
14
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
3,
5
]
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": []
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"v1-5-pruned-emaonly-fp16.safetensors"
]
}
],
"links": [
[
3,
4,
1,
6,
0,
"CLIP"
],
[
5,
4,
1,
7,
0,
"CLIP"
],
[
9,
8,
0,
9,
0,
"IMAGE"
],
[
10,
10,
0,
8,
1,
"VAE"
],
[
11,
6,
0,
11,
1,
"CONDITIONING"
],
[
12,
7,
0,
11,
2,
"CONDITIONING"
],
[
14,
4,
0,
11,
0,
"MODEL"
],
[
18,
13,
0,
12,
0,
"IMAGE"
],
[
28,
11,
0,
8,
0,
"LATENT"
],
[
30,
10,
0,
12,
1,
"VAE"
],
[
32,
12,
0,
11,
3,
"LATENT"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 0.7513148009015777,
"offset": [
61.56363636363638,
-86
]
},
"frontendVersion": "1.34.5",
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}
- 🟩VAE Encodeノードで、画像をlatentに変換します。
- 🟨
start_at_stepの値を変更して、元の画像をどれくらい残すか、いろいろ試してみてください。
KSamplerでのworkflow
無印 KSampler でも、もちろん image2image はできます。
ただし、「どのつまみで元画像の残り具合を決めるか」 が、KSampler (Advanced) とかなり違います。

{
"id": "8b9f7796-0873-4025-be3c-0f997f67f866",
"revision": 0,
"last_node_id": 16,
"last_link_id": 39,
"nodes": [
{
"id": 8,
"type": "VAEDecode",
"pos": [
1209,
186
],
"size": [
210,
46
],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 39
},
{
"name": "vae",
"type": "VAE",
"link": 10
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"slot_index": 0,
"links": [
9
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
},
{
"id": 10,
"type": "VAELoader",
"pos": [
464.1892561983473,
736.7997591425777
],
"size": [
210,
58
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "VAE",
"type": "VAE",
"links": [
10,
30
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "VAELoader"
},
"widgets_values": [
"vae-ft-mse-840000-ema-pruned.safetensors"
]
},
{
"id": 13,
"type": "LoadImage",
"pos": [
145.97903082644623,
611.5931484814206
],
"size": [
272.2618963068182,
377.6363636363636
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
18
]
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"vivi (1).png",
"image"
],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 9,
"type": "SaveImage",
"pos": [
1451,
186
],
"size": [
354.2876035004722,
433.23967321788405
],
"flags": {},
"order": 8,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33"
},
"widgets_values": [
"ComfyUI"
]
},
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
415,
186
],
"size": [
411.95503173828126,
151.0030493164063
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
35
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"high quality, cute clay figure of a small humanoid character with long pink hair, yellow curved horns, purple boots, simple flat colors, minimal facial features, soft studio lighting, clean background"
]
},
{
"id": 7,
"type": "CLIPTextEncode",
"pos": [
416.1970166015625,
392.37848510742185
],
"size": [
410.75801513671877,
158.82607910156253
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 5
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
36
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark"
]
},
{
"id": 12,
"type": "VAEEncode",
"pos": [
685.9517580991734,
611.5931484814206
],
"size": [
140,
46
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "pixels",
"type": "IMAGE",
"link": 18
},
{
"name": "vae",
"type": "VAE",
"link": 30
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [
37
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "VAEEncode"
},
"widgets_values": [],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 4,
"type": "CheckpointLoaderSimple",
"pos": [
38.43636363636362,
363.0864500000007
],
"size": [
315,
98
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
38
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
3,
5
]
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": []
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"v1-5-pruned-emaonly-fp16.safetensors"
]
},
{
"id": 16,
"type": "KSampler",
"pos": [
871.9451695085444,
186
],
"size": [
301.7355371900828,
262
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 38
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 35
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 36
},
{
"name": "latent_image",
"type": "LATENT",
"link": 37
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [
39
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "KSampler"
},
"widgets_values": [
123,
"fixed",
20,
8,
"euler",
"normal",
0.7
],
"color": "#323",
"bgcolor": "#535"
}
],
"links": [
[
3,
4,
1,
6,
0,
"CLIP"
],
[
5,
4,
1,
7,
0,
"CLIP"
],
[
9,
8,
0,
9,
0,
"IMAGE"
],
[
10,
10,
0,
8,
1,
"VAE"
],
[
18,
13,
0,
12,
0,
"IMAGE"
],
[
30,
10,
0,
12,
1,
"VAE"
],
[
35,
6,
0,
16,
1,
"CONDITIONING"
],
[
36,
7,
0,
16,
2,
"CONDITIONING"
],
[
37,
12,
0,
16,
3,
"LATENT"
],
[
38,
4,
0,
16,
0,
"MODEL"
],
[
39,
16,
0,
8,
0,
"LATENT"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 0.9090909090909091,
"offset": [
61.56363636363638,
-86
]
},
"frontendVersion": "1.34.5",
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}
- 🟪
denoiseの値を変更して、元の画像をどれくらい残すかを設定します。1.0では完全にノイズで埋めます。つまりtext2imageと同じです。0.0ではノイズを一切追加しないので、元の画像がそのまま出力されます。
無印と Advanced の違い
ここで、KSampler (Advanced) と見比べてみます。
やりたいこと自体は同じで、どちらも 「元画像にどれくらいノイズを足してから、どれくらい除去するか」 を調整しています。
ただ、つまみの割り当て方が違うため少し混乱します。同じ結果になりそうな設定でそれぞれの挙動を見てみましょう。
KSampler (Advanced)
- 例えば
steps: 20,start_at_step: 4とすると、
「全体 20 ステップのうち、4 ステップ目から 20 ステップ目まで」だけを実行します。 - 実際にサンプリングされる回数は 20 - 4 = 16 回 です。
無印 KSampler
- 同じく
steps: 20にして、denoise: 0.8などと設定すると、見た目の「ノイズのかかり方」は近くなりますが、サンプリング回数は 20 回のまま です。 denoiseの値を 0.5 に変えても 0.1 に変えても、やはり 20 回サンプリングします。
- Advanced
stepsは「全体のステップ数」、start_at_step以降だけ実行 → 実行回数が変わる
- 無印
stepsは「実際の実行回数」、denoiseはノイズの強さだけを変える → 実行回数は変わらない
もし、無印KSamplerで Advanced に「近いノイズのかかり方」にしたい場合、以下の式がざっくりした目安になります。(完全に一致はしません)
設定するstep数 ≒ 全体のstep数 * denoise
別に気にしなくていい
ここまでしっかり説明しておいてなんですが、どちらも 「元画像にどれくらいノイズを足すか」 を決めているだけです。
無印KSamplerとAdvancedを混在させる場合は注意が必要ですが、そんなworkflowを組む人はいないので、気にする必要はありません。
どのパラメータを変更すれば、どの程度元の画像が残るかがわかっていればOKです。
denoise 1.0のときのimage2imageとtext2image
denoise: 1.0の時、元の画像をノイズで完全に埋めてしまうので、仕組み的にはimage2imageもEmpty Latent Imageノードを使ったtext2imageも同じになるはずです。

が、Stable Diffusion 1.5だと同じになりません。(実装の違いだと思いますが、理解していないのでわかりません。)
一方で、最近のモデル(Flux等)では、全く同じ画像になります。
Stable Diffusion 1.5は特殊な例として、このサイトでは、本来の設計どおり 「denoise 1.0 の image2image と text2image は同じもの」 として扱っていきます。
サンプル画像
