高解像度の画像を出したい (Hires. Fix の基本形)

画像生成するなら、1920x1080 あたり以上のサイズが欲しいことも多いでしょう。 しかし、Stable Diffusion では、学習時の画像サイズである 512x512 (オリジナルの SD1 の場合) や 768x768 (オリジナルの SD2 の場合) から大きく離れたサイズの画像を生成しようとすると、構図のおかしな画像になります。 現実には、一辺を 1.5 倍にする程度が実用的な限度です。 最近は 1024x1024 などの画像で追加学習したモデルも出回っているものの、それでも不足です。 そこで、問題の起きにくいサイズで画像生成し、それを拡大する、というのがよく使われる手法です。

このページでは、いわゆる Hires. fix を含む各種の高解像度化手法とその得失について解説します。

まとめ
  • ComfyUI なら多段の『Hires. fix』なども実装できる。ただし、LDSR は使えない。
  • 個人的には 2段 * (ImageUpscaleWithModel(x4) + ImageScale(x0.5) + KSampler) が好き。
スケーラー単独
ImageScale
単独
ImageUpscaleWithModel
単独
LatentUpscale
単独
サイズの自由度

1ピクセル単位

×

2x 固定だったり
4x 固定だったり

8ピクセル単位

速度、処理時間

一瞬

△×

KSampler よりは早い

一瞬

結果の予測可能性

素直

○△

画質

拡大しても画質、
情報量は変わらない

○△×

良くなったり悪くなったり、
粗が強調されることもある。

モデルや元画像の状況次第

×

アーティファクトがひどい

KSampler あり
ImageScale
+ KSampler
ImageUpscaleWithModel
+ ImageScale
+ KSampler
LatentUpscale
+ KSampler
サイズの自由度

8ピクセル単位

8ピクセル単位

(ImageScale を併用する)

8ピクセル単位

1段あたりの実用的な最大拡大率

2.0x

2.0x 〜 4.0x

モデルと元画像の状況次第

1.5x 〜 2.0x

速度、処理時間 ×

KSampler も VAE デコードも遅い

×

KSampler も VAE デコードも遅い

×

段数多い =
アーティファクト除去の
KSampler が遅い

結果の予測可能性

denoise 次第

○△

手順の単純さ △×

VAE を往復しないといけない

△×

VAE を往復しないといけない

単純だが段数は多くなりがち

画質

元画像の状況次第

○△

モデルと元画像の状況次第

×△

高画質化しようとすると
構図が崩れやすい

KSampler

denoise: 小〜中、
steps: 小〜中

高画質化するならやや強めのが必要

denoise: 小〜中、
steps: 小〜中

モデルや元画像の状況次第

denoise: 中〜大、
steps: 中〜大

強めのが必須

典型的な構成

2段 〜 3段

2段

3段 〜 4段

目次

Hires. fix の中身と ComfyUI による実装

Hires. fix の中身

Stable Diffusion での生成画像を (半ばブラックボックス的に) 高解像度化することを、『Hires. fix』と呼ぶことがあります (誰がそう呼び出したのかは分かりません)。 いわゆる『Hires. fix』では、以下のような処理を行います。

  • 画像の拡大 & 補間
    • pixel 画像を拡大 (単純な bi-linear だったり、ESRGAN だったり)、または
    • latent 画像を拡大 (単純な bi-linear だったり、LDSR だったり)
  • 大抵の場合、上項に追加して img2img による細部の復元

このうち LDSR は ComfyUI の対応待ちですが、それ以外の処理は ComfyUI で実現可能です。

ComfyUI による実装

単純な例から始めましょう。

元となる latent 画像を前半の LatentUpscale で 1.5倍に拡大した後、後半の img2img を担当する KSampler で細部を作っています。

前半で拡大します。 ここでは LatentUpscale を使っていますが、LatentUpscaleBy でも一緒です。 また、ImageScaleImageUpscaleWithModel を使うこともできます。 その場合は、一度 VAEDecode で pixel 画像に変換してから拡大し、VAEEncode で戻すことになります。 方法によって得失は様々です。 詳細は各項で説明します。

後半では、KSampler を使います。 KSampler は、ノイズを加えて前半で発生したアーティファクトを隠した後に、あらためてノイズを除去し直すと共に細部を再構成します。 プロンプトは、通常は元画像生成時のものと同じものを使用します (ConditioningSetArea を使っている場合を除く)。

