AIで生成した不均一なスプライトシートを切り分ける方法

画像モデルに4行4列の歩行サイクルを頼むと、大きなPNGが1枚返ってきました。グリッドに見えますが、実際は違います。16個の均等矩形に切ると、あちこちで頭や剣先が切れ、半分のフレームが中央から外れます。理由と、それでも使えるフレームを得る方法を説明します。

AIスプライトシートが完全なグリッドにならない理由

従来のスプライトシートはツールで作られます。制作者が固定のセルサイズでフレームを描き、書き出しツールが正確なピクセルオフセットに配置します。すべてのセルは同じで、各スプライトは既知の枠内に収まり、切り分けは計算だけで済みます。

画像生成ツールは、そのようには動作しません。DALL·E、Midjourney、Stable Diffusionなどの拡散モデルは、1枚の連続した画像を生成します。「歩く騎士のスプライトシート、4x4グリッド」と依頼すると、モデルが作るものは のように見える スプライトシートを何千枚も見てきたからです。セル境界を計算せず、グリッドの見た目を模倣しています。生成処理には、3行目が正確に384ピクセル下から始まることを強制するものはありません。

実用上の結果は一貫しています:

  • ずれていく間隔。 スプライト間の隙間は数ピクセルから数十ピクセルまで異なります。ずれは通常、左から右、上から下へ積み上がり、右下のフレームが最も悪くなります。
  • 不揃いなスプライトのサイズ。 歩行途中のキャラクターは、静止しているときより幅が広くなります。モデルは各ポーズを均一な枠に収まるように縮尺調整するのではなく、見た目が自然なサイズで描きます。
  • 中央から外れた内容。 セルがおおむね均等でも、内部のスプライトは中央にないことが多いため、正しいグリッドで切っても、再生時に揺れるフレームになります。
  • フレームの欠落または結合。 4x4の配置なのにスプライトが15個だったり、2つのポーズが重なって1つの塊に見えたりすることがあります。
  • 奇数のキャンバス寸法。 1024x1024の出力を3列で割ると、341.33ピクセルになります。どこかで丸めが必要になり、丸め誤差は積み重なります。
青い鎧の騎士を生成したスプライトシート。16個のポーズのサイズと位置が不揃いで、均等なグリッドではなく、間の隙間の幅もばらばら
典型的な生成シートです。一見すると4x4の配置ですが、ポーズのサイズが異なり、間の隙間も不均一で、いくつかのスプライトは想定するセルの中心からずれています。1つのフレームはキャンバスの端からはみ出しています。

固定グリッド分割が失敗する理由

固定グリッドでの切り分けには、画像が同じサイズのセルの格子であるという1つの前提があります。幅を列数、高さを行数で割って切ります。その前提が成り立てば、完璧で高速です。成り立たない場合、誤差は無視できるランダムなノイズではありません。すべての切断位置が誤り、アニメーションで最も重要な形で、その誤りが目に見えます。

フレームの上部が4ピクセル切れているのは、単なる見た目の問題ではありません。ゲームエンジンではフレームが同じ基準点で描画されるため、2枚目のフレームの内容が1枚目より4ピクセル下にあると、再生中にスプライトが目に見えて上下に跳ねます。プレイヤーは説明できなくても、これを不具合として受け取ります。後から1フレームずつ手作業で直すほうが、最初から正しく切り分けるより時間がかかります。

左右比較:左は等間隔の赤いグリッド線が複数のキャラクターを横切り、右は緑の枠が各キャラクターの実際の輪郭を囲んでいる
同じシートを2通りで分割。固定グリッド線は計算上の位置に置かれ、頭や武器を切ってしまう。内容ベースの検出は各スプライトの実際の範囲を先に見つけ、その周囲で切る。
目安: 画像生成モデルのシートは、確認するまで不均一と考えてください。Aseprite、TexturePacker、スプライトシート出力ツールのシートなら、固定グリッドがほぼ確実に正しく、それを使うべきです。

対策:座標ではなく内容で切る

グリッドでスプライトの位置が分からなくても、ピクセルなら分かります。透明背景のシートでは、すべてのピクセルはスプライトの一部(アルファが0より大きい)か、背景の一部(アルファが0)です。この1つの区別だけで、配置を事前に知らなくてもスプライトを見つけられます。

内容に基づく検出の仕組み

  1. 背景が透明か確認してください。 隅のピクセルを調べてください。完全に透明なら自動検出の候補です。白や単色なら、先に背景を削除する必要があります。
  2. 空の行と列を見つけてください。 画像を走査し、不透明ピクセルがまったくない行と列を記録します。その空の帯が、どこにあってもスプライト間の隙間です。
  3. 各隙間の中央で切ってください。 隙間は線ではなく幅のある領域です。その中央で切ると、両隣のスプライトに最大限の余裕ができ、アンチエイリアスによるはみ出した1〜2ピクセルにも対応できます。
  4. 各部分を自身の外接矩形までトリミングします。 パーツを分離したら、不透明ピクセルを含む最小の矩形へ縮めます。セルが不揃いに見えた不均一な余白を取り除きます。
  5. 結果を確認し、繰り返してください。 最初の処理では、接触しているため1つのパーツに2つのスプライトが残ったり、隣のパーツに比べて空白が大きすぎたりする問題がよく残ります。出力を再解析し、さらに分割または再トリミングすることで、その大半を検出できます。

