WebRTCのgetUserMediaで取得した映像をいじってみた
WebRTCのgetUserMediaで取得した自分のカメラ映像の画素を取得し、いろいろいじってみた。
テンプレート
まず、いろいろいじるためのテンプレートを載せる。
template.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script type="text/javascript" src="template.js"></script> <title>Title</title> </head> <body> <video id="video"></video> <canvas id="display_canvas"></canvas> </body> </html>
template.js
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia ; window.URL = window.URL || window.webkitURL ; function initialize() { navigator.getUserMedia( {audio: true, video: true}, function(stream) { var video = document.getElementById('video'); video.src = URL.createObjectURL(stream); video.play(); renderStart(); }, function(error) { console.error(error); } ); } function renderStart() { var video = document.getElementById('video'); var buffer = document.createElement('canvas'); var display = document.getElementById('display_canvas'); var bufferContext = buffer.getContext('2d'); var displayContext = display.getContext('2d'); var render = function() { requestAnimationFrame(render); var width = video.videoWidth; var height = video.videoHeight; if (width == 0 || height == 0) {return;} buffer.width = display.width = width; buffer.height = display.height = height; bufferContext.drawImage(video, 0, 0); var src = bufferContext.getImageData(0, 0, width, height); // カメラ画像のデータ var dest = bufferContext.createImageData(buffer.width, buffer.height); // 空のデータ(サイズはカメラ画像と一緒) /* ############################## ここで処理を行う ############################## */ displayContext.putImageData(dest, 0, 0); }; render(); } window.addEventListener('load', initialize);
src.data は、
src.data = { [画素(0)のR,G,B,alpha], [画素(1)のR,G,B,alpha], ... , [画素(width*height-1)のR,G,B,alpha] }
というふうにカメラ画像のRGB値とalpha値が入った長さ width*height*4 の配列になっている。(見やすくするために [ 画素(1)のR,G,B,alpha ] と表記しているが、実際は一次元配列。)
この元データを使って、dest.data に加工後の画素値を入れていく。
色調反転
まずは、単純に色調反転をしてみる。
ソースコード(処理と、その前後だけ)
var src = bufferContext.getImageData(0, 0, width, height); // カメラ画像のデータ var dest = bufferContext.createImageData(buffer.width, buffer.height); // 空のデータ(サイズはカメラ画像と一緒) for (var i = 0; i < dest.data.length; i += 4) { dest.data[i + 0] = 255 - src.data[i + 0]; // Red dest.data[i + 1] = 255 - src.data[i + 1]; // Green dest.data[i + 2] = 255 - src.data[i + 2]; // Blue dest.data[i + 3] = 255; // Alpha } displayContext.putImageData(dest, 0, 0);
こんな感じになる。不健康ですね。
エッジ検出
http://www.html5.jp/canvas/ref/method/getImageData.html
にエッジ検出のサンプルがあったので、使ってみた。
ソースコード(処理と、その前後だけ)
var src = bufferContext.getImageData(0, 0, width, height); // カメラ画像のデータ var dest = bufferContext.createImageData(buffer.width, buffer.height); // 空のデータ(サイズはカメラ画像と一緒) for (var y = 1; y < height-1; y += 1) { for (var x = 1; x < width-1; x += 1) { for (var c = 0; c < 3; c += 1) { var i = (y*width + x)*4 + c; dest.data[i] = 127 + -src.data[i - width*4 - 4] - src.data[i - width*4] - src.data[i - width*4 + 4] + -src.data[i - 4] + 8*src.data[i] - src.data[i + 4] + -src.data[i + width*4 - 4] - src.data[i + width*4] - src.data[i + width*4 + 4]; } dest.data[(y*width + x)*4 + 3] = 255; // Alpha } } displayContext.putImageData(dest, 0, 0);
こんな感じになる。動くと楽しい。
おまけ
RGB値が 128 より小さい場合は 0 に、128 以上の場合は 255 に、という処理をしてみた。
ソースコード(処理と、その前後だけ)
var src = bufferContext.getImageData(0, 0, width, height); // カメラ画像のデータ var dest = bufferContext.createImageData(buffer.width, buffer.height); // 空のデータ(サイズはカメラ画像と一緒) for (var i = 0; i < dest.data.length; i += 4) { for (var c = 0; c < 3; c ++) { if (src.data[i+c] < 128) { dest.data[i+c] = 0; } else { dest.data[i+c] = 255; } } dest.data[i+3] = 255; // Alpha } displayContext.putImageData(dest, 0, 0);
こんな感じになる。なんかかっこいい。
感想
カメラの画素を取得していじるのはOpenCVでやったことがあるが、その時は結構面倒なイメージだった。しかし、今回はJavaScriptのWebAPIを使うことで非常に楽に出来たので驚いた。