0.はじめに
私は、ただの初心者です。ブラウザーで動かせる超解像のJSを見つけたのでCodepenで動作確認をしてみました。
一応、動くものができたのでQiitaに記事を書こうと思いましたが、超解像の知識ゼロなので、生成AIのPerplexity先生(無料版)に以下の質問をして記事を書いてもらいました。
どのくらい超解像かはこんな感じでした。
1.Perplexity先生(無料版)の記事
以下の青字部分がPerplexity先生(無料版)の記事になります。スニペットの引用と説明はうまくできず、スニペットは張替え、説明文は取り消し線で修正しました。
ブラウザで動く超解像処理:JavaScript/WebAssemblyを使った画像品質向上の実装
はじめに
画像の超解像(Super-Resolution)技術は、低解像度の画像から高品質な高解像度画像を生成する手法として注目されています。通常、この処理には高性能なハードウェアが必要ですが、最近のWeb技術の進歩により、ブラウザ上でもこの処理が可能になってきました。
本記事では、GitHub上のオープンソースプロジェクト super-resolution-js を利用して、ブラウザ上で動作する超解像処理の実装について解説します。また、実際に動作するCodePenのデモを作成し、その過程で行った最適化や制約について詳しく説明します。
超解像の仕組み
super-resolution-jsリポジトリは、ブラウザ上でJavaScript/WebAssemblyを使用して画像の超解像を実現するプロジェクトです。その仕組みは以下の通りです:
-
モデル: SwinIRと呼ばれる最先端の画像超解像モデルを使用しています。
-
ONNXフォーマット: SwinIRモデルはONNX (Open Neural Network Exchange) フォーマットに変換されています。
-
WebAssembly: ONNXモデルはWebAssembly (Wasm) を通じてブラウザ上で実行されます。
-
JavaScript インターフェース: JavaScriptを使用してユーザーインターフェースを構築し、画像の入力や処理の制御を行います。
-
処理フロー:
a. ユーザーが画像をアップロード
b. JavaScriptがONNXランタイムを使用してSwinIRモデルを読み込む
c. 入力画像がモデルに渡される
d. モデルが画像を処理し、高解像度版を生成
e. 結果がブラウザ上に表示される -
オンデバイス処理: すべての処理はユーザーのデバイス上で行われるため、プライバシーが保護され、サーバーへの依存も不要です。
実装と最適化
super-resolution-jsを使用して、実際に動作するデモをCodePen上に実装しました。以下のリンクから確認できます:
実装にあたり、以下の最適化と制約を設けました:
-
画像のマルチ選択の制限: 処理が重いため、アップロード時の画像のマルチ選択を無効にしました。
-
Save処理の簡略化: 元の実装にあったSave処理を、単純に複数画像のダウンロードに変更しました。
-
画像サイズチェックの導入: 処理時間を抑えるため、入力画像のサイズチェックを実装しました。
-
進捗表示の追加: 処理に時間がかかるため、動作状況がわかるようにアラートを追加しました。
画像サイズチェックの実装
画像サイズをチェックし、大きすぎる画像の処理を防ぐために以下のコードを追加しました:※コードは正しいものに張替えました
document.getElementById('fileInputEl').addEventListener('change',(e)=>{
const file = e.target.files[0];
if (file) {
const chkimg = new Image();
console.log('aaa1');
chkimg.onload = function() {
console.log('aaa2');
if (this.width > 200 || this.height > 200) {
alert('画像サイズが200×200ピクセルを超えています。\n( '+ this.width + 'x' + this.height +' )\n非常に時間がかかります');
} else {
console.log('画像サイズは適切です。');
}
};
chkimg.onerror = function() {
alert('画像の読み込みに失敗しました。');
};
chkimg.src = URL.createObjectURL(file);
}
})
このコードは、アップロードされた画像のサイズをチェックし、200x200ピクセルを超える場合はアラートを表示し てエラーを発生させ ます。
超解像処理の実行
超解像処理を実行する主要な部分は以下のようになっています:※コードは正しいものに張替えました
async function main() {
if(!fileInputEl.files[0] && !exampleImageBlob) return alert("Please select some images first.");
startBtn.disabled = true;
startBtn.innerHTML = "processing...";
let files = fileInputEl.files[0] ? fileInputEl.files : [exampleImageBlob];
let inputBlob;
for(let inputBlob of files) {
let {data, width, height} = await blobToLinearRGBArray(inputBlob);
const feeds = {'input': new ort.Tensor('float32', data, [1, 3, height, width])};
console.log("Running inference...");
let t = Date.now();
const results = await onnxSession.run(feeds);
console.log(`Finished in ${Date.now()-t}ms`);
const out = results["output"]; // greyscale data tensor
console.log(`results:`, out);
// out.data is of shape/form Channel-Red-Green-Blue
let blob = await CRGBArrayToBlob(out.data, {width:out.dims[3], height:out.dims[2]});
let blobUrl = URL.createObjectURL(blob);
let imgEl = document.createElement("img");
imgEl.dataset.name = inputBlob.name;
imgEl.src = blobUrl;
imgEl.className = 'outimg';
document.body.appendChild(imgEl);
}
alert('Super Resolution complete.');
startBtn.disabled = false;
startBtn.innerHTML = "start";
downloadBtn.disabled = false;
}
このコードでは、ONNXモデルを読み込み、入力画像をテンソルに変換し、モデルを実行して結果を取得します。処理の 開始と 完了時にアラートを表示して、ユーザーに進捗を知らせています。
処理時間に関する考察
超解像処理、特に大きな画像の処理には時間がかかります。その主な理由は以下の通りです:
-
モデルの複雑さ: SwinIRは高品質な結果を生成するために設計された複雑なモデルで、多くの計算を必要とします。
-
ブラウザ環境の制約: WebAssemblyを通じて実行されるため、ネイティブアプリケーションと比較して処理速度が遅くなります。
-
画像サイズと計算量の関係: 超解像処理の計算量は、入力画像のピクセル数に比例して増加します。
-
メモリ制約: ブラウザ環境では利用可能なメモリに制限があり、大きな画像の処理時に影響します。
-
WebAssemblyの最適化の限界: 現状のWebAssembly実装では、GPUアクセラレーションなどの高度な最適化技術の利用が制限されています。
WebAssemblyとネイティブコードの性能比較
WebAssemblyの性能はネイティブコードに近づいていますが、完全に同等というわけではありません:
- 多くのベンチマークテストでは、WebAssemblyの性能はネイティブコードの70%〜90%程度です。
- 言語やタスクの種類、最適化レベル、ブラウザの実装によって性能差が変わります。
- 計算集約型のタスクでは、WebAssemblyはJavaScriptよりも大幅に高速で、ネイティブコードに近い性能を示すことがあります。
- WebAssemblyモジュールの読み込みと初期化に時間がかかるため、短時間で終了するタスクではネイティブアプリケーションよりも遅くなる可能性があります。
まとめ
ブラウザ上で動作する超解像処理は、最新のWeb技術の可能性を示す興味深い例です。WebAssemblyとJavaScriptを組み合わせることで、従来はサーバーサイドでしか実現できなかった高度な画像処理をクライアントサイドで実行できるようになりました。
ただし、処理時間やリソース制約などの課題もあり、実用化にはさらなる最適化が必要です。今後、WebAssemblyの最適化やブラウザの性能向上により、これらの制約が緩和されることが期待されます。
参考リンク
2.おわりに
Perplexity先生(無料版)の記事生成は、完全ではありません。
もちろん、記事の内容も100%正しいとは私レベルでは言えません。
まぁまぁホントぽい気はしてますが…
しかし、かなりコードの引用を除いては、かなり優秀だと思いました。
有料版ならもっとすごいかも
以上