前回は非接触温度センサー「AMG8833」を使い、サーモグラフィーを作りました。今度はセンサーが捉えたものの温度を計測できるようにします。
動作サンプル
まずはモルモットを検温。
・・・逃げてしまいました。
今回作ったサーモグラフィーでは、検温に5秒程度かかってしまいます。
動いている動物では難しいので、静物で実験します。
温めたおにぎりが39.8℃、氷水が0.3℃。
センサーに映したものの中で、一番高い温度を表示しています。
検温に使ったコード
開発環境、サーバー側のコードはこちらをご確認ください。HTMLのみ下記コードに改修しています。
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
<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> #temp { position: absolute; top: 0; right: 0; font-size: 72px; line-height: 1; } #canvas { position: relative; margin: 100px 0 0 40%; transform: scale(30); z-index: -1; } </style> </head> <body> <main> <button type="button" id="thermalBtn">検温!</button> <span id="temp"></span><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'); const $temp = $('#temp'); let isTemp = false; let tempList = []; 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++) { //最大温度記録 if(data[i][j] > temp){ temp = data[i][j]; } //色相を設定 h = max - data[i][j] * 7; if(max < h){ h = max; }else if(min > h){ h = min; } ctx.fillStyle = 'hsl('+ h +', 100%, 50%)'; ctx.fillRect(j, i, 1, 1); } } tempList.push(temp); if(tempList.length > 10){ tempList.shift(); } $temp.text(getTemp(tempList) + '℃'); }; const getTemp = (tempList) => { // 中央値の温度を返す let array = tempList.slice(), val; array.sort((a, b) => { return a - b; }); let half = Math.floor(array.length / 2); if (array.length % 2) { val = array[half]; } else { val = (array[half - 1] + array[half]) / 2; } return val.toFixed(1); }; init(); </script> </body> </html> |
10回計測して、温度の中央値を表示する仕様です。
体温を調べたい
「AMG8833」を人間の検温に使いたいと思う人は、今のご時世多いかもしれません。
通常、人間の体温は周囲より高いため、「AMG8833」を人間にかざした場合、最も高い温度を体温として取得すればよいでしょう。
実際に自分にセンサーを向け、0.5秒ごとに体温を測ってみました。
若干低めですが、検温はできます。ただ、2つ問題がありました。
体温が安定しない
一つ目の問題。恒温動物である人間が、突然38℃になったり、30℃になったり、頻繁に異常値がでます。これに関しては10回取得した温度の中央値を取ることで解決しました。
中央値を使うことで、異常値を除外できます。
例えば、10回計測した温度が[35,35,34,34,38,35,34,38,35,35]だった場合、35℃が中央値になります。平均値と違い、38℃の影響を受けません。
距離によって体温が変わる
もう一つの問題は、距離によって温度が変わることです。センサーと人との距離が近いほど温度が正確になるようです。
そのため、おでこにセンサーをかざして検温すると、より正確な体温を知ることができます。
しかし、それではサーモグラフィーの意味がない・・・「AMG8833」の64の解像度はいらないです。
サーモグラフィーを生かすため、次回、離れた場所で正確に検温できるように調整します。