seed は適当で構いません。 画像を拡大しているので、元画像の KSampler と同じ値でも問題ありません。 とは言え、同じ seed に特別な利点があるわけでもありません。 作業の効率から言えば、キャッシュを有効活用するために、fixed にはしておいた方が良いです。

denoise は、前半の条件や元画像により 0.05 〜 0.6 あたりで様々です。 0.05 であっても、細部の再構成に留まらない変化が少なからず (目に見えるレベルで) 発生します。

前半で発生したアーティファクトやボケが denoise 換算でどれくらいになるかに関して、確立した理論はありません。 経験的に言えることの一つは、前半で大きく拡大すると、後半で大きな denoise を行わないとアーティファクトやボケが残る、ということです。 denoise を大きくすると構図が崩れたり、有ったものが消えたり無いものが増えたりしやすくなります。 特に人物のアップや直線の多い構造物などは、一気に拡大するのは難しいです。

おおまかに言って、拡大率を高くしやすいのは、

  • もともと崩れていて積極的に拡大することで修正したい場合 (小面積の人物等。ただし LatentUpscale だと消えることがある) (この場合が一番 Hires. "Fix" っぽい)
  • 拡大後の解像度でも崩れにくい場合 (中面積の人物等)
  • 崩れても目立ちにくい場合 (自然の風景等)
  • 物が消えたり別の物が入ったりしても問題ない場合
  • 前半の拡大で発生したアーティファクトが少ない場合 (ImageScaleImageUpscaleWithModel を使う場合)
  • 前半の拡大で細部のヒントが補間された場合 (ImageUpscaleWithModel を使う場合)

となります。その限界を超えて更に高解像度化するには、段を追加します。

2段目の拡大率が 1段目と同じであれば、denoise 量は同じで問題無いことが多いです。 ただ、サイズが上がっている分、処理時間がかなり長くなります。 そのため、step に関しては、様子を見つつ限界まで下げることもあります。

seed については、画像を拡大しているので、上の例のように前の段と同じ値でも問題ありません。

画像のサイズが大きくなると、学習済み U-Net が前提とする被写体とプロンプトとの乖離が発生します。 特に人物では問題になりやすいです。 対処法としては以下のようなものがありますが、完全ではありません。

  • denoise 量を下げる
  • 問題の発生する段以降で使用するプロンプトを、個別具体的なものから一般的なものに変更する (best quality, extremely detailed だけにするなど)
  • cfg を下げる
  • (画像個別の対応を厭わない場合) SetLatentNoiseMask で latent noise mask を指定して、問題の起こる場所を処理から除外する (かなり面倒)

KSampler での VRAM 使用量や処理時間に問題がなければ、3段目以降を追加することもできます。

個別の手法

ImageScale 単独

ImageScale ノードを使います。 古典的な画像処理アルゴリズムを使って、pixel 画像を拡大します。

機械学習技術を使う ImageUpscaleWithModel と比較すると、以下のような特徴があります:

  • 拡大後のサイズを pixel 単位で指定できる。
  • かなり速い。 処理はほぼ一瞬。
  • 結果が予想できる。 ボケる (bilinear) かジャギる (nearest-exact, area) かのどちらか。 不自然な副作用が無い。
  • 拡大時に細部を描き込んだりすることはできない。

良い点もありますが、ボケるかジャギるかが確定しているので、最終結果を得る手段としては不適です。

ImageScale + KSampler

ImageScale で拡大し、KSampler で細部の再現を行います。

ImageScale で拡大した画像に対しては、KSampler の反応が弱いです。 ボケやジャギをその画像の特徴と捉えて、そのまま残そうとしているように見えます。 そのため、やや強めの denoise が必要になります。 学習データに ImageScale 相当の拡大画像が多く含まれていたのかもしれません。

1段あたり 2倍程度の拡大率が一般的です。

denoise の目安
1.5x 2.0x
元画像の質が良い場合 0.25 〜 0.40 0.30 〜 0.45
元画像の質が悪い場合 0.40 〜 0.60 0.45 〜 0.60

ImageUpscaleWithModel 単独

ImageUpscaleWithModel ノードを使います。 機械学習技術を使って、pixel 画像を拡大します。拡大率は upscale モデル依存で固定です。2倍と 4倍のものが主流です。

