先日、javascriptでヒートマップを表示する方法をまとめました。
elsammit-beginnerblg.hatenablog.com
今回は以前から用いている赤外線アレイセンサ値をヒートマップで表示してみたいと思います!!
■構成
今回もこちらの赤外線アレイセンサをラズパイに接続して動作させていきます。
用いている赤外線アレイセンサはいつも通りこちら。
構成はこちら。
また、ラズパイ側はgo言語を用いて赤外線アレイセンサの受信とpost responseを行っていきます。
■サーバサイド実装
ではラズパイ側での実装を進めていきます。
先ほど記載した通り、go言語で実装いたします。
PCからのpost requestを受け取り、赤外線アレイセンサのセンサ値をjsonでresponseさせるため、
go言語ライブラリのGinを用います。
コードはこちら。
package main import ( "time" "github.com/gin-gonic/gin" "github.com/jweissig/amg8833" ) func Do_Post() { r := gin.Default() r.POST("/post/", func(c *gin.Context) { c.JSON(200, gin.H{ "message": gridpost, }) }) r.Run() } var gridpost []float64 func main() { amg, err := amg8833.NewAMG8833(&amg8833.Opts{ Device: "/dev/i2c-1", Mode: amg8833.AMG88xxNormalMode, Reset: amg8833.AMG88xxInitialReset, FPS: amg8833.AMG88xxFPS10, }) if err != nil { panic(err) } ticker := time.NewTicker(1 * time.Second) go Do_Post() for { gridpost = amg.ReadPixels() <-ticker.C } }
実施していることですが、
Ginでpost受信するためのサーバをスレッドで立ち上げ、
そのままメイン関数で赤外線アレイセンサ値を1秒ごとに取得しています。
サーバ立ち上げ時の関数はDo_Post()です。
赤外線アレイセンサ値は
{ "message": gridpost, }
というようにjsonデータ化してresponseとして返しております。
■フロントエンド実装
次にWeb上でヒートマップを表示するための実装をしていきます!!
post送信にはjQueryを用います。
ではコードです。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Test</title> <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css'> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> </head> <body> <div style="height:800px; width:800px"> <canvas id="heatMap" style="height:800px; width:800px"></canvas> </div> <script type="text/javascript"> 'use strict' const mapHeight = 8; const mapWidth = 8; var datalist = []; // データセットの生成 const generateDatasets = function(){ const datasets = [] for(let i=0; i<mapHeight; i++){ datasets.push({ data: new Array(mapWidth).fill(1), borderWidth: 0.2, borderColor: "#FFFFFF", backgroundColor: generateColor(i) // 変更 }) } return datasets } // 定期的に赤外線アレイセンサ値を取得. const interval = function(){ $.post("パス") .always(function(data){ datalist = data.message }) heatMap.data = { datasets: generateDatasets(), labels: generateLabels() } Chart.defaults.global.animation.duration = 0 heatMap.update(); } setInterval(interval, 1000); const generateColor = function(y){ const datasetColors = [] for(let x=0; x<mapWidth;x++){ const opa = ((datalist[x + (mapHeight-y-1) * mapWidth] - 16)*0.08).toFixed(2); datasetColors.push("rgb(235,10,10,"+opa+")") } return datasetColors; } // データラベルの生成 const generateLabels = function(){ let labels = [] for (var i=1; i<mapWidth+1; i++){ labels.push(i) } return labels } const ctx = document.getElementById('heatMap').getContext('2d') const heatMap = new Chart(ctx, { type: 'bar', data: { datasets: generateDatasets(), labels: generateLabels() }, options: { title: { display: true, text: 'Heat Map Sample', fontSize: 18, }, animation: false, animation: { duration: 0 }, legend: { display: false }, scales: { xAxes: [{ gridLines: { color: '#FFFFFF', }, barPercentage: 0.99, categoryPercentage: 0.99, stacked: true, ticks: { min: 0, display: false, } }], yAxes: [{ gridLines: { color: '#FFFFFF', zeroLineWidth: 0 }, stacked: true, ticks: { min: 0, stepSize: 1, display: false } }] }, } }); </script> </body> </html>
ちょっと長いですが、、、
先日のヒートマップをランダムに表示するコードと異なる点は2つ。
1つ目は、
赤外線センサ値取得のための定期的なjQueryでpost送信部。
post responseで得られたjsonのmessageに赤外線アレイセンサ値が格納されているので、
datalist変数に値を格納し、heatmapとして表示するためにgenerateDatasets()実行+heatMap.update()を行っています。
const interval = function(){ $.post("パス") .always(function(data){ datalist = data.message }) heatMap.data = { datasets: generateDatasets(), labels: generateLabels() } heatMap.update(); } setInterval(interval, 1000);
2つ目はヒートマップ表示のためのRGBAの値の調整。
const generateColor = function(y){ const datasetColors = [] for(let x=0; x<mapWidth;x++){ const opa = ((datalist[x + (mapHeight-y-1) * mapWidth] - 16)*0.08).toFixed(2); datasetColors.push("rgb(235,10,10,"+opa+")") } return datasetColors; }
■実行してみる part1
では先ほどのコードを実行してみます!!
真ん中あたりに人を配置して実行させてみました!!
実行結果はこちら。
あまり濃淡がはっきりせず人がどこにいるのか分かりにくいですね😅
よく見ると濃淡があって分かりますが。。。
こちらの計算により濃淡を変化させているのですが、、、
こちらのような、センサ値に対して濃淡を連続値にしてしまうときれいな濃淡を出すのが難しそう。。。
const opa = ((datalist[x + (mapHeight-y-1) * mapWidth] - 16)*0.08).toFixed(2);
■濃淡表現式の変更
ということで、先ほどの式を変更し、非連続で濃淡(というかRGB値)を変更してみました!!
コードはこちら。
const generateColor = function(y){ const datasetColors = [] for(let x=0; x<mapWidth;x++){ if(datalist[x + (mapHeight-y-1)*mapWidth] >= 30){ datasetColors.push("rgb(235,10,10,"+1.0+")") }else if(datalist[x + (mapHeight-y-1)*mapWidth] >= 23){ datasetColors.push("rgb(235,10,10,"+0.5+")") }else{ datasetColors.push("rgb(5,10,235,"+0.8+")") } } return datasetColors; }
アレイセンサの各画素毎に、
・28以上:RGB値(235,10,10,1.0)
・28より小さく18以上:RGB値(235,10,10,10,0.5)
・18より小さい:RGB値(5,10,235,0.8)
としました。
■実行してみる part2
では変更したコードで実行してみます。
先ほどと同様に真ん中あたりに人を配置して実行。
結果はこちら。
うん!!人がいる部分といない部分ではっきりしていますね。
見やすくなりました!!