本文へスキップ

TypeScriptとCanvasで画像処理100本ノックに挑戦した

6

概要

画像処理100本ノックを、TypeScriptと Canvas APIで実装しました。画像処理ライブラリを使わず、Q.1〜Q.100をブラウザ上で実行できます。

この記事は2019年に、JavaScriptとVueで40問まで実装した時点の記録として公開しました。 2026年に100問すべての実装とReact・TypeScriptへの移行が完了したため、現在の構成と アルゴリズム別の解説記事一覧へ更新しました。

実装の特徴

Canvas 2D ContextのgetImageDataでRGBAの画素配列を取得し、各アルゴリズムを適用した結果を putImageDataでCanvasへ戻します。

const src = context.getImageData(0, 0, width, height);
const dst = context.createImageData(width, height);

for (let i = 0; i < src.data.length; i += 4) {
  // src.data[i + 0] = R
  // src.data[i + 1] = G
  // src.data[i + 2] = B
  // src.data[i + 3] = A
}

context.putImageData(dst, 0, 0);

OpenCVなどの画像処理ライブラリは使用していません。行列演算、ヒストグラム描画、HOG、 IoU、NMSもプロジェクト内で実装しています。

基礎的な画素操作

Q.1〜8は、個別の既存記事を現在のTypeScript実装へ合わせて更新しています。

問題 解説
Q.1 チャンネル入れ替え 画像のRGBチャンネルを入れ替える
Q.2 グレースケール 画像をグレースケールに変換する
Q.3 二値化 固定閾値で画像を二値化する
Q.4 大津の二値化 大津の方法で閾値を自動決定する
Q.5 HSV変換 RGBとHSVを相互変換する
Q.6 減色 固定した代表値へ減色する
Q.7、Q.8 プーリング 平均・Maxプーリングを実装する

アルゴリズム別の解説

問題番号を10問ずつ区切るのではなく、処理の目的とアルゴリズムの系統で分類しています。

画素値・空間・座標を扱う処理

分類 対象 解説
空間フィルタ Q.9〜19 平滑化とエッジ検出
ヒストグラム・濃度変換 Q.20〜24 正規化、平坦化、ガンマ補正
補間・幾何変換 Q.25〜31 画像補間とアフィン変換
周波数解析 Q.32〜35 2次元フーリエ変換と周波数フィルタ
画像圧縮 Q.36〜40 DCT、量子化、YCbCrとJPEG

形状・領域・特徴を扱う処理

分類 対象 解説
エッジから直線を検出 Q.41〜46 CannyとHough変換
形態学的変換 Q.47〜55 膨張・収縮とモルフォロジー処理
照合・領域分割 Q.56〜60 テンプレートマッチングとラベリング
二値図形の骨格 Q.61〜65 連結数と細線化
勾配特徴 Q.66〜69 HOG特徴量
色による領域抽出 Q.70〜72 HSVカラートラッキングとマスク
マルチスケール処理 Q.73〜76 画像ピラミッドと顕著性マップ
方向・周波数特徴 Q.77〜80 ガボールフィルタ
特徴点 Q.81〜83 Hessian・Harrisコーナー検出

認識・学習・検出

分類 対象 解説
教師あり画像分類 Q.84〜87 色ヒストグラムとk-NN
教師なし学習・減色 Q.88〜92 k-meansクラスタリング
物体検出 Q.93〜100 HOG、ニューラルネットワーク、NMSと評価

アルゴリズムのつながり

100問は独立したサンプルの集合ではなく、前半で作った処理を後半で再利用する構成です。

グレースケール・平滑化
  ├─ 勾配 → Canny → Hough直線検出
  ├─ 勾配 → HOG ─┐
  └─ 二値化 → 形態学・細線化

補間 → 画像ピラミッド

色ヒストグラム → k-NN / k-means

IoU + HOG + NN + NMS → 物体検出

たとえばHOGはQ.66〜69で作成し、Q.96以降の顔・非顔分類と物体検出で再利用します。 IoUは学習用クロップのラベル付け、NMS、最終評価でそれぞれ異なる役割を持ちます。

ローカルで動かす

git clone https://github.com/s-yoshiki/Gasyori100knockJS.git
cd Gasyori100knockJS
pnpm install
pnpm dev

型検査、Lint、フォーマット検査、テストは次のコマンドでまとめて実行できます。

pnpm check

まとめ

ブラウザで結果を確認しながら、画素操作、周波数解析、特徴抽出、分類、物体検出までを 段階的に追えるようにしました。解説記事は問題番号の区切りではなく、同じ考え方や共通処理を 持つアルゴリズム単位でまとめています。

学習するときの進め方

最初から100問を順番に消化するより、次の単位で結果を比較すると理解しやすくなります。

  1. 同じ入力に対してRGB/BGR、HSV、グレースケールの値を確認する
  2. 畳み込みフィルターのkernelと境界処理を変える
  3. 二値化からラベリング、輪郭、特徴量へ進む
  4. 学習データと評価データを分離して分類結果を見る
  5. IoU、Precision/Recall、NMSの閾値を変えて検出結果を比較する

ブラウザ実装ではCanvasの画素配列がRGBA順である一方、元のOpenCV教材はBGRを前提にする場合があります。アルゴリズムを移植するときは、チャンネル順、値域、丸め、画像端の扱いをテストで固定すると差分を追いやすくなります。

実装を利用する際の注意

これは学習用の素朴な実装です。実サービスで大きな画像を処理する場合は、メインスレッドを塞がないようWeb Worker、OffscreenCanvas、WASM/OpenCV.js、GPU処理などを検討してください。また、ユーザーが指定した画像はサイズ・MIME typeを検証し、Object URLを作った場合は不要になった時点で解放します。

おすすめの記事

最新の記事

著者について

404

s-yoshiki

ただの備忘録です。

※外部送信に関する公表事項