これを行うのが Magic Slice 当ツールのタブ スプライトシートスライサー 透明背景を検出し、アルファから境界を見つけ、最大3回の再調整で各分割結果の余分な余白や複数スプライトを調べ、必要なら再分割します。低・中・高の感度で検出の積極性を制御します。ほぼ接触する場合は上げ、浮いた盾や魔法効果など離れた部品を持つ1スプライトが分断される場合は下げます。

16体のキャラクターのスプライトシートをスライサーに読み込み、検出した境界線を重ねたもの。線は等間隔ではなくキャラクター間の透明な隙間に置かれるため、列ごとに幅が異なる

シート上で検出された境界

分割結果:sprite_1からsprite_16までの16個の独立したスプライトファイル。それぞれ1体のキャラクターを表示し、204x257、181x260などファイルごとのピクセル寸法が異なる

それぞれトリミングされた16ファイル

境界は均等なグリッドではなく、キャラクター間の空白帯に沿うため、列幅は不均等になります。右側の出力ファイル下にある寸法を確認してください。数十ピクセルずつ異なりますが、それこそがトリミング処理の目的であり、後の余白追加が重要になる理由です。

シートが単色背景の場合

内容に基づく検出には透明度が必要です。シートの背景が均一な白、黒、マゼンタなら、先に背景削除ツールを使ってください。当サイトのツールはこちらです /remove-bg 四隅のピクセルを採取し、その色に十分近い全ピクセルを消して透明PNGを書き出します。これを行うのは 前に 分割前であり、後ではありません。シート全体で1回の背景削除は1操作ですが、個別16フレームでは16回の不統一な結果の機会になります。

スプライト内に現れる背景に注意してください。 キャラクターが白いシャツを着ていて背景も白なら、隅に基づく削除はシャツに穴を開けます。その場合は、被写体のどこにもない背景色を生成ツールに指定してください。鮮やかなマゼンタやネオングリーンが昔から選ばれるのは、まさにこのためです。

手動のグリッド線:常に使える代替手段

自動検出が失敗するシートもあり、どのような場合か知っておく価値があります。重なったり接触したりするスプライトは、空の帯を走査しても分離できません。空の帯がないためです。ドロップシャドウや光彩がキャンバス全体を覆うシートには、完全に透明な行がありません。1体のキャラクターが離れたパーツでできているシートは、分割されすぎます。

これらの場合はすべて、ご自身で線をドラッグしてください。この 手動・プリセット タブは2x2〜6x6のプリセット、または最大20x20の独自の行・列数から始め、各グリッド線を実際の位置へドラッグできます。手順は:

  1. 間隔が違っていても、16フレームなら4x4など、意図した配置に最も近いプリセットを選んでください。
  2. 各縦線を左右の隙間へドラッグしてください。左から右へ進めると、すでに直した線を基準に調整できます。
  3. 水平線も、上から下へ同じように調整してください。
  4. 最も窮屈なフレーム、通常は最も幅広いポーズを拡大し、分割線が横切らないことを確認します。
  5. 書き出します。PNGは透明度を保持し、スプライトに適しています。JPGとWebPも利用できますが、JPGはアルファチャンネルを完全に捨てます。

手動調整は遅そうに聞こえますが、そうではありません。16フレームのシートの内側の線は合計6本なので、16回の切り抜きではなく6回のドラッグで済みます。画像エディターでシートを開き、各フレームを選択するのに比べ、はるかに速くなります。

ゲームエンジン用にフレームを準備

個別PNGができたら、エンジンへの方法は2つです。個別のフレームとして取り込むか、きれいで均一なシートに再配置します。どちらを使うかは、エンジンとプロジェクトによります。

Unity

個別のフレームでは、PNGをプロジェクトへ追加し、Texture Typeを次に設定します Sprite (2D and UI)、Sprite Modeを Single。Filter Modeを次に設定してください Point (no filter) Compressionを次に設定: None ピクセルアート向けです。32x32スプライトのバイリニアがぼけの原因です。Pixels Per Unitをグリッドに合わせ、全フレームを選んでGameObjectにドラッグするとUnityがAnimation Clipを自動生成します。

再配置したシートには、Sprite Modeの次の設定を使います Multiple Sprite Editorも使います。Grid By Cell Sizeは詰め直したシートが本当に均等な場合だけ動作します。それこそが再パッキングで得られ、元のAIシートにはなかったものです。

Godot

Godot 4で、次を追加します AnimatedSprite2D、新しいものを作成します SpriteFrames リソースで、次を使用: Add Frames from Sprite Sheet 均一なシートなら、または Add Frames from File(s) 個別PNGを直接読み込みます。シートインポーターは均等セルを期待するので、ここでは個別フレームが簡単です。ピクセルアートではフィルターをNearestにします。ノードごとのCanvasItem → Texture → Filter、または次で全体設定できます: rendering/textures/canvas_textures/default_texture_filter プロジェクト設定。

