1. ホーム
  2. Web制作
  3. html5

ビデオグリーンスクリーンキーイングのキャンバスピクセルポイントマニピュレーション

2022-02-01 22:31:33

 今回は、ビデオグリーンスクリーンキーイングのキャンバスピクセルポイント操作について紹介し、以下のように共有します。

使用方法

context.putImageData(imgData, x, y, dX, dY, dWidth, dHeight);

<テーブル パラメータ 説明 imgData キャンバス上に戻すImageDataオブジェクトを指定します。 x ImageData オブジェクトの左上隅の x 座標をピクセル単位で指定します。 y ImageData オブジェクトの左上隅の y 座標をピクセル単位で指定します。 dX オプション。キャンバス上の画像を配置する水平方向の値 (x) をピクセル数で指定します。 dY オプション。キャンバス上の画像を配置する水平方向の値 (y)をピクセル単位で指定します。 dWidth オプション。キャンバス上に画像を描画するために使用する幅。 dHeight オプション。キャンバス上に画像を描画するために使用する高さ。

以下の栗は、いくつかの簡単なフィルター効果を単純に実装したもので、ここで参照される特定のアルゴリズムは、デジタル画像処理を勉強した学生にはよりよく理解されるはずです。

デモ

この栗は純粋にデモンストレーションのためのものなので、データではなく効果を重視するのであれば、CSS3のfilterプロパティで効率よく簡単に行うことができます。

コードの一部

import imgUrl from '. /component/sample.jpg';

export default {
	data () {
		return {
			imgUrl: imgUrl
		}
	},

	methods: {
		onOperate1 () {
			this.ctx.putImageData(this.onCompute1(), 0, 0);
		},

		onOperate2 () {
			this.ctx.putImageData(this.onCompute2(), 0, 0);
		},

		...

		onCancel () {
			this.reload();
		},

		onCompute1 () {
			let data = this.frameData.data;

	        for (let i = 0; i < this.imgDataLength; i += 4) {
	          	let r = data[i + 0],
	          		g = data[i + 1],
	          		b = data[i + 2];
	          	
          		data[i + 0] = 255 - r;
          		data[i + 1] = 255 - g;
          		data[i + 2] = 255 - b;
	        }

	        return this.frameData;
		},

		onCompute2 () {
			let data = this.frameData.data;

	        for (let i = 0; i < this.imgDataLength; i += 4) {
	          	data[i] = Math.abs(data[i + 1] - data[i + 2] + data[i + 1] + data[i]) * data[i] / 256;  
            	data[i + 1] = Math.abs(data[i + 2] - data[i + 1] + data[i + 2] + data[i]) * data[i] / 256;  
            	data[i + 2] = Math.abs(data[i + 2] - data[i + 1] + data[i + 2] + data[i]) * data[i + 1] / 256;
	        }

	        return this.frameData;
		},

		...
	},

	mounted () {
        this.canvas = this.$refs['canvas'];
        this.ctx = this.canvas.getContext('2d');

        this.reload();
	}
}

先週、クラスメートと一緒に溧陽の天目湖にある南山竹海へ行き、景勝地で騙されて写真を撮りましたが、これがその写真です--。

その後、写真をキーにしたことでサークルの仲間に荒らされました。実はこれ、グリーンスクリーンの前に立って撮ったものなんです :joy: .

PSのマジックワンドツールを使うと、画像内の似たようなピクセルを一定の許容範囲で選択・消去できるので、被写体が背景と大きく異なる場合、つまりピクセル値の差が大きいほど、ワンクリックで簡単にキーイング効果を得ることができるのです。

Canvas はビデオフレームを扱うことができ、原理は同じです -- 各ビデオフレーム内のグリーンスクリーンのピクセルブロックの透明度を 0 に設定するだけです。

デモ

コードの一部

import videoUrl from '. /component/video.ogv';
import imgUrl from '. /component/sample.jpg';

const TOLERANCE = 5;
export default {
	data () {
		return {
			videoUrl: videoUrl,
			imgUrl: imgUrl
		}
	},

	methods: {
		draw () {
			if (this.video.pused || this.video.ended) {
	          	return;
	        }
			this.ctx.drawImage(this.video, 0, 0, this.width, this.height);
			this.ctx.putImageData(this.cutOut(), 0, 0);
		},

		cutOut () {
			let frameData = this.ctx.getImageData(0, 0, this.width, this.height),
				len = frameData.data.length / 4;

	        for (let i = 0; i < len; i++) {
	          	let r = frameData.data[i * 4 + 0],
	          		g = frameData.data[i * 4 + 1],
	          		b = frameData.data[i * 4 + 2];
	          	if (r - 100 >= TOLERANCE 
	          	 && g - 100 >= TOLERANCE 
	          	 && b - 43 <= TOLERANCE) {
		            frameData.data[i * 4 + 3] = 0;
	          	}
	        }
	        return frameData;
		}
	},

	mounted () {
		this.video = this.$refs['video'];
        this.canvas = this.$refs['canvas'];
        this.ctx = this.canvas.getContext('2d');
        this.timer = null;

        this.video.addEventListener('play', () => {
            this.width = this.video.videoWidth;
            this.height = this.video.videoHeight;

            this.timer && clearInterval(this.timer);
            this.timer = setInterval(() => {
            	this.draw();
            }, 50);
        }, false);
	}
}

参考文献

キャンバスを使った動画の操作

 canvasによるピクセル操作

キャンバスと画像とピクセル