6
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TensorFlowLiteで1枚の画像から物体検出するたぶん最小構成 for Android

Last updated at Posted at 2019-07-08

#はじめに
前にTensorFlow Mobileでの物体検出はやったんですが、今やるならTensorFlowLiteでしょうということでやってみた

#検証環境

  • Android Studio 3.2.1
  • CompileSdkVersion:28
  • MinSdkVersion:18
  • TargetSdkVersion:28
  • TensorFlowLite

#プロジェクト作成
まずはプロジェクトの作成お好きなプロジェクト名で
001.png
minumum SDKはAPI 18未満だとエラーが出るんで、18以上を選択
002.png
初期Activityは何でもいいですが、ここでは最小構成ということでEmpty Activity
003.png

#build.gradleの設定

build.gradle(app)
apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.anadreline.android.peopleaicounter"
        minSdkVersion 18
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    aaptOptions {
        noCompress "tflite"
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly'
    implementation 'org.tensorflow:tensorflow-lite-gpu:0.0.0-nightly'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

ポイントは2つだけ
TensorFlowLiteの依存設定
 implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly'
 implementation 'org.tensorflow:tensorflow-lite-gpu:0.0.0-nightly'
tfliteファイルを圧縮させないためのnoCompress設定
 aaptOptions {
  noCompress "tflite"
 }

#検出関連クラス
004.png
公式のサンプルからClassifier.javaとTensorFlowObjectDetectionAPIModel.javaとLogger.javaの3つ
それにassetsフォルダに公式サイトのモデルファイル(detect.tflite)とラベルファイル(label_map.txt)を入れます

#レイアウト
あとは画像選択させるためMainActivityにボタンを設置してー

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Detect"
        android:onClick="onClick"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

#物体検出
最後に画像を取得して物体検出する処理を作成して完成

MainActivity.java
package com.anadreline.android.objectdetection;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.io.IOException;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private static final int TF_OD_API_INPUT_SIZE = 300;
    private static final boolean TF_OD_API_IS_QUANTIZED = true;
    private static final String TF_OD_API_MODEL_FILE = "detect.tflite";
    private static final String TF_OD_API_LABELS_FILE = "file:///android_asset/labelmap.txt";

    private final int REQUEST_FILE = 1;
    private final int REQUEST_CAMERA = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onClick(View view) {
        Intent intentGallery;
        if (Build.VERSION.SDK_INT < 19) {
            intentGallery = new Intent(Intent.ACTION_GET_CONTENT);
            intentGallery.setType("image/*");
        } else {
            intentGallery = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intentGallery.addCategory(Intent.CATEGORY_OPENABLE);
            intentGallery.setType("image/*");
        }
        startActivityForResult(intentGallery, REQUEST_FILE);
    }

    @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK) {
            Uri resultUri = data.getData();
            if (resultUri == null) { return;}
            Bitmap image = Utl.decodeUri(this, resultUri, 1200, 0);
            int height = image.getHeight();
            int width = image.getWidth();
            Bitmap crop = Bitmap.createBitmap(TF_OD_API_INPUT_SIZE, TF_OD_API_INPUT_SIZE, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(crop);
            canvas.drawBitmap(image, new Rect(0, 0, width, height), new Rect(0, 0, TF_OD_API_INPUT_SIZE, TF_OD_API_INPUT_SIZE), new Paint());
            try {
                Classifier detector = TFLiteObjectDetectionAPIModel.create(
                                getAssets(),
                                TF_OD_API_MODEL_FILE,
                                TF_OD_API_LABELS_FILE,
                                TF_OD_API_INPUT_SIZE,
                                TF_OD_API_IS_QUANTIZED);
                final List<Classifier.Recognition> results = detector.recognizeImage(crop);
                for (final Classifier.Recognition result : results) {
                    Log.v("Detect", "Title:" + result.getTitle());
                    Log.v("Detect", "Confidence:" + result.getConfidence());
                    Log.v("Detect", "Location:" + result.getLocation());
                }
            } catch (final IOException e) {
                e.printStackTrace();
                Toast toast = Toast.makeText(getApplicationContext(), "Classifier could not be initialized", Toast.LENGTH_SHORT);
                toast.show();
                finish();
            }
        }
    }
}

ここでのポイントは検出クラスに投げる画像は決められたサイズにする必要があること
上記のこのへんで変形してます

MainActivity.java
    //TF_OD_API_INPUT_SIZE=300;
    Bitmap crop = Bitmap.createBitmap(TF_OD_API_INPUT_SIZE, TF_OD_API_INPUT_SIZE, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(crop);
    canvas.drawBitmap(image, new Rect(0, 0, width, height), new Rect(0, 0, TF_OD_API_INPUT_SIZE, TF_OD_API_INPUT_SIZE), new Paint());

以上TensorFlowLiteによる物体検出のたぶん最小構成

6
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?