ブラウザに表示したカメラ映像を加工し、中央以外を暗くするサンプルを作りました。QRコードリーダーのような読み取りアプリに使えるUIです。すべての加工をJavaScriptで処理せず、CSSも併用した方が軽量になります。
明度・彩度変換はCSS filter利用
ブラウザで実行しているWebアプリサンプルです。真ん中の四角を通る時だけカラーになります。
Webカメラの映像全体をcanvasに転写して、中央以外の明度・彩度を変換して作ることもできますが、少し重くなります。
軽量化するため、明度・彩度のfilter CSSをかけた映像の上に、中央の映像を転写したcanvasを重ねています。
映像(videoタグ)に対しfilterをかけ、グレースケール100%、明るさを50%に加工しています。
1 |
filter: grayscale(100%) brightness(50%); |
canvasに転写した映像は、処理が間に合わないと、1フレーム裏の映像とズレが発生してしまいます。微妙なズレを許容できれば、使える手法です。
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Webカメラをcanvasに一部転写</title> <style> #videoArea { position: relative; } #localVideo { filter: grayscale(100%) brightness(50%); } #canvasVideo { position: absolute; } </style> </head> <body> <main> <div id="videoArea"> <video id="localVideo"></video> <canvas id="canvasVideo" width="160" height="160"></canvas> </div> </main> <script> (async function main() { const localVideo = document.getElementById('localVideo'); const canvas = document.getElementById("canvasVideo"); const ctx = canvas.getContext('2d'); const videoW = 1280; const videoH = 720; const canvasW = 480; const canvasH = 480; const canvasX = (videoW - canvasW) / 2; const canvasY = (videoH - canvasH) / 2; canvas.style.top = `${canvasY}px`; canvas.style.left = `${canvasX}px`; canvas.width = canvasW; canvas.height = canvasH; const localStream = await navigator.mediaDevices .getUserMedia({ audio: false, video: { width: {ideal: videoW}, height: {ideal: videoH} } }) .catch(console.error); localVideo.muted = true; localVideo.srcObject = localStream; localVideo.playsInline = true; await localVideo.play().catch(console.error); const setRealtimeCanvas = () => { drowRealtime = setInterval(() => { ctx.drawImage(localVideo, canvasX, canvasY, canvasW, canvasH, 0 , 0, canvasW, canvasH); // 何か認識する処理 }, 1000/30); canvasStream = canvas.captureStream(30); }; setRealtimeCanvas(); })(); </script> </body> </html> |
このようなUIを作るときは、中央の四角部分で何か認識を行うと思います。
私の場合は、ボールの認識で使っています。
中央の四角はCSSのborder-radius、またはcanvasのclipで円にすることもできます。