Google OS実験室 ~Moonlight 明日香~

GoogleのAndroidで遊び始めて, すでに6年以上が経った. Androidは思った以上の発展を遂げている. この技術を使って, 新しいことにチャレンジだ!!

FLIR ONEで遊んでみる(2)

FLIR Oneを使ったアプリを考える前に, FLIR Oneについてもう少し理解を深めてみよう.

まずは, FLIR Oneのドキュメント[1]やサンプルコード[2]をベースに, 基本的な機能(サーマル画像表示, 温度測 - 定など)を実装し, FLIR Oneの基本的な動きを確認してみる.

1. サーマル画像表示
基本的な処理の流れは以下の通り.
flir02
[手順]
1) onCreateメソッド
 - 画像タイプを指定して, FrameProcessorのインスタンスを取得する.
2) onResumeメソッド
 - Device#startDiscoveryメソッドで, FLIR Oneとの接続を開始する.
  注) 例外処理(try-catch)をすること.
3) onStopメソッド
 - Device#stopDiscoveryメソッドで, FLIR Oneからのリスニングを中止し接続を停止する.
  注) stopDescoveryメソッド内で, closeメソッドも実行される.
4) onDeviceConnectedメソッド
 - デバイス情報を保持する.
 - Device#startFrameStreamメソッドで,On ストリーミングを開始する.
5) onDeviceDisconnectedメソッド
 - チューニング状態をUnknownにする.
 - Device#stopFrameStreamメソッドで, ストローミングを停止する.
6) onFrameReceivedメソッド
 - チューニング状態がInProgressでない場合に, FrameProcessor#processFrameメソッドで, フレームデータを処理する.
7) onFrameProcessedメソッド
 - RenderImage#getBitmapメソッドで, ビットマップ画像を取得する.
 - ImageView#setImageBitmapメソッドで, ビットマップ画像をビューにセットし, 画像を表示させる.
  注) UI表示はrunOnUiThread内で行うこと.

[コード]
package com.moonlight_aska.android.vision.flironedemo;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.Toast;

import com.flir.flironesdk.Device;
import com.flir.flironesdk.Frame;
import com.flir.flironesdk.FrameProcessor;
import com.flir.flironesdk.RenderedImage;

import java.util.EnumSet;

public class PreviewActivity extends AppCompatActivity
        implements Device.Delegate, Device.StreamDelegate, FrameProcessor.Delegate {
    private static final String LOG_TAG = PreviewActivity.class.getSimpleName();

    private ImageView mThermalView = null;  // 表示用View
    private volatile Device mDevice = null;  // Flir Oneデバイス
    private FrameProcessor mFrmProcessor = null;  // フレーム処理プロセッサ
    private Device.TuningState mTuningState = Device.TuningState.Unknown;    // チューニング状態
    private Bitmap mThermalBitmap = null;   // 描画用ビットマップ画像

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_preview);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mThermalView = (ImageView)findViewById(R.id.thermal_view_id);
        mThermalView.setRotation(180.0f);  // 表示上下反転
        RenderedImage.ImageType defImageType = RenderedImage.ImageType.BlendedMSXRGBA8888Image;  // Thermal + Visual画像
        mFrmProcessor = new FrameProcessor(this, this, EnumSet.of(defImageType));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_preview, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

   @Override
    protected void onResume() {
        super.onResume();
        try {
            Log.i(LOG_TAG, "onPesume, starting discovery!");
            Device.startDiscovery(this, this);
        } catch(IllegalStateException e) {
            Log.e(LOG_TAG, "onPesume, startDiscovery() error!");
            e.printStackTrace();
        }
    }

    @Override
    protected void onStop() {
        Log.i(LOG_TAG, "onStop, stopping discovery!");
        Device.stopDiscovery();

        super.onStop();
    }

    @Override
    public void onTuningStateChanged(Device.TuningState tuningState) {

    }

    @Override
    public void onAutomaticTuningChanged(boolean b) {

    }

    @Override
    public void onDeviceConnected(Device device) {
        Log.i(LOG_TAG, "Device connected!");

        mDevice = device;
        mDevice.startFrameStream(this);  // ストリーミング開始
        // Debug
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(), "Device connected.", Toast.LENGTH_LONG).show();
            }
        });
    }

    @Override
    public void onDeviceDisconnected(Device device) {
        Log.i(LOG_TAG, "Device disconnected!");

        mTuningState = Device.TuningState.Unknown;
        if (mDevice != null) {
            mDevice.stopFrameStream();
            mDevice = null;
            // Debug
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), "Device disconnected.", Toast.LENGTH_LONG).show();
                }
            });
        }
    }

    @Override
    public void onFrameReceived(Frame frame) {
        Log.i(LOG_TAG, "Frame received!");

        if (mFrmProcessor != null) {
            if (mTuningState != Device.TuningState.InProgress) {  // チューン中でない
                mFrmProcessor.processFrame(frame);
            }
        }
    }

    @Override
    public void onFrameProcessed(RenderedImage renderedImage) {
        Log.i(LOG_TAG, "Frame processing!");

        if (renderedImage.imageType() == RenderedImage.ImageType.BlendedMSXRGBA8888Image) {
            mThermalBitmap = renderedImage.getBitmap();
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (mThermalView != null) {
                        mThermalView.setImageBitmap(mThermalBitmap); // 画像表示
                    }
                }
            });
        }
    }
}

[実行結果]
 - Nexus 7(2013) / Android 4.4.4

flir01

一応, サーマル画像を表示できるようになった.
次は, 温度表示を行ってみようと思う.

----
参照URL:
[1] FLIR One SDK Documentation
[2] FLIR One Software Development Kit

FLIR ONEで遊んでみる(1)

FLIR ONEいうスマフォ用サーマルカメラに触れる機会があったので, 少し遊んでみた.
ちなみに, FLIRとは Foward Looking Infra-Red の略で, 軍用飛行機に搭載される「赤外線前方監視装置」のことである.



1. FLIR ONEを試す
Google Playから「FLIR ONE」というアプリをNexus7にインストールし, サーマルカメラを接続してみた.

端末情報:
 - Nexus 7 (2013) / Android 4.4.4

パソコンのディスプレイを写してみると...

Thermal0

中央部分の温度を測定することができる.
掌の温度が35.0℃ということで, それなりに温度が測定できているようだ.

thermal04

また, 一覧でいろいろな表示方法を確認することができる.

thermal03

2. SDKに触れる[1]
結構面白そうだが, 自分でアプリを作れるのだろうか?

少し調べてみると, FLIR One Developerのサイトでユーザ登録すると, DOWNLOAD THE SDKというところから SDKをダウンロードできる.
SDKには, ライブラリ(flironesdk.aar), ドキュメントの他にサンプルアプリが含まれていたので, さっそくビルドしてみた.

ビルド環境:
 - Android Studio 1.4.1
  - Andorid SDK Build-Tools 21.1.2
  - Target SDK Version 21

ビルド環境に合わせて, build.gradleを若干修正したが, 意外と簡単にビルドが通った.

さっそくサンプルアプリを動かしてみる.

thermal05

thermal06

サンプルアプリは, 単にサーマル画像を表示するだけでなく, 表示や色の切り替えなどライブラリの基本的な使い方がいろいろと実装されていそうだ.

これをベースにすれば, 何か面白いことが割と簡単にできそうな気がする.

----
参照URL:
[1] FLIR One Developer | Developer community  for FLIR One thermal imaging device


livedoor プロフィール
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

記事検索



  • ライブドアブログ