以前、mruby から TensorFlow Lite を扱う為の mrbgems、「mruby-tflite」を書きました。
Big Sky :: MRuby の TensorFlow Lite バインディングを書いた。
以前 TensorFlow Lite の Go バインディングを書いたのだけど Big Sky :: TensorFlow Lite の Go binding を書いた。 Google launche...
https://mattn.kaoriya.net/software/lang/c/20190417102631.htm
KaoriYa さんに Coral EdgeTPU をプレゼントして頂いたので、mruby-tflite を Coral EdgeTPU 対応する為の mrbgems を書きました。
GitHub - mattn/mruby-tflite-edgetpu
https://github.com/mattn/mruby-tflite-edgetpu
元の mruby-tflite とはソースを分離してあります。build_config.rb に以下の様に追加して頂くだけで EdgeTPU を扱える様になります。
conf.gem :github => 'mattn/mruby-tflite'
conf.gem :github => 'mattn/mruby-tflite-edgetpu'
conf.gem :github => 'kjunichi/mruby-webcam'
conf.gem :github => 'qtkmz/mruby-gd'
mruby-tflite と mruby-tflite-edgetpu を連携するには以下の様にインタプリタに対してオプション設定する必要があります。
#! ./bin/mruby
# オプションを生成
options = TfLite::InterpreterOptions.new
# Coral EdgeTPU のデバイス一覧から 0 番目を delegate として割り付け
options.add_delegate TfLite::EdgeTPU.new(TfLite::EdgeTPU.devices[0])
model = TfLite::Model.from_file 'mobilenet_ssd_v2_coco_quant_postprocess_edgetpu.tflite'
interpreter = TfLite::Interpreter.new(model, options)
interpreter.allocate_tensors
input = interpreter.input_tensor(0)
output2 = interpreter.output_tensor(1)
output3 = interpreter.output_tensor(2)
wanted_width = input.dim(1)
wanted_height = input.dim(2)
wanted_channel = input.dim(3)
data = Array.new(wanted_height * wanted_width * wanted_channel, 0)
labels = {}
File.read('coco_labels.txt').lines.each do |x|
kv = x.split(' ')
labels[kv[0].to_i] = kv[1].strip
end
cam = Webcam.new(ARGV[0]||0)
cam.set_size(wanted_width, wanted_height)
cam.each(true) {|img|
decoded = GD::Image.new_from_jpeg_data(img)
(0...wanted_width).each do |x|
(0...wanted_height).each do |y|
pixel = decoded.get_pixel(x, y)
offset = (y * wanted_width + x) * wanted_channel
data[offset..offset+2] = [decoded.red(pixel), decoded.green(pixel), decoded.blue(pixel)]
end
end
decoded.destroy
input.data = data
interpreter.invoke
result = []
output3.data.each_with_index do |v, i|
next if v < 0.6
result.push([v, output2.data[i]])
end
result.sort{|a, b| b[0] <=> a[0] }.take(5).each_with_index do |v, i|
s = v[0]
i = v[1]
puts "#{labels[i]} #{i} #{s}"
end
puts "---"
}
現状、mruby には OpenCV の様に加工した MAT を表示できる mrbgems が存在しない為、kjunichi さんが作っておられる mruby-webcam で画像を取り込み、qtkmz さんの mruby-gd で画像を解析し、そこに何が映っているのかを端末に出力しているだけですが、今後 OpenCV の様な mrbgems が登場すれば mruby でもリアルタイムで画像を解析し、認識したオブジェクトに枠や名称を描画する事も出来る様になるかもしれません。