電力モニターの作り方

 website=http://okubolab.genes.nig.ac.jp/kouwatan/gauge.html height=300 width=300 border=0 scroll=no  http://okubolab.genes.nig.ac.jp/kouwatan/gauge.html

=これは何?= ネットワークから切り離された電力モニターの映像情報を元にして、 リアルタイム電力モニターを作成したものです.

=どうやって実現しているのか?=

概要

 * 1) パナソニック製のネットワークカメラBB-HCM581を用いて、キャプチャ画像をLinuxサーバへ6秒間隔でftp転送する.
 * 2) Linuxサーバ上で、以下の処理を6秒ごとに実行する.
 * 3) キャプチャ画像から必要な部分を切り出す(トリミング).
 * 4) 切り出した画像をOCRにかける.
 * 5) OCRの結果を精査しJSON形式に保存する.
 * 6) JavaScript(Google Chart Tools, jQuery)を用いてブラウザで電力モニターを表示する.

ネットワークカメラBB-HCM581の設定
BB-HCMN581はキャプチャ画像をftp転送する機能を持っている.  OCR精度を上げるため、最も高い解像度(640x480)でキャプチャした画像を6秒間隔でLinuxサーバへ転送した. 

Linuxサーバ上での処理
制御はcronを利用、cronは秒単位制御は無い為、"処理実行"->6秒sleepを毎分0秒から9回繰り返す命令を設定した.  処理の実時間は0.08秒しか掛からず、6秒間隔の処理実行を行うにあたり、6秒間sleepすることで問題ないと判断した. $ crontab -l
 * 1) m h  dom mon dow   command
 * * * * * for a in $(seq 1 9); do /home/kouwatan/webcam/exec.sh & sleep 6; done;

キャプチャ画像のトリミング
OCR処理を行うにあたり、精度を上げるため、必要な領域(数値が表示されている領域)のみ切り出した.  ImageMagickを利用. convert -crop 170x395+390+10 webcam.jpg /dev/shm/capture.jpg 実行結果

jpeg形式からpnm形式に変換
ImageMagickを利用. jpegtopnm /dev/shm/capture.jpg > /dev/shm/capture.pnm

OCRを実行
OCRの精度は画像の状態によりどうしても得手不得手が発生するようである.  そこで複数のOCRを実行し、その結果を元に正解と思われる結果を導出するアプローチを取った.  今回利用したOCRはGOCR、Ocradの2種類である. gocr /dev/shm/capture.pnm > /dev/shm/capture.gocr ocrad /dev/shm/capture.pnm > /dev/shm/capture.ocrad

OCRの結果から値の導出、JSON形式へ
ここで行う処理は大きく以下の2点の処理を行っている. Rubyで実装したのが以下のとおり. require 'rubygems' if(RUBY_VERSION < '1.9.1') require 'json' require 'pp'
 * OCRの結果の誤認識を修正:数値であることがわかっているので、定番の誤認識(1を"|"や"l")を修正する
 * 複数のOCRの結果を利用:全てのOCRの結果が同一値である場合のみ電力メーターに反映(JSON形式に出力)する.

def str_clean(str) str.gsub(/l/,"1"). gsub(/\|/,"1"). gsub(/Z/i,"2"). gsub(/T/,"7"). gsub(/g/,"9"). gsub(/o/i,"0"). gsub(/\s/,"") end

data = '/var/www/html/kouwatan/data.json'

ocr_out_h = {} ARGV.each { |ocr_out| ocr_out_h[ocr_out] = File.open(ocr_out).collect{|x| str_clean(x.chomp)}.delete_if{|x| x==""} } a = ocr_out_h.collect{|k,v| v[1]}.find_all{|x| x[/^\d+$/]}.collect{|x| begin x.to_i rescue nil end}.uniq if a.length == 1 h = JSON.parse(File.read(data)) h["now"] = a[0] File.open(data,"w"){|f| f.puts JSON.pretty_generate(h)} end 出力結果のJSON形式は以下のとおり http://okubolab.genes.nig.ac.jp/kouwatan/data.json { "now": 1282, "max": 2100, "redTo": 2100, "greenFrom": 1500, "redFrom": 1800, "height": 175, "yellowTo": 1800, "greenTo": 0, "yellowFrom": 1500, "width": 175 }

電力モニター
JSONデータの逐次取得はjQueryを利用し、電力モニターはGoogle Chart Toolsのgauge(ゲージ)を利用する

  google.load("jquery", "1"); google.load('visualization', '1', {packages:['gauge']}); google.setOnLoadCallback(drawChart); function drawChart { var data = new google.visualization.DataTable; data.addColumn('string', 'Label'); data.addColumn('number', 'Value'); data.addRows(1); data.setValue(0, 0, 'power(kW)'); var chart = new google.visualization.Gauge(document.getElementById('chart_div')); var options = {width: 200, height: 200, greenColor:'#7CD660', minorTicks: 5}; $.getJSON('./data.json',         function(obj, status) {            data.setValue(0, 1, obj.now);            data.setValue(0, 1, obj.now);            options['max']=obj.max;            options['greenFrom']=obj.greenFrom;            options['greenTo']=obj.greenTo;            options['yellowFrom']=obj.yellowFrom;            options['yellowTo']=obj.yellowTo;            options['redFrom']=obj.redFrom;            options['redTo']=obj.redTo;            options['width']=obj.width;            options['height']=obj.height;            chart.draw(data, options);          }        ); chart.draw(data, options); setInterval(function {         $.getJSON('./data.json' , function(obj, status) { data.setValue(0, 1, obj.now); options['max']=obj.max; options['greenFrom']=obj.greenFrom; options['greenTo']=obj.greenTo; options['yellowFrom']=obj.yellowFrom; options['yellowTo']=obj.yellowTo; options['redFrom']=obj.redFrom; options['redTo']=obj.redTo; options['width']=obj.width; options['height']=obj.height; chart.draw(data, options); }         );        }, 6000);      }    

Kouwatan 12:02, 19 June 2011 (JST)