Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

javascriptでPC内蔵カメラで撮影した画像をサーバに送信

今回は、、、
 ・javascriptを用いて、PC内蔵カメラで写真撮影⇒サーバに送信
 ・nodejsでクライアントから送信されたデータを受信
の備忘録を書きたいと思います。
f:id:Elsammit:20200616213644p:plain

実は昔調べながら苦労して作ったことがあったのですが、忘れそうだったので備忘録として残したいと思い、書くことにしました!!
調べてもあまり出てこず、結構苦労した記憶があります。。。
f:id:Elsammit:20200602213323p:plain

画像をアップロードとかはいろんな人がやってるけど、内蔵カメラで取得したデータを、、、となると結構マイナーだもんね。。。
では初めて行きます!!



クライアントサイド

まずは、PC内蔵カメラの起動です。
html表示した時に自動でカメラ起動させたかったのでこのように実装。

window.onload = function Init(){
	startVideo();
}

function startVideo() {
	navigator.mediaDevices.getUserMedia({video: true, audio: false})	
	.then(function (stream) { 
		document.getElementById('local_video').srcObject = stream;
	}).catch(function (error) { // 失敗時の処理はこちら.
		console.error('mediaDevice.getUserMedia() error:', error);
		return;
	});
}

重要なのはstartVideo関数!!こちらをコールすればカメラが起動します。
ここで、”local_video”とは、html側、videoタグのidとなります。
下記のように定義すれば、定義した位置にカメラで写った映像が表示されます。

<video id="local_video"autoplay style="width: 300px; height:200px; border: 1px solid black;"></video>

次にカメラ映像を画像として切り取ります!!
処理の流れとしては
 ①videoタグで映し出された映像を事前に定義しておいたcanvasに展開
 ②canvasに展開した画像をbase64に変換
 ③base64変換したデータのプレフィクスを削除
になります。
base64とは、エンコード方式の一種で64進数を意味しており、
すべてのデータをアルファベット(a~z, A~z)と数字(0~9)、一部の記号(+,/)の64文字で表す方式とのことです。
base64ってなんぞ??理解のために実装してみた - Qiita

なぜbase64に変換したか??ですが、
imageをそのままhttpで送信できないようで、エンコードする必要があるため実施しました。

では実際の実装はこちらとなります。

// javascriptでcanvas上に写真を
function take_picture() {
	var canvas = document.getElementById('canvas');	// videoのstreamをcanvasに書き出す方法.
	var ctx = canvas.getContext('2d');
	var w = video.offsetWidth * 0.5;	// videoの横幅取得.
	var h = video.offsetHeight * 0.5;	// videoの縦幅取得.
	canvas.setAttribute("width", w);	// canvasに書き出すための横幅セット.
	canvas.setAttribute("height", h);	// canvasに書き出すための縦幅セット.
	ctx.drawImage(video, 0, 0, w, h);	// videoの画像をcanvasに書き出し.

	var base64 = canvas.toDataURL('image/jpg');	// canvas上の画像をbase64に変換.
	var picture = base64.replace(/^data:\w+\/\w+;base64,/, '');	// base64変換したデータのプレフィクスを削除.
}

サーバサイド

このbase64エンコードしたデータをサーバに送信してみます。
と言っても、エンコードしたデータをjson形式にして、ajaxを用いてpost送信するのみとなります!!
実装はこちらになります。

function tenso(picture){
	return $.ajax({
		url:"http://localhost:8080/camera",//phpファイルのURL
		type: "post",
		data: {"image":picture},
		success: function(){	// 転送成功時.
		console.log("success");	
		},
		error: function (XMLHttpRequest, textStatus, errorThrown) {	// 転送失敗時.
			console.log("error");
		}
	})
}

では次にサーバ側での受信についてです。
こちらは先ほど送信されたbase64エンコードしたデータをデコードして画像に変換する処理となります。
今回は、デコードしたデータをpicture.jpgでファイル保存する時の処理をこちらに記載しました。

app.post('/camera',function(req, res) {
	fs.writeFile('picture.jpg',JSON.stringify(req.body.image),'base64',function(err);
});

最後に

カメラを起動させるためにはlocalhostにするか、httpsでアクセスしなければなりません。
httpだとカメラ起動させることが出来ないです(セキュリティ的にNGのようです)。


実際にまとめてみると案外簡単な処理ですね。
やっていることは、
フロントサイド:カメラ起動⇒videoタグ上にカメラ映像表示⇒canvasに画像を展開⇒base64変換し送信
サーバサイド :base64から画像に変換し画像として保存
のみなので。


今回のと前回書いたopenfaceを連携させれば、顔認証とか出来て面白そうですねw。
elsammit-beginnerblg.hatenablog.com
やってみようかな?w