0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ブラウザで画像の超解像(AI高画質化)を動かす:タイル分割の継ぎ目対策とWebGPU/WASMのメモリ管理メモ

0
Posted at

Real-ESRGAN系の超解像モデルを onnxruntime-web で動かし、画像を2倍・4倍に拡大する機能を作りました。デモは数時間で動きましたが、実際のユーザー画像で安定させるまでに時間がかかったポイントをまとめます。

なぜタイル分割が必要か

4倍拡大モデルに2000×1500の画像をそのまま入れると、出力は8000×6000、Float32のRGBテンソルで約576MBです。中間層はさらに大きく、GPUメモリが足りずにクラッシュします。

そこで入力を例えば128×128のタイルに分割し、1枚ずつ推論して結果を貼り合わせます。

継ぎ目(シーム)対策

単純に分割すると、タイル境界に格子状の線が出ます。畳み込みの受容野がタイルの外側を見られないためです。

対策は**オーバーラップ(パディング)**です。

const TILE = 128, PAD = 16;
for (let y = 0; y < h; y += TILE) {
  for (let x = 0; x < w; x += TILE) {
    const sx = Math.max(0, x - PAD), sy = Math.max(0, y - PAD);
    const ex = Math.min(w, x + TILE + PAD), ey = Math.min(h, y + TILE + PAD);
    const out = await infer(crop(img, sx, sy, ex, ey));
    // 出力からパディング分(×scale)を切り落として中央部分だけ貼る
    paste(out, (x - sx) * S, (y - sy) * S, TILE * S, TILE * S, x * S, y * S);
  }
}

PADは8pxでも目立たなくなりますが、空や肌のようななだらかな領域では16px以上が安全でした。

WebGPUとWASMの使い分け

  • WebGPUが使える環境では、タイル1枚あたり数百ms程度。
  • WASMフォールバックでは数秒かかることもあるため、タイルを小さくして進捗を細かく表示します。
  • requestAdapter() が null を返す環境(ブロックリスト対象のGPUなど)は意外と多いので、必ずフォールバックを用意します。

メモリリーク対策

onnxruntime-web のテンソルは、使い終わったら明示的に dispose() しないとGPUメモリが解放されないことがあります。ループ内で毎回破棄しないと、50タイル目あたりで落ちる、という現象に悩まされました。

また、出力は巨大なCanvasに直接書かず、OffscreenCanvas をWorkerで扱うとメインスレッドが固まりません。ブラウザごとにCanvasの最大サイズ制限(面積や一辺の長さ)があるので、4倍拡大後のサイズが制限を超えないかも事前に確認します。

期待値の調整

超解像は「なかった情報を生成する」処理です。文字や顔は、それらしく見えても元と違う形になることがあります。証明写真や書類の文字を拡大する用途では、その旨をUIに書いておくべきだと考えています。

参考

挙動の比較には、同じくブラウザ内で処理するNibboの画像高画質化ツールを使いました。モデルの初回ダウンロード後は、画像をアップロードせずに2倍・4倍を試せます。

— Vitalii

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?