非接触温度センサー「AMG8833」を使い、サーモグラフィーをブラウザに表示します。8×8の温度配列を、canvasで描画し、CSSで拡大しています。
「AMG8833」の温度データをブラウザで読み込む
「AMG8833」をラズパイに繋いぎ、非接触で温度を確認します。
開発環境やサーバー側(node.js、Python)は、前回の記事をご確認ください。
今回はフロント側、HTMLのみ書き換えます。
8×8のサーモグラフィーをcanvas描画
「AMG8833」で取得した8×8の温度配列を、canvasでサーモグラフィーのように描画します。
8×8のcanvasを用意して、1pxずつ色を塗ります。
温度によって色を変えるには、hslで色指定をすると簡単です。
h(色相)を温度が高いほど0(赤)。低いほど250(青)に近づけます。
色相環になっているため、hが250を越えていくと赤に近づいき、逆にhがマイナスになると青に近づいてしまいます。
hの値は0~250からはみ出ないように制限は必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const max = 250; const min = 0; drawCanvas([[20.1,20.5...],[],[],[],[],[],[],[]]); //8×8の温度配列 const drawCanvas = (data) => { let h, temp = 0; for (let i = 0; i < data.length; i++) { for (let j = 0; j < data[i].length; j++) { //色相を設定 h = max - data[i][j] * 9; if(max < h){ h = max; }else if(min > h){ h = min; } ctx.fillStyle = 'hsl('+ h +', 100%, 50%)'; ctx.fillRect(j, i, 1, 1); } } }; |
これでちっちゃいですが、サーモグラフィーをcanvasで描画することができます。
ブラウザでバイキュービック補間
「AMG8833」の解像度は8×8しかありません。これをブラウザ標準のバイキュービック補間を使って、滑らかな画像にします。
単純にtransform: scale(30);を指定して、30倍にしています。
すると、ブラウザ側で滑らかに補完してくれます。
OpenCVでもできますが、CSSで行うのが最も軽量で簡単だと思います。
最終的なコード
「検温!」ボタンを押したら、0.5秒おきにサーモグラフィーが更新されていくようにしました。
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 72 73 74 75 76 77 78 79 80 81 82 83 |
<html> <head> <title>サーマルカメラ</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.0/socket.io.js"></script> <style> #canvas { position: relative; margin: 100px 0 0 50%; transform: scale(30); z-index: -1; } </style> </head> <body> <main> <button type="button" id="thermalBtn">検温!</button><br> <canvas id="canvas" width="8" height="8"></canvas> </main> <script> const socket = io(); const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const max = 250; const min = 0; const $thermalBtn = $('#thermalBtn'); let isTemp = false; const init = () => { setSocket(); setBtn(); }; const setSocket = () => { let array, result = []; socket.on('thermal', (data) => { drawCanvas(data); }); }; const setBtn = () => { let timer; $thermalBtn.on('click', function(){ const emitThermal = function(){ socket.emit('msg', 'thermal'); }; isTemp = !isTemp; if(isTemp){ emitThermal(); timer = setInterval(emitThermal, 500); $thermalBtn.text('計測中…'); }else{ clearInterval(timer); $thermalBtn.text('検温!'); } return false; }); }; const drawCanvas = (data) => { let h, temp = 0; for (let i = 0; i < data.length; i++) { for (let j = 0; j < data[i].length; j++) { //色相を設定 h = max - data[i][j] * 9; if(max < h){ h = max; }else if(min > h){ h = min; } ctx.fillStyle = 'hsl('+ h +', 100%, 50%)'; ctx.fillRect(j, i, 1, 1); } } }; init(); </script> </body> </html> |
次回、サーモグラフィーと合わせて体温を表示するように改修します。