使用する upscale モデルによって特性は様々ですが、 古典的なアルゴリズムを使う ImageScale と比較すると、おおまかに以下のような特徴があります:

  • 拡大率が固定。
  • かなり遅い。
  • 元画像に含まれていない高周波成分を復元できることが多い。 細い線が見えるようになったり、輪郭がはっきりしたりする。
  • 上項と関連して、ボケたままにして欲しいところが不自然に鮮明になったりすることがある。
  • モデルによっては、元画像に含まれるノイズ (JPEG 圧縮のブロックノイズ等) を強力に除去できる。 ただし、latent 由来のノイズはほぼ除去できない (そういう用途で学習されていない)。 それどころか、ノイズを強調したりすることもある。
  • 上項と関連して、服のシワや髪の毛などが消えたり、塗りが平坦になりすぎたりすることがある。

細部にうねりや作り物っぽさが出ることもありますが、使用する upscale モデルと元画像との組み合わせが良ければ、最終結果を得る手段としても有効です。

ImageUpscaleWithModel + KSampler

ImageUpscaleWithModel で拡大し、KSampler でアーティファクト除去と細部の再現を行います。 ImageUpscaleWithModel の拡大率が高すぎる場合は、KSampler に入れる前に ImageScale で縮小します。

元画像の質が良く、ImageUpscaleWithModel で使用するモデルとの相性が良ければ、小さな denoise を使用でき、とても良い結果を得られます。 1段あたり 2倍の拡大率が一般的ですが、コントロールされた条件下であれば 4倍もありえます。

モデルによりますが、2x よりも同系統の 4x のモデルで拡大して ImageScale で 0.5 倍した方が、良い結果が得られることが多い気がします。

denoise の目安
2.0x 4.0x
512x512 からの 1段目で
元画像の質が良い場合
0.05 〜 0.20 0.05 〜 0.30
512x512 からの 1段目で
元画像の質が悪い場合
0.20 〜 0.40 0.30 〜 0.50
1024x1024 からの 2段目で
元画像の質が良い場合
0.05 〜 0.20 0.05 〜 0.20
1024x1024 からの 2段目で
元画像の質が悪い場合
0.10 〜 0.30 0.10 〜 0.40

LatentUpscale 単独

LatentUpscale ノード、または LatentUpscaleBy ノードを使います。

LatentUpscale の場合は、latent 画像を指定した幅と高さになるように拡大します。 幅と高さの指定は対応する pixel 画像の大きさで、それぞれ 8 の倍数で指定します。

LatentUpscaleBy の場合は、latent 画像を指定した倍率で拡大します。 幅と高さは、pixel 画像の大きさ換算でそれぞれ 8 の倍数になるように、3捨4入調整されます。

pixel に比べて荒い latent 画素 (解像度 1/8) に対する処理になるので、結果の品質は良くありません。 また、latent に埋め込まれた位置関係の情報が狂うことになるため、アーティファクトが盛大に乗ります。

アーティファクトが目立ちすぎるので、最終結果を得る手段にはなり得ません。

LatentUpscale + KSampler

LatentUpscale または LatentUpscaleBy で拡大し、KSampler でアーティファクト除去と細部の再現を行います。

pixel 画像を経由せずに latent 画像だけで完結するので、構成としては単純になります。

LatentUpscale で発生した盛大なアーティファクトを除去する必要があるので、denoisesteps も大きくなります。 denoise が大きくなれば、今度は KSampler でアーティファクトが発生しやすくなります。 2倍以上の拡大は、構図崩れとの戦いとなりがちです。 一段あたり 1.3 〜 1.5倍程度の拡大に抑えて多段構成にするのが一般的です。 一段あたり縦横 128 ピクセルずつ分しか拡大しない、という人もいたりします (10 段とかになる)。

LatentUpscalenearest-exact を選ぶと、アーティファクト由来の構造 (縞や出島等) が出やすくなります。 bilinear を選ぶと、かなりボケます。 いずれの場合も、どの程度 LatentUpscale 由来のアーティファクトの影響を受け入れるかが denoise 量を左右し、KSampler でのアーティファクトとのトレードオフになります。

denoise の目安
1.5x 2.0x
nearest-exact でアーティファクト由来の
模様等を受け入れる場合
0.20 〜 0.40 0.30 〜 0.45
nearest-exact でアーティファクト由来の
模様等を消す場合
0.40 〜 0.55 0.45 〜 0.60
bilinear でボケを受け入れる場合 0.20 〜 0.40 0.30 〜 0.40
bilinear でボケを消す場合 0.40 〜 0.55 0.40 〜 0.60