Skip to content

Commit

Permalink
Merge pull request opencv#24680 from AleksandrPanov:update_android_mo…
Browse files Browse the repository at this point in the history
…bilenet_tutorial

Update Android mobilenet tutorial
  • Loading branch information
asmorkalov authored Dec 12, 2023
2 parents 9bbc890 + 556f539 commit bf72e9d
Show file tree
Hide file tree
Showing 21 changed files with 108 additions and 115 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed doc/tutorials/dnn/dnn_android/5_setup.png
Binary file not shown.
Binary file not shown.
Binary file removed doc/tutorials/dnn/dnn_android/7_import_module.png
Binary file not shown.
Binary file removed doc/tutorials/dnn/dnn_android/8_import_module.png
Binary file not shown.
Binary file not shown.
108 changes: 1 addition & 107 deletions doc/tutorials/dnn/dnn_android/dnn_android.markdown
Original file line number Diff line number Diff line change
@@ -1,107 +1 @@
# How to run deep networks on Android device {#tutorial_dnn_android}

@tableofcontents

@prev_tutorial{tutorial_dnn_openvino}
@next_tutorial{tutorial_dnn_yolo}

| | |
| -: | :- |
| Original author | Dmitry Kurtaev |
| Compatibility | OpenCV >= 3.3 |

## Introduction
In this tutorial you'll know how to run deep learning networks on Android device
using OpenCV deep learning module.

Tutorial was written for the following versions of corresponding software:
- Android Studio 2.3.3
- OpenCV 3.3.0+

## Requirements

- Download and install Android Studio from https://developer.android.com/studio.

- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases and unpack it (for example, `opencv-4.X.Y-android-sdk.zip`).

- Download MobileNet object detection model from https://github.com/chuanqi305/MobileNet-SSD. We need a configuration file `MobileNetSSD_deploy.prototxt` and weights `MobileNetSSD_deploy.caffemodel`.

## Create an empty Android Studio project
- Open Android Studio. Start a new project. Let's call it `opencv_mobilenet`.
![](1_start_new_project.png)

- Keep default target settings.
![](2_start_new_project.png)

- Use "Empty Activity" template. Name activity as `MainActivity` with a
corresponding layout `activity_main`.
![](3_start_new_project.png)

![](4_start_new_project.png)

- Wait until a project was created. Go to `Run->Edit Configurations`.
Choose `USB Device` as target device for runs.
![](5_setup.png)
Plug in your device and run the project. It should be installed and launched
successfully before we'll go next.
@note Read @ref tutorial_android_dev_intro in case of problems.

![](6_run_empty_project.png)

## Add OpenCV dependency

- Go to `File->New->Import module` and provide a path to `unpacked_OpenCV_package/sdk/java`. The name of module detects automatically.
Disable all features that Android Studio will suggest you on the next window.
![](7_import_module.png)

![](8_import_module.png)

- Open two files:

1. `AndroidStudioProjects/opencv_mobilenet/app/build.gradle`

2. `AndroidStudioProjects/opencv_mobilenet/openCVLibrary330/build.gradle`

Copy both `compileSdkVersion` and `buildToolsVersion` from the first file to
the second one.

`compileSdkVersion 14` -> `compileSdkVersion 26`

`buildToolsVersion "25.0.0"` -> `buildToolsVersion "26.0.1"`

- Make the project. There is no errors should be at this point.

- Go to `File->Project Structure`. Add OpenCV module dependency.
![](9_opencv_dependency.png)

![](10_opencv_dependency.png)

- Install once an appropriate OpenCV manager from `unpacked_OpenCV_package/apk`
to target device.
@code
adb install OpenCV_3.3.0_Manager_3.30_armeabi-v7a.apk
@endcode

- Congratulations! We're ready now to make a sample using OpenCV.

## Make a sample
Our sample will takes pictures from a camera, forwards it into a deep network and
receives a set of rectangles, class identifiers and confidence values in `[0, 1]`
range.

- First of all, we need to add a necessary widget which displays processed
frames. Modify `app/src/main/res/layout/activity_main.xml`:
@include android/mobilenet-objdetect/res/layout/activity_main.xml

- Put downloaded `MobileNetSSD_deploy.prototxt` and `MobileNetSSD_deploy.caffemodel`
into `app/build/intermediates/assets/debug` folder.

- Modify `/app/src/main/AndroidManifest.xml` to enable full-screen mode, set up
a correct screen orientation and allow to use a camera.
@include android/mobilenet-objdetect/gradle/AndroidManifest.xml

- Replace content of `app/src/main/java/org/opencv/samples/opencv_mobilenet/MainActivity.java`:
@include android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java

- Launch an application and make a fun!
![](11_demo.jpg)
The page was moved to @ref tutorial_android_dnn_intro
2 changes: 1 addition & 1 deletion doc/tutorials/dnn/dnn_openvino/dnn_openvino.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ OpenCV usage with OpenVINO {#tutorial_dnn_openvino}
=====================

@prev_tutorial{tutorial_dnn_halide_scheduling}
@next_tutorial{tutorial_dnn_android}
@next_tutorial{tutorial_dnn_yolo}

| | |
| -: | :- |
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ YOLO DNNs {#tutorial_dnn_yolo}

@tableofcontents

@prev_tutorial{tutorial_dnn_android}
@prev_tutorial{tutorial_dnn_openvino}
@next_tutorial{tutorial_dnn_javascript}

| | |
Expand Down
1 change: 0 additions & 1 deletion doc/tutorials/dnn/table_of_content_dnn.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ Deep Neural Networks (dnn module) {#tutorial_table_of_content_dnn}
- @subpage tutorial_dnn_halide
- @subpage tutorial_dnn_halide_scheduling
- @subpage tutorial_dnn_openvino
- @subpage tutorial_dnn_android
- @subpage tutorial_dnn_yolo
- @subpage tutorial_dnn_javascript
- @subpage tutorial_dnn_custom_layers
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# How to run deep networks on Android device {#tutorial_android_dnn_intro}

@tableofcontents

@prev_tutorial{tutorial_dev_with_OCV_on_Android}
@next_tutorial{tutorial_android_ocl_intro}

@see @ref tutorial_table_of_content_dnn

| | |
| -: | :- |
| Original author | Dmitry Kurtaev |
| Compatibility | OpenCV >= 4.9 |

## Introduction
In this tutorial you'll know how to run deep learning networks on Android device
using OpenCV deep learning module.
Tutorial was written for Android Studio Android Studio 2022.2.1.

## Requirements

- Download and install Android Studio from https://developer.android.com/studio.

- Get the latest pre-built OpenCV for Android release from https://github.com/opencv/opencv/releases
and unpack it (for example, `opencv-4.X.Y-android-sdk.zip`).

- Download MobileNet object detection model from https://github.com/chuanqi305/MobileNet-SSD.
Configuration file `MobileNetSSD_deploy.prototxt` and model weights `MobileNetSSD_deploy.caffemodel`
are required.

## Create an empty Android Studio project and add OpenCV dependency

Use @ref tutorial_dev_with_OCV_on_Android tutorial to initialize your project and add OpenCV.

## Make an app

Our sample will takes pictures from a camera, forwards it into a deep network and
receives a set of rectangles, class identifiers and confidence values in range [0, 1].

- First of all, we need to add a necessary widget which displays processed
frames. Modify `app/src/main/res/layout/activity_main.xml`:
@include android/mobilenet-objdetect/res/layout/activity_main.xml

- Modify `/app/src/main/AndroidManifest.xml` to enable full-screen mode, set up
a correct screen orientation and allow to use a camera.
@code{.xml}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:label="@string/app_name">
@endcode
@snippet android/mobilenet-objdetect/gradle/AndroidManifest.xml mobilenet_tutorial

- Replace content of `app/src/main/java/com/example/myapplication/MainActivity.java` and set a custom package name if necessary:

@snippet android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java mobilenet_tutorial_package
@snippet android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java mobilenet_tutorial

- Put downloaded `deploy.prototxt` and `mobilenet_iter_73000.caffemodel`
into `app/src/main/res/raw` folder. OpenCV DNN model is mainly designed to load ML and DNN models
from file. Modern Android does not allow it without extra permissions, but provides Java API to load
bytes from resources. The sample uses alternative DNN API that initializes a model from in-memory
buffer rather than a file. The following function reads model file from resources and converts it to
`MatOfBytes` (analog of `std::vector<char>` in C++ world) object suitable for OpenCV Java API:

@snippet android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java mobilenet_tutorial_resource

And then the network initialization is done with the following lines:

@snippet android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java init_model_from_memory

See also [Android documentation on resources](https://developer.android.com/guide/topics/resources/providing-resources.html)

- Take a look how DNN model input is prepared and inference result is interpreted:

@snippet android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java mobilenet_handle_frame

`Dnn.blobFromImage` converts camera frame to neural network input tensor. Resize and statistical
normalization are applied. Each line of network output tensor contains information on one detected
object in the following order: confidence in range [0, 1], class id, left, top, right, bottom box
coordinates. All coordinates are in range [0, 1] and should be scaled to image size before rendering.

- Launch an application and make a fun!
![](images/11_demo.jpg)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Use OpenCL in Android camera preview based CV application {#tutorial_android_ocl_intro}
=====================================

@prev_tutorial{tutorial_dev_with_OCV_on_Android}
@prev_tutorial{tutorial_android_dnn_intro}
@next_tutorial{tutorial_macos_install}

| | |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Android Development with OpenCV {#tutorial_dev_with_OCV_on_Android}
===============================

@prev_tutorial{tutorial_O4A_SDK}
@next_tutorial{tutorial_android_ocl_intro}
@next_tutorial{tutorial_android_dnn_intro}

| | |
| -: | :- |
Expand Down
File renamed without changes
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Introduction to OpenCV {#tutorial_table_of_content_introduction}
- @subpage tutorial_android_dev_intro
- @subpage tutorial_O4A_SDK
- @subpage tutorial_dev_with_OCV_on_Android
- @subpage tutorial_android_dnn_intro
- @subpage tutorial_android_ocl_intro

##### Other platforms
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<application
android:label="@string/app_name"
android:icon="@drawable/icon">

<!-- //! [mobilenet_tutorial] -->
<activity
android:exported="true"
android:name=".MainActivity"
Expand All @@ -25,3 +25,4 @@
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>

</manifest>
<!-- //! [mobilenet_tutorial] -->
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.opencv.samples.opencv_mobilenet;

/*
// snippet was added for Android tutorial
//! [mobilenet_tutorial_package]
package com.example.myapplication;
//! [mobilenet_tutorial_package]
*/
//! [mobilenet_tutorial]
import android.content.Context;
import android.content.res.AssetManager;
import android.os.Bundle;
Expand Down Expand Up @@ -47,16 +53,17 @@ protected void onCreate(Bundle savedInstanceState) {
return;
}

//! [init_model_from_memory]
mModelBuffer = loadFileFromResource(R.raw.mobilenet_iter_73000);
mConfigBuffer = loadFileFromResource(R.raw.deploy);
if (mModelBuffer == null || mConfigBuffer == null) {
Log.e(TAG, "Failed to load model from resources");
} else
Log.i(TAG, "Model files loaded successfully");


net = Dnn.readNet("caffe", mModelBuffer, mConfigBuffer);
Log.i(TAG, "Network loaded successfully");
//! [init_model_from_memory]

setContentView(R.layout.activity_main);

Expand Down Expand Up @@ -106,6 +113,7 @@ public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2RGB);

// Forward image through network.
//! [mobilenet_handle_frame]
Mat blob = Dnn.blobFromImage(frame, IN_SCALE_FACTOR,
new Size(IN_WIDTH, IN_HEIGHT),
new Scalar(MEAN_VAL, MEAN_VAL, MEAN_VAL), /*swapRB*/false, /*crop*/false);
Expand Down Expand Up @@ -143,11 +151,14 @@ public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(0, 0, 0));
}
}
//! [mobilenet_handle_frame]

return frame;
}

public void onCameraViewStopped() {}

//! [mobilenet_tutorial_resource]
private MatOfByte loadFileFromResource(int id) {
byte[] buffer;
try {
Expand All @@ -167,6 +178,7 @@ private MatOfByte loadFileFromResource(int id) {

return new MatOfByte(buffer);
}
//! [mobilenet_tutorial_resource]

private static final String TAG = "OpenCV-MobileNet";
private static final String[] classNames = {"background",
Expand All @@ -181,3 +193,4 @@ private MatOfByte loadFileFromResource(int id) {
private Net net;
private CameraBridgeViewBase mOpenCvCameraView;
}
//! [mobilenet_tutorial]

0 comments on commit bf72e9d

Please sign in to comment.