基準点と位置合わせ

省略すると、午後いっぱいデバッグすることになる手順です。全フレームを個々の外接矩形にトリミングした場合、寸法が異なり、エンジンはそれぞれ同じ原点で中央配置します。2枚目で腕を伸ばすキャラクターは、追加の幅で見た目の中心がずれ、後方へ滑るように見えます。

対策は、すべてのフレームに余白を足して共通サイズへ戻し、内容を一貫した位置に置くことです。通常は横方向を中央、縦方向を下端に合わせ、足の位置を固定します。最大のフレームから共通サイズを決め、扱いやすい数値に切り上げ、残りを透明な余白で埋めます。トリミング後に余白を足すのは堂々巡りに思えるかもしれませんが、違います。トリミングは生成モデルの任意の余白を捨て、余白追加は自分で管理する余白を付け直すのです。

トラブルシューティング

検出されたパーツが多すぎる

感度が高すぎるか、スプライトに離れた要素があります。感度を下げて、スプライト内の小さな透明な隙間がフレーム間の隙間として扱われないようにしてください。改善しない場合は手動の分割線に切り替えます。キャラクターが離れた物を持っている場合、アルファ走査では常に2つのスプライトに見えます。

検出されたパーツが少なすぎる

スプライトが接触しているか、薄い光が隙間をつないでいます。まず感度を上げてください。実際に重なっているなら、自動処理では分離できません。フレーム間に明確な空間を設けるよう指定してシートを再生成するか、手動で切り出してください。

20体のキャラクターが密集したスプライトシートに、検出した境界線を重ねたもの。キャラクター間の距離が近く、検出された水平線が少ないため、複数の行が1本の帯として扱われている

1. 感度が低すぎる — 検出された境界が少ない

検出不足の結果:20ファイルではなく8ファイルで、そのうち数枚は、1ファイル1体ではなく4体が結合した幅1557ピクセルの帯になっている

2. 20ファイルのはずが8ファイルしかない

書き出された1つの帯を拡大して見ると、4体のキャラクターが1つのファイルにつながっており、間に完全に透明な列がない

3. 原因:間に明確な空白の列がない

同じ帯を高い感度で再分割し、異なる4つの幅のキャラクターファイル4枚に分離した状態

4. 感度を上げた状態 — 4ファイル

検出不足の見た目と対策。シートのフレーム数よりファイルが少ないのが特徴です。走査で隣のキャラクターとの間に完全透明な列が見つからず、1つのスプライトとして扱われています。感度を上げると、より狭い隙間で切るようになります。

フレームに元の背景の薄い縁が残っている

背景削除後、半透明の端のピクセルに元の背景色が残っています。次のガイドをご覧ください 透明PNGと白い縁 対策はこちら。

エンジン内でアニメーションがぶれる

ほぼ常に、切り分けではなく基準点の問題です。すべてのフレームが同じ寸法と位置合わせの規則を持つことを確認し、エンジン内のスプライトのピボットを確認してください。

何もうまくいかず、シートが乱れている

再生成は低コストです。効果的な指示は、透明背景を明示、均等な間隔と一定のキャラクターサイズを指定、シートのフレーム数を減らす(3x3は6x6より使える可能性が高い)、便利さより動きが重要ならポーズを個別生成することです。

よくある質問

白背景のスプライトシートを自動で切り分けられますか?

読むアルファチャンネルがないため、アルファに基づく検出では直接できません。先に背景を消して透明PNGを作り、切り分けます。アルファでなく単色を使う方法もありますが、被写体と背景が同じ色を持つと、はるかに不安定になります。

ブラウザーで切り分けると画質は落ちますか?

PNGやWebPへの書き出しなら、落ちません。この用途ではどちらも可逆で、アルファチャンネルを保ちます。JPGは非可逆でアルファがないため、ピクセルを再圧縮し、透明部分を単色に置き換えます。スプライトは常にPNGで書き出してください。

スライサーを使うと、画像はどこかへアップロードされますか?

いいえ。すべてCanvas APIでブラウザー内処理します。端末からcanvasへ読み、そこで切り分け、ダウンロードとして書き出します。サーバーへの送信はなく、ページを読み込んだ後はオフラインでも動作します。

生成ツールには何フレームを依頼すべきですか?

思っているより少ない数です。セル数が増えると各スプライトに割かれるモデルの注意とピクセル領域が減るため、品質は急速に低下します。1024x1024の3x3や4x4のシートなら、1フレーム約256〜340ピクセルで、使えるだけの細部があります。同じ解像度の6x6では、1フレーム約170ピクセルになり、ポーズ同士がぼやけて混ざりがちです。

自分のシートで試す

スプライトシートスライサーを開き、シートをドロップしてMagic Sliceタブから始めてください。自動検出が合わなければ「手動・プリセット」へ切り替え、線をドラッグします。すべてブラウザー内で動作します。

スプライトシートスライサーを開く