Qwen-Image 2.1の部分編集は、引数1つで位置ずれが約0.1pxになった
目次

7月にQwen-Image-Edit 2511のピクセル位置ずれを測った記事では、ComfyUIの標準ノードが参照画像を勝手にリサイズするせいで、編集のたびに絵が約8pxずれていた。ComfyUI標準のReferenceLatentノードで元の寸法のまま入れると、ずれは約1pxまで小さくなった。
Qwen-Image 2.1は、文章からの生成と画像の編集が1つのモデルにまとまっている。
M1 Maxでは編集1枚に約12分かかっていたが、TaylorSeerキャッシュを入れた記事で約4分半になり、Qwen-Image-Edit(8ステップの蒸留版)の約5分とほぼ同じになった。
なら、表情だけ変えるような部分編集でも位置を保てるのか。7月と同じ元画像、同じ測り方で確かめた。
検証環境
| 項目 | 内容 |
|---|---|
| マシン | MacBook Pro、Apple M1 Max、メモリ64GB |
| 実行環境 | Python 3.12.12、PyTorch 2.14.0(MPS)、Diffusers 0.41.0.dev0(コミット 80c7ed26) |
| モデル | Qwen-Image 2.1(BF16) |
| 共通の生成条件 | 832×1216、40ステップ、シード42、CFG1.0、ネガティブプロンプトなし。各条件1回ずつ |
| 高速化 | TaylorSeer Lite(数ステップだけ実際に計算して、残りを予測するキャッシュ。cache_interval=3)とKVキャッシュの併用。1条件だけキャッシュなしでも生成 |
| 元画像 | 7月と同じ、自作キャラ2人の全身立ち絵 832×1216 |
| 比較対象 | 7月の記事のQwen-Image-Edit 2511(Qwen-Rapid-AIO v23、8ステップ)の出力と計測値 |
| ずれの測定 | エッジマップの位相相関(2枚の画像のずれ量を周波数から求める方法)を、画像全体と3×3ブロックで計算。dxは横、dyは縦のずれ。7月の測定スクリプトを流用 |
| 変化の測定 | 元画像とのRGB平均絶対差が20/255を超えた画素の割合。顔の枠は、2人の顔を目視で囲った長方形2つで、7月と同じ座標 |
測定スクリプトは、7月のQwen-Image-Editの出力にかけて、記事と同じ値(線画でdx +8.0px、表情編集の顔の外0.7%)になることを先に確かめた。
測定スクリプトと編集の指示はLiltingChannelLaboに置いた。
![]()
Diffusersのパイプラインが行う参照画像のリサイズ
Diffusersの QwenImage21Pipeline は、参照画像を受け取ると、面積が output_resolution の2乗(既定は1024×1024)になる寸法を計算して、そこへリサイズしてからVAE(画像と内部表現を変換する部分)とテキストエンコーダーに入力する。寸法は32の倍数に丸められる。
# diffusers/pipelines/qwenimage21/pipeline_qwenimage21.py(抜粋)
def calculate_dimensions(target_area, ratio):
width = math.sqrt(target_area * ratio)
height = width / ratio
width = round(width / 32) * 32
height = round(height / 32) * 32
return width, height, None
832×1216の元画像を入れると、参照は832×1248になる。幅はそのままで、縦だけ2.6%伸びる。
出力の寸法を元画像と同じ832×1216に指定すると、参照と出力で格子が合わなくなる。
引数を1つ指定するだけで直った。output_resolution に、元画像の幅と高さの積の平方根を丸めた値を指定する。832×1216なら1006で、output_resolution の2乗が元画像の面積とほぼ同じになるので、計算される寸法が832×1216ちょうどになり、リサイズしても寸法が変わらなくなる。
| 元画像の寸法 | 既定(1024)での参照の寸法 | 指定する output_resolution | そのときの参照の寸法 |
|---|---|---|---|
| 832×1216 | 832×1248 | 1006 | 832×1216 |
| 1216×832 | 1248×832 | 1006 | 1216×832 |
| 1024×1024 | 1024×1024 | 1024 | 1024×1024 |
| 960×1280 | 896×1184 | 1109 | 960×1280 |
| 1024×1536 | 832×1248 | 1254 | 1024×1536 |
この計算が合うのは、元画像の幅と高さが32の倍数のとき。1024×1024や768×1344のように、既定のままで寸法が変わらない組み合わせもある。
image = pipe(
prompt=prompt,
image=[source], # 832×1216
width=832,
height=1216,
output_resolution=1006, # round(sqrt(832 * 1216))
num_inference_steps=40,
true_cfg_scale=1.0,
generator=torch.Generator("cpu").manual_seed(42),
).images[0]
既定のままを条件A、output_resolution=1006 を条件Cとする。呼び方は、7月の記事の条件A(標準ノード直結)と条件C(ReferenceLatent)に合わせた。7月の条件Bにあたる1024×1024への切り出しは、今回はやっていない。
実験1 線画推定でずれを測る
7月と同じ線画化の指示を使った。参照画像の呼び方だけ、Qwen-Image 2.1の書き方に合わせて Picture 1 から image 1 に変えている。
Convert image 1 into clean black line art on a pure white background. Trace every contour and detail exactly where it is in the original image. Do not move, resize, crop, or redraw anything. No color, no shading, no gray tones.
| モデル | 条件 | 全体のずれ | 3×3ブロックの傾向 |
|---|---|---|---|
| Qwen-Image 2.1 | A(既定) | dx +1.1px / dy +0.0px | 左の列が+6〜+8px、右の列が−5〜−8px。左右から中央へ縮んでいる |
| Qwen-Image 2.1 | C(output_resolution=1006) | dx +0.0px / dy +0.1px | 9ブロック中6つが0.1px以下、残りも1px未満 |
| Qwen-Image-Edit 2511(7月) | A(標準ノード直結) | dx +8.0px / dy −3.3px | 左端+3px→右端+14pxの勾配 |
| Qwen-Image-Edit 2511(7月) | C(ReferenceLatent) | dx +1.1px / dy +0.5px | 全ブロック約1pxで均一 |
条件Aは、全体の平均では小さい値になるが、ブロックごとに測ると左右で逆にずれていた。左の列が約+7px、右の列が約−8pxで、列の中心どうしは約555px離れている。15÷555で、人物が横に約2.7%細くなった計算になる。参照が縦に伸ばされた2.6%とほぼ同じ。
伸ばされた参照の縦横比が、832×1216の出力の中でもそのまま保たれた結果に思える。縦のずれはどのブロックも1px未満だった。
条件Cは画像全体で0.1px以下になり、7月のReferenceLatent構成の約1pxより小さい。
位相相関で出るのは、輪郭どうしが一番よく重なる平行移動の量で、画素の1つ1つのずれが0.1px以内という意味ではない。


元画像のエッジを赤、出力のエッジをシアンで重ねた。

実験2 表情だけ変えて、ほかが動かないか
7月の記事で、ほかを変えるなという指定を付けなかった版と同じ1行の指示で、2人の表情を閉じ目の笑顔に変えた。
Change both girls' facial expressions to a big cheerful open-mouth smile with happy closed eyes.
| モデル | 条件 | 平均差分 | 変化画素率(全体) | 顔領域内 | 顔領域外 |
|---|---|---|---|---|---|
| Qwen-Image 2.1 | VAE往復のみ | 1.21 | 0.02% | 0.12% | 0.02% |
| Qwen-Image 2.1 | A(既定) | 15.18 | 15.1% | 49.2% | 12.8% |
| Qwen-Image 2.1 | C、TaylorSeerあり | 4.33 | 3.8% | 20.8% | 2.6% |
| Qwen-Image 2.1 | C、キャッシュなし | 4.43 | 3.9% | 21.1% | 2.7% |
| Qwen-Image-Edit 2511(7月) | C(ReferenceLatent) | 2.66 | 1.7% | 16.9% | 0.7% |
条件Aは顔の外の12.8%が変わった。人物が細くなった分、全身の輪郭が動いている。
条件Cは顔の外が2.6%まで下がった。TaylorSeerありとキャッシュなしはほぼ同じ値で、今回の表情編集では、キャッシュの有無による違いは小さかった。


顔の外の2.6%は、7月のQwen-Image-Editの0.7%より多い。VAEの往復だけなら0.02%だった。
差分のヒートマップでは、全身の輪郭に沿って細い赤線が残っている。元画像と並べて拡大すると、位置は合っているが、輪郭線がわずかに細くなり、肌の影も少し薄くなっていた。今回の出力では、編集していない場所の輪郭も軽くなぞり直されたように思える。

顔の描き方を、元画像、7月のQwen-Image-Edit、今回のQwen-Image 2.1で並べた。



実験3 怒り顔と、片方だけの着せ替え
条件Cのまま、指示を変えて2枚出した。
(怒り顔)
Change both girls' facial expressions to an angry face with furrowed eyebrows.
(左の子だけ黒セーラー服)
Change only the left girl's outfit to a black sailor school uniform.
| 編集 | 全体 | 顔領域内 | 顔領域外 | 左半分 | 右半分 | 画像全体のずれ |
|---|---|---|---|---|---|---|
| 怒り顔 | 3.6% | 18.8% | 2.6% | 3.5% | 3.7% | dx −0.1px / dy +0.0px |
| 左の子だけ黒セーラー服 | 14.2% | 9.7% | 14.5% | 25.2% | 3.2% | dx −0.1px / dy −0.0px |
怒り顔の顔の外は2.6%で、笑顔と同じ値になった。
左の子だけの着せ替えでは、指示していない右半分にも3.2%の変化が出たが、表情編集の顔の外とほぼ同じ値だった。7月のQwen-Image-Editでは、同じ編集の右半分が0.42%だった。
画像全体のずれは、笑顔も含めてどの編集でも約0.1pxだった。


背景の透過
表情や衣装の編集の出力はRGBAのPNGで保存されていたが、アルファ(透明度)は全面255だった。
パイプラインのコードを確かめると、Qwen-Image 2.1のVAEは入力が4チャンネルで、参照画像もRGBAに変換してから入力している。背景を透明にする指示を出してみた。
Remove the white background of image 1 and make the background fully transparent. Keep the two girls exactly as they are.
| 項目 | 値 |
|---|---|
| アルファが128未満の画素 | 57.5% |
| アルファが255の画素 | 39.9% |
| 背景部分のアルファ | 大半が1〜8(完全な0は1.6%) |
| 全体の位置ずれ | dx +0.0px / dy −0.0px |



白い背景の上の白いシャツと白い靴下は、透明にならずに残った。色のしきい値で白を消す方法だと、シャツと靴下も一緒に消える。
背景のアルファは完全な0にはならず、大半が1〜8だった。
前と後ろの2枚を参照にして横向きを出す
元画像の右側にいる茶髪のサイドポニーの子が、オリキャラのかなちゃん。ローカル版の記事では、かなちゃんの立ち絵を真横に編集すると、本人の左側で結んだサイドポニーの位置が保てなかった。
三面図を参照に入れるとちゃんとポーズを取れるという話を聞いたが、その三面図の横向きの1枚が出せない。前と後ろの2枚を入れたら横向きが出せないか、試してみた。後ろ姿は、ローカル版の記事で出した真後ろの画像を使った。
プロンプトは前回の真横の英文のままで、参照の呼び方だけを変えた。
1girl, solo, the girl from image 1, image 2 shows the same girl from behind, keep her face, hairstyle and outfit exactly as in image 1 and image 2,


| 向き | 参照 | 期待 | 結果 | 生成処理 |
|---|---|---|---|---|
| 本人の右側から | 正面の1枚 | 結び目は頭の奥側に隠れる | 結び目とシュシュが手前側に見えている | 270.0秒 |
| 本人の右側から | 正面と真後ろの2枚 | 同上 | 結び目が少し高く後ろ寄りになったが、手前側に見えたまま | 331.1秒 |
| 本人の左側から | 正面の1枚 | 結び目は手前側の側頭部 | 手前側だが、後頭部寄りの高い位置 | 277.8秒 |
| 本人の左側から | 正面と真後ろの2枚 | 同上 | 1枚のときとほぼ同じ | 330.6秒 |




真後ろの参照を足しても、右側からの横顔は直らなかった。結び目が少し高く後ろ寄りになっただけで、手前側に見えたままだった。左側からの横顔は、参照が1枚でも2枚でもほぼ同じ絵になった。
左右どちらの横顔も後頭部の高い位置に結び目があり、同じ絵を左右反転したように見える。
Qwen-Image-Editでも、前と後ろを入れて横向きは出なかったので、こんなものだと思う。
編集1枚の生成時間
| 処理 | 生成処理 |
|---|---|
| Qwen-Image 2.1の編集、参照1枚、TaylorSeer+KVキャッシュ | 約270秒 |
| Qwen-Image 2.1の編集、参照2枚、TaylorSeer+KVキャッシュ | 約331秒 |
| Qwen-Image 2.1の編集、参照1枚、キャッシュなし、条件C | 677.4秒 |
| Qwen-Image-Edit 2511(7月、8ステップの蒸留版、ComfyUI) | 約5分 |
参照を2枚にすると、参照のトークンが増える分、実計算1回が約17秒から約19秒に増えた。
関連記事
Qwen-Image 2.1を試した記事。
- Qwen-Image 2.1の早期アクセス版で、効かなかった構図指定とオリキャラの描き分けを試した ModelScope Studioの早期アクセス版で、構図指定10種と4人バンド、かなちゃんの向き・服・ポーズの編集を試した
- Qwen-Image 2.1のローカル版をAnimaと比べた 公開された重みをM1 Max 64GBで動かし、Studioと同じ俯瞰指定と、Anima・WAI-Anima・WAI-Illustriousと同じプロンプトで比べた
- Qwen-Image 2.1をM1 MaxでTaylorSeerキャッシュにかけたら1枚10分が3分半になった DiffusersのTaylorSeerキャッシュを入れて、M1 Maxでの1枚約10分を約3分半にした