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?

More than 3 years have passed since last update.

canvasで画像比較したい

Posted at

canvasで画像比較したい

最近ffmpegを使って音をいじいじする機会がありました。
いろんなパターンで音を編集してみたのですが、音の変化を耳で感じるのに限界を感じ、視覚的に見る方法ないかなぁと思っていました。
そしたらffmpegには音の波形を画像で出す機能があるようで。

波形の画像を生成したは良いが、微妙な違いを確認するためには結局目を凝らすしかないという結果に。。
Rubyにはrmagickがありますが、javascriptでなんかできないかなぁと思いcanvasを使ってやってみることにしました。

どうやったか

概要

wave_1.pngwave_1.pngを用意し、canvasに順番にレンダリング。
レンダリングした情報を変数に格納。
画像を比較して差分がある箇所だけ色を付ける。

index.html
<body>
  <p>image1</p>
  <img id="image_1" src="wave_1.png" />
  <p>image2</p>
  <img id="image_2" src="wave_2.png" />
  <p>diff</p>
  <canvas id="my-canvas" width="480" height="270"></canvas>
  <script type="application/javascript" src="canvas.js"></script>
</body>

class WaveDiffChecker {
  load() {
    this.image1 = document.getElementById("image_1");
    this.image2 = document.getElementById("image_2");
    this.c1 = document.getElementById("my-canvas");
    this.ctx1 = this.c1.getContext("2d");

    this.width = this.image1.clientWidth;
    this.height = this.image1.clientHeight;

    this.checkWave();
  }

  checkWave() {
    this.ctx1.drawImage(this.image1, 0, 0, this.width, this.height);
    const frame1 = this.ctx1.getImageData(0, 0, this.width, this.height);
    this.ctx1.drawImage(this.image2, 0, 0, this.width, this.height);
    const frame2 = this.ctx1.getImageData(0, 0, this.width, this.height);
    
    const pixels = frame1.data.length / 4; // 同じ画像サイズなのでdotsは1つでOK

    for (let i = 0; i < pixels; i++) {
      const index = i * 4;
      const isSame = [0, 1, 2].every(value => {
        return frame1.data[index + value] === frame2.data[index + value];
      });
      frame1.data[index] = isSame ? 0 : 100; // Red値
      frame1.data[index + 3] = isSame ? 0 : 100; // Alpha値
    }
    this.ctx1.putImageData(frame1, 0, 0);
  }
}

const diffChecker = new WaveDiffChecker();
diffChecker.load();


スクリーンショット 2020-07-10 22.09.23.png

ポイント

this.ctx1.getImageData(0, 0, this.width, this.height)
getImageDataの返り値はimageData
であり、imageData.dataでUint8ClampedArray
にアクセスできます。
このArrayはRGBAの順で0から255のデータを持っています。

//1ピクセルの構成
frame1.data[0] //=> 0(Red)
frame1.data[1] //=> 255(Green)
frame2.data[2] //=> 100(Blue)
frame3.data[3] //=> 150(Alpha)

各ピクセルの要素を順に確認していき、RGBAのどこかに差分がある場合のみ色をつけています。

0
0
2

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?