FaMirror Project

報告的なこと、技術的なこと

ブラウザでWebカメラの映像を画像化【javasript】

概要

html5で追加された「WebRTC」の機能を使えば、ブラウザでWebカメラの映像を取得することができます。

今回はその映像を画像化します。

html5の「video」領域にWebカメラの映像を映し、それを「canvas」領域にコピーし、さらにそれを「img」領域に書き出します。

Webカメラの映像を映す

WebRTCの「getUserMedia」というメソッドによってカメラにアクセスします。

現在はChromeFirefoxOperaなどが対応しており、IESafariは未対応となっています。

以下のページから詳しい対応状況を見ることができます。
Can I use... Support tables for HTML5, CSS3, etc

また、最近localhost以外のhttp通信では、カメラが起動しなくなりました。

localhost以外でこのメソッドを使用する場合は、https通信をご使用ください。

まずは「video」領域にWebカメラの映像を映します。

以下のソースでWebカメラの映像をブラウザに映すことができます。

HTML(index.html)

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<link rel="stylesheet" href="style.css">
	<title>Webカメラの映像を画像化</title>
</head>
<body>
	<h2>Video</h2>
	<video id="camera" autoplay></video>
	<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
	<script type="text/javascript" src="./script.js"></script>
</body>
</html>

CSS(style.css)

@charset "UTF-8";

#camera {
	width: 400px;
	height: 300px;
}

JavaScript(script.js)

$(function() {
	//videoタグを取得
	var video = document.getElementById('camera');
	//カメラが起動できたかのフラグ
	var localMediaStream = null;
	//カメラ使えるかチェック
	var hasGetUserMedia = function() {
		return (navigator.getUserMedia || navigator.webkitGetUserMedia ||
			navigator.mozGetUserMedia || navigator.msGetUserMedia);
	};

	//エラー
	var onFailSoHard = function(e) {
		console.log('エラー!', e);
	};

	if(!hasGetUserMedia()) {
		alert("未対応ブラウザです。");
	} else {
		window.URL = window.URL || window.webkitURL;
		navigator.getUserMedia  = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
		navigator.getUserMedia({video: true}, function(stream) {
			video.src = window.URL.createObjectURL(stream);
			localMediaStream = stream;
		}, onFailSoHard);
	}
});

カメラの映像を反転させて鏡のように使いたい場合は、cssに以下の記述を追加してください。

CSS(style.css)追加

#camera {
	transform: rotateY(180deg);
}

Webカメラの映像を画像化する

手順としては先ほど「video」領域に映した映像を「canvas」領域にコピーし、「img」領域に書き出すという形になります。

htmlの「video」タグの下に以下の記述を入れてください。

startボタンは画像化開始のボタンになります。

HTML(index.html)追加

	<button id="start">start</button>
	<h2>Canvas</h2>
	<canvas id="canvas"></canvas>
	<h2>Img</h2>
	<img id="img">

cssにも以下の記述を追加してください。

canvasのサイズ指定をcssで行うと、canvas内に描画した画像が引き伸ばされ、画像が歪んでしまうので、ここでは指定しません。

CSS(style.css)追加

#img {
	width: 400px;
	height: 300px;
}

画像化のコードは以下のようになります。

JavaScript(script.js)追加

	$("#start").click(function() {
		if (localMediaStream) {
			var canvas = document.getElementById('canvas');
			//canvasの描画モードを2sに
			var ctx = canvas.getContext('2d');
			var img = document.getElementById('img');

			//videoの縦幅横幅を取得
			var w = video.offsetWidth;
			var h = video.offsetHeight;

			//同じサイズをcanvasに指定
			canvas.setAttribute("width", w);
			canvas.setAttribute("height", h);

			//canvasにコピー
			ctx.drawImage(video, 0, 0, w, h);
			//imgにpng形式で書き出し
			img.src = canvas.toDataURL('image/png');
		}
	});

このようにjavascriptcanvasのサイズを指定することで、videoのサイズを変更した場合でも画像をゆがませずに書き出すことができます。

videoのサイズをパーセントで指定しても問題ありません。

コード

HTML(index.html)

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<link rel="stylesheet" href="style.css">
	<title>Webカメラの映像を画像化</title>
</head>
<body>
	<h2>Video</h2>
	<video id="camera" autoplay></video>
	<button id="start">start</button>
	<h2>Canvas</h2>
	<canvas id="canvas"></canvas>
	<h2>Img</h2>
	<img id="img">
	<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
	<script type="text/javascript" src="./script.js"></script>
</body>
</html>

CSS(style.css)

@charset "UTF-8";

#camera {
	width: 400px;
	height: 300px;
}

#img {
	width: 400px;
	height: 300px;
}

JavaScript(script.js)

$(function() {
	//videoタグを取得
	var video = document.getElementById('camera');
	//カメラが起動できたかのフラグ
	var localMediaStream = null;
	//カメラ使えるかチェック
	var hasGetUserMedia = function() {
		return (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
	};

	//エラー
	var onFailSoHard = function(e) {
		console.log('エラー!', e);
	};

	if(!hasGetUserMedia()) {
		alert("未対応ブラウザです。");
	} else {
		window.URL = window.URL || window.webkitURL;
		navigator.getUserMedia  = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
		navigator.getUserMedia({video: true}, function(stream) {
			video.src = window.URL.createObjectURL(stream);
			localMediaStream = stream;
		}, onFailSoHard);
	}

	$("#start").click(function() {
		if (localMediaStream) {
			var canvas = document.getElementById('canvas');
			//canvasの描画モードを2sに
			var ctx = canvas.getContext('2d');
			var img = document.getElementById('img');

			//videoの縦幅横幅を取得
			var w = video.offsetWidth;
			var h = video.offsetHeight;

			//同じサイズをcanvasに指定
			canvas.setAttribute("width", w);
			canvas.setAttribute("height", h);

			//canvasにコピー
			ctx.drawImage(video, 0, 0, w, h);
			//imgにpng形式で書き出し
			img.src = canvas.toDataURL('image/png');
		}
	});
});