ControlNet 1.1のプリプロセッサまとめ!出力結果を比較してみた【Stable Diffusion】

ControlNet プリプロセッサまとめ 画像生成AI

今回もStable DiffusionのControlNetに関する話題で、タイトルのとおり

ControlNet 1.1の各プリプロセッサの特徴・出力結果の違い

を一通りまとめて比較してみるという内容になっています。

ControlNet 1.1ではプリプロセッサの数が大幅に増えたのですが、便利になった反面

  • 種類が多すぎてどれを使えばいいのかよくわからんな…
  • このプリプロセッサは他のやつどどう違うんだろう??

と混乱してしまいますよね。

そこでここではControlNet 1.1のプリプロセッサについて、それぞれ何が違うのか?といった点を解説していきますね。

前提:ControlNetのプリプロセッサとは?

まずはじめに予備知識的な話なのですが、ControlNetのプリプロセッサとは一言でいえば

入力画像に対して前処理を行うための手法のこと

を指します。例えば入力画像の輪郭を抽出して画像を生成する「Canny」モデルのプリプロセッサでは、前処理として下記のように輪郭の抽出を行います。

入力画像 プリプロセッサの出力
女性の写真(1) cannyプリプロセッサの出力例1
※上記1点の入力画像の出典:ぱくたそ 様(https://www.pakutaso.com/)

このようにプリプロセッサでは、各モデルが活用しやすい形になるように入力画像を加工する役割を持っています。

モデルごとのプリプロセッサの比較まとめ

ではモデルごとのプリプロセッサの比較をしていこうと思います。なお今回は複数あるプリプロセッサの比較が目的なので、ここでは対応するプリプロセッサが一つしかないモデルに関しては解説を省略します。つまり下記の7つのモデルを取り上げて解説しますね。

  1. Lineart
  2. Depth
  3. Normal
  4. Scribble
  5. Soft Edge
  6. Segmentation
  7. Openpose

ちなみに比較の際の条件は、特に記載がない場合下記のとおりにするものとします。

プリプロセッサ以外の条件はすべて同じ(もちろんシードの値も同じ)

Lineart

入力画像を線画に変換し、それを元に画像生成を行うモデルです。

女性の写真(1)

入力画像

プリプロセッサの種類 プリプロセッサの出力 生成したイラストの例
lineart_coarse lineart_coarseの出力例 lineart_coarseを使った美少女イラストの例
lineart_realistic lineart_realisticの出力例 lineart_realisticを使った美少女イラストの例
lineart_standard lineart_standardの出力例 lineart_standardを使った美少女イラストの例

プリプロセッサの出力結果を見てみるとそれぞれ結構違いがありますね。

  • coarseはその名の通り粗い感じ
  • realisticは一番精細
  • standardは上2つの中間

といった感じでしょうか。ただ生成したイラストを見るとどれがいいかは好みによると思うので、好きなものを使っていただいてOKでしょう。

Depth

入力画像の深度情報を元に画像生成を行うモデルです。プリプロセッサでは深度の推定を行います。

女性の写真(1)

入力画像

プリプロセッサの種類 プリプロセッサの出力 生成したイラストの例
depth_leres depth_leresの出力例 depth_leresを使って生成した美少女イラストの例
depth_midas depth_midasの出力例 depth_midasを使って生成した美少女イラストの例
depth_zoe depth_zoeの出力例 depth_zoeを使って生成した美少女イラストの例

プリプロセッサの出力を見るとzoeが一番きれいな深度マップを生成できているので、使うならzoeが一番オススメです。

Normal

入力画像の法線情報を元に画像生成を行うモデルです。プリプロセッサでは法線マップを生成します。

女性の写真(1)

入力画像

プリプロセッサの種類 プリプロセッサの出力 生成したイラストの例
normal_bae normal_baeの出力例 normal_baeを使って生成した美少女イラストの例
normal_midas normal_midasの出力例 normal_midasを使って生成した美少女イラストの例

midasが変な法線マップを出力する一方で、baeは正しい法線マップを出力できています。Normalモデルを使うときはbaeのほうを使いましょう。

Scribble

落書きを清書するモデルです。

筆者が適当に描いた「くまみちゃん」の線画

入力画像

プリプロセッサの種類 プリプロセッサの出力 生成したイラストの例
scribble_hed scribble_hedの出力例 scribble_hedを使った美少女イラストの例
scribble_pidinet scribble_pidinetの出力例 scribble_pidinetを使った美少女イラストの例
scribble_xdog scribble_xdogの出力例 scribble_xdogを使った美少女イラストの例

プリプロセッサの出力を見るとまあまあ違いがありますね。でもイラストの生成結果は一概に「これがいい!」という感じでもなく好みによると思うので、好きなものを使っていただいてOKだと思います。

Soft Edge

柔らかい輪郭線を生成し、それを元に画像を生成するモデルです。

女性の写真(1)

入力画像

プリプロセッサの種類 プリプロセッサの出力 生成したイラストの例
softedge_hed softedge_hedの出力例 softedge_hedを使って生成した美少女イラストの例
softedge_hedsafe softedge_hedsafeの出力例 softedge_hedsafeを使って生成した美少女イラストの例
softedge_pidinet softedge_pidinetの出力例 softedge_pidinetを使って生成した美少女イラストの例
softedge_pidisafe softedge_pidisafeの出力例 softedge_pidisafeを使って生成した美少女イラストの例

ControlNet 1.1で

  • softedge_hedsafe
  • softedge_pidisafe

という2つの新しいプリプロセッサが追加されました。このプリプロセッサが追加された理由は、公式ドキュメントによると

HED または PIDI がソフト推定内の元の画像の破損したグレースケール バージョンを隠す傾向があり、そのような隠されたパターンが ControlNet の注意をそらし、悪い結果につながる可能性があるという事実が原因です。(※機械翻訳)

とのこと。まあ要するに従来のプリプロセッサの処理だとControlNet側の処理が上手くいかない場合があるので、その対策を講じたのが上記2つのプリプロセッサだそうです。

Segmentation

セマンティックセグメンテーションという手法で入力画像の物体を認識し、分割を行ってそれを元に画像を生成するモデルです。

きれいな部屋の写真

入力画像(出典:ぱくたそ 様 https://www.pakutaso.com/)

プリプロセッサの種類 プリプロセッサの出力 生成したイラストの例
seg_ofade20k seg_ofade20kの出力例 seg_ofade20kを使って生成した部屋のイラスト
seg_ofcoco seg_ofcocoの出力例 seg_ofcocoを使って生成した部屋のイラスト
seg_ufade20k seg_ufade20kの出力例 seg_ufade20kを使って生成した部屋のイラスト

プリプロセッサの出力を見てみるとそれぞれ違うことが分かりますが、生成したイラストを見ると甲乙つけがたい感じなので好きなものを使っていただいてOKだと思います。

Openpose

入力画像の人物のポーズを認識して棒人間画像を作成し、それを元に画像生成を行う人気のモデルです。

女性の写真

入力画像(出典:ぱくたそ 様 https://www.pakutaso.com/)

プリプロセッサの種類 プリプロセッサの出力 生成したイラストの例
openpose openposeの出力例 openposeを使って生成した美少女イラストの例
openpose_face openpose_faceの出力例 openpose_faceを使って生成した美少女イラストの例
openpose_faceonly openpose_faceonlyの出力例 openpose_faceonlyを使って生成した美少女イラストの例
openpose_full openpose_fullの出力例 openpose_fullを使って生成した美少女イラストの例
openpose_hand openpose_handの出力例 openpose_handを使って生成した美少女イラストの例

ControlNet 1.1では手や表情を認識するためのプリプロセッサが追加されて

  1. openpose:棒人間だけ(手や表情は無し)
  2. openpose_face:表情と棒人間(手は無し)
  3. openpose_faceonly:表情だけ
  4. openpose_full:表情と手のついた棒人間のフルセット
  5. openpose_hand:手のついた棒人間(表情は無し)

の5種類になりました。用途によって使い分けるのがよいと思いますが、基本的には

  • openpose
  • openpose_full

のどちらかのプリプロセッサを使えば十分でしょう。

おわりに

以上、ControlNet 1.1の各プリプロセッサの特徴や比較結果について解説しました。選択したプリプロセッサによって結果が結構違ってくる場合があるので、適当に選ぶのではなくぜひ用途に合わせたプリプロセッサを選択していただければと思います。

この記事が何かしら参考になれば幸いです。

',b.captions&&s){var u=J("figcaption");u.id="baguetteBox-figcaption-"+t,u.innerHTML=s,l.appendChild(u)}e.appendChild(l);var c=J("img");c.onload=function(){var e=document.querySelector("#baguette-img-"+t+" .baguetteBox-spinner");l.removeChild(e),!b.async&&n&&n()},c.setAttribute("src",r),c.alt=a&&a.alt||"",b.titleTag&&s&&(c.title=s),l.appendChild(c),b.async&&n&&n()}}function X(){return M(o+1)}function D(){return M(o-1)}function M(e,t){return!n&&0<=e&&e=k.length?(b.animation&&O("right"),!1):(q(o=e,function(){z(o),V(o)}),R(),b.onChange&&b.onChange(o,k.length),!0)}function O(e){l.className="bounce-from-"+e,setTimeout(function(){l.className=""},400)}function R(){var e=100*-o+"%";"fadeIn"===b.animation?(l.style.opacity=0,setTimeout(function(){m.transforms?l.style.transform=l.style.webkitTransform="translate3d("+e+",0,0)":l.style.left=e,l.style.opacity=1},400)):m.transforms?l.style.transform=l.style.webkitTransform="translate3d("+e+",0,0)":l.style.left=e}function z(e){e-o>=b.preload||q(e+1,function(){z(e+1)})}function V(e){o-e>=b.preload||q(e-1,function(){V(e-1)})}function U(e,t,n,o){e.addEventListener?e.addEventListener(t,n,o):e.attachEvent("on"+t,function(e){(e=e||window.event).target=e.target||e.srcElement,n(e)})}function W(e,t,n,o){e.removeEventListener?e.removeEventListener(t,n,o):e.detachEvent("on"+t,n)}function G(e){return document.getElementById(e)}function J(e){return document.createElement(e)}return[].forEach||(Array.prototype.forEach=function(e,t){for(var n=0;n","http://www.w3.org/2000/svg"===(e.firstChild&&e.firstChild.namespaceURI)}(),m.passiveEvents=function i(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){e=!0}});window.addEventListener("test",null,t)}catch(n){}return e}(),function a(){if(r=G("baguetteBox-overlay"))return l=G("baguetteBox-slider"),u=G("previous-button"),c=G("next-button"),void(d=G("close-button"));(r=J("div")).setAttribute("role","dialog"),r.id="baguetteBox-overlay",document.getElementsByTagName("body")[0].appendChild(r),(l=J("div")).id="baguetteBox-slider",r.appendChild(l),(u=J("button")).setAttribute("type","button"),u.id="previous-button",u.setAttribute("aria-label","Previous"),u.innerHTML=m.svg?f:"<",r.appendChild(u),(c=J("button")).setAttribute("type","button"),c.id="next-button",c.setAttribute("aria-label","Next"),c.innerHTML=m.svg?g:">",r.appendChild(c),(d=J("button")).setAttribute("type","button"),d.id="close-button",d.setAttribute("aria-label","Close"),d.innerHTML=m.svg?p:"×",r.appendChild(d),u.className=c.className=d.className="baguetteBox-button",function n(){var e=m.passiveEvents?{passive:!1}:null,t=m.passiveEvents?{passive:!0}:null;U(r,"click",x),U(u,"click",E),U(c,"click",C),U(d,"click",B),U(l,"contextmenu",A),U(r,"touchstart",T,t),U(r,"touchmove",N,e),U(r,"touchend",L),U(document,"focus",P,!0)}()}(),S(e),function s(e,a){var t=document.querySelectorAll(e),n={galleries:[],nodeList:t};return w[e]=n,[].forEach.call(t,function(e){a&&a.filter&&(y=a.filter);var t=[];if(t="A"===e.tagName?[e]:e.getElementsByTagName("a"),0!==(t=[].filter.call(t,function(e){if(-1===e.className.indexOf(a&&a.ignoreClass))return y.test(e.href)})).length){var i=[];[].forEach.call(t,function(e,t){var n=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1,H(i,a),I(t)},o={eventHandler:n,imageElement:e};U(e,"click",n),i.push(o)}),n.galleries.push(i)}}),n.galleries}(e,t)},show:M,showNext:X,showPrevious:D,hide:j,destroy:function e(){!function n(){var e=m.passiveEvents?{passive:!1}:null,t=m.passiveEvents?{passive:!0}:null;W(r,"click",x),W(u,"click",E),W(c,"click",C),W(d,"click",B),W(l,"contextmenu",A),W(r,"touchstart",T,t),W(r,"touchmove",N,e),W(r,"touchend",L),W(document,"focus",P,!0)}(),function t(){for(var e in w)w.hasOwnProperty(e)&&S(e)}(),W(document,"keydown",F),document.getElementsByTagName("body")[0].removeChild(document.getElementById("baguetteBox-overlay")),w={},h=[],o=0}}})