diff --git a/doc/tutorials/dnn/dnn_android/10_opencv_dependency.png b/doc/tutorials/dnn/dnn_android/10_opencv_dependency.png deleted file mode 100644 index 03b0b597ec..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/10_opencv_dependency.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/1_start_new_project.png b/doc/tutorials/dnn/dnn_android/1_start_new_project.png deleted file mode 100644 index 37f1dd7182..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/1_start_new_project.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/2_start_new_project.png b/doc/tutorials/dnn/dnn_android/2_start_new_project.png deleted file mode 100644 index 4eeeb8ae11..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/2_start_new_project.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/3_start_new_project.png b/doc/tutorials/dnn/dnn_android/3_start_new_project.png deleted file mode 100644 index 8a2cd4b454..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/3_start_new_project.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/4_start_new_project.png b/doc/tutorials/dnn/dnn_android/4_start_new_project.png deleted file mode 100644 index d1b63f94c2..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/4_start_new_project.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/5_setup.png b/doc/tutorials/dnn/dnn_android/5_setup.png deleted file mode 100644 index 81b88a9f49..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/5_setup.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/6_run_empty_project.png b/doc/tutorials/dnn/dnn_android/6_run_empty_project.png deleted file mode 100644 index 88dc30ce99..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/6_run_empty_project.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/7_import_module.png b/doc/tutorials/dnn/dnn_android/7_import_module.png deleted file mode 100644 index c258f5ad25..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/7_import_module.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/8_import_module.png b/doc/tutorials/dnn/dnn_android/8_import_module.png deleted file mode 100644 index e2e0d3e358..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/8_import_module.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/9_opencv_dependency.png b/doc/tutorials/dnn/dnn_android/9_opencv_dependency.png deleted file mode 100644 index 107f4d210b..0000000000 Binary files a/doc/tutorials/dnn/dnn_android/9_opencv_dependency.png and /dev/null differ diff --git a/doc/tutorials/dnn/dnn_android/dnn_android.markdown b/doc/tutorials/dnn/dnn_android/dnn_android.markdown index 2c81b7ed1d..a153bd4255 100644 --- a/doc/tutorials/dnn/dnn_android/dnn_android.markdown +++ b/doc/tutorials/dnn/dnn_android/dnn_android.markdown @@ -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 \ No newline at end of file diff --git a/doc/tutorials/dnn/dnn_openvino/dnn_openvino.markdown b/doc/tutorials/dnn/dnn_openvino/dnn_openvino.markdown index 57c9840386..8eb965ca55 100644 --- a/doc/tutorials/dnn/dnn_openvino/dnn_openvino.markdown +++ b/doc/tutorials/dnn/dnn_openvino/dnn_openvino.markdown @@ -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} | | | | -: | :- | diff --git a/doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown b/doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown index 364091044c..7db3b797e9 100644 --- a/doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown +++ b/doc/tutorials/dnn/dnn_yolo/dnn_yolo.markdown @@ -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} | | | diff --git a/doc/tutorials/dnn/table_of_content_dnn.markdown b/doc/tutorials/dnn/table_of_content_dnn.markdown index e878eb2357..974ca4fc5e 100644 --- a/doc/tutorials/dnn/table_of_content_dnn.markdown +++ b/doc/tutorials/dnn/table_of_content_dnn.markdown @@ -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 diff --git a/doc/tutorials/introduction/android_binary_package/android_dnn_intro.markdown b/doc/tutorials/introduction/android_binary_package/android_dnn_intro.markdown new file mode 100644 index 0000000000..00ed2bceb6 --- /dev/null +++ b/doc/tutorials/introduction/android_binary_package/android_dnn_intro.markdown @@ -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} + + + + +@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` 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) diff --git a/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown b/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown index b06914a908..174726f699 100644 --- a/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown +++ b/doc/tutorials/introduction/android_binary_package/android_ocl_intro.markdown @@ -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} | | | diff --git a/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.markdown b/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.markdown index d37721a188..651d1e9443 100644 --- a/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.markdown +++ b/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.markdown @@ -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} | | | | -: | :- | diff --git a/doc/tutorials/dnn/dnn_android/11_demo.jpg b/doc/tutorials/introduction/android_binary_package/images/11_demo.jpg similarity index 100% rename from doc/tutorials/dnn/dnn_android/11_demo.jpg rename to doc/tutorials/introduction/android_binary_package/images/11_demo.jpg diff --git a/doc/tutorials/introduction/table_of_content_introduction.markdown b/doc/tutorials/introduction/table_of_content_introduction.markdown index 4df7ad2c78..11ac025c10 100644 --- a/doc/tutorials/introduction/table_of_content_introduction.markdown +++ b/doc/tutorials/introduction/table_of_content_introduction.markdown @@ -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 diff --git a/samples/android/mobilenet-objdetect/gradle/AndroidManifest.xml b/samples/android/mobilenet-objdetect/gradle/AndroidManifest.xml index ef50659a2d..9cc994cb32 100644 --- a/samples/android/mobilenet-objdetect/gradle/AndroidManifest.xml +++ b/samples/android/mobilenet-objdetect/gradle/AndroidManifest.xml @@ -5,7 +5,7 @@ - + + diff --git a/samples/android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java b/samples/android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java index e2add816c6..6d417a5214 100644 --- a/samples/android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java +++ b/samples/android/mobilenet-objdetect/src/org/opencv/samples/opencv_mobilenet/MainActivity.java @@ -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; @@ -47,6 +53,7 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener return; } + //! [init_model_from_memory] mModelBuffer = loadFileFromResource(R.raw.mobilenet_iter_73000); mConfigBuffer = loadFileFromResource(R.raw.deploy); if (mModelBuffer == null || mConfigBuffer == null) { @@ -54,9 +61,9 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener } 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); @@ -106,6 +113,7 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener 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); @@ -143,11 +151,14 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener 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 { @@ -167,6 +178,7 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener return new MatOfByte(buffer); } + //! [mobilenet_tutorial_resource] private static final String TAG = "OpenCV-MobileNet"; private static final String[] classNames = {"background", @@ -181,3 +193,4 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener private Net net; private CameraBridgeViewBase mOpenCvCameraView; } +//! [mobilenet_tutorial]