diff --git a/doc/tutorials/introduction/android_binary_package/android_dev_intro.markdown b/doc/tutorials/introduction/android_binary_package/android_dev_intro.markdown index 21547b4bba..c82efb709a 100644 --- a/doc/tutorials/introduction/android_binary_package/android_dev_intro.markdown +++ b/doc/tutorials/introduction/android_binary_package/android_dev_intro.markdown @@ -55,7 +55,7 @@ Here's how to get a ready to work environment: 2. Extract the tar.gz archive 3. Follow the instructions in `Install-Linux-tar.txt`: open `android-studio/bin` folder in terminal and run `./studio.sh` 4. Perform standard installation through GUI - 5. Optionally you can add a shortcut on a desktop for a quick access by clicking menu Tools -> Create desktop entry. The menu appears after any project is created or opened. + 5. Optionally you can add a shortcut on a desktop for a quick access by clicking menu ***Tools -> Create desktop entry***. The menu appears after any project is created or opened. 2. Install fresh Android SDK and NDK: 1. Open SDK manager in Android Studio (***Customize -> All Settings -> Languages & Frameworks -> Android SDK***) 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 d37d1710a3..24fc79949c 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 @@ -29,6 +29,8 @@ If you encounter any error after thoroughly following these steps, feel free to Hello OpenCV sample ------------------- +In this section we're gonna create a simple app that does nothing but OpenCV loading. In next section we'll extend it to support camera. + In addition to this instruction you can use some video guide, for example [this one](https://www.youtube.com/watch?v=bR7lL886-uc&ab_channel=ProgrammingHut) 1. Open Android Studio and create empty project by choosing ***Empty Views Activity*** @@ -75,7 +77,6 @@ In addition to this instruction you can use some video guide, for example [this 6. OpenCV project uses `aidl` and `buildConfig` features. Please enable them in `MyApplication/OpenCV/build.gradle` file to `android` block: - @code{.gradle} buildFeatures{ aidl true @@ -93,17 +94,19 @@ In addition to this instruction you can use some video guide, for example [this 7. Add the module to the project: - Click ***File -> Project structure... -> Dependencies -> All modules -> + (Add Dependency button) -> Module dependency*** - - Choose `app` - - Select `OpenCV` ![](images/add_module_1.png) + - Choose `app` + ![](images/add_module_2.png) + - Select `OpenCV` + ![](images/add_module_3.png) 8. Before using any OpenCV function you have to load the library first. If you application includes other OpenCV-dependent native libraries you should load them ***after*** OpenCV initialization. - Library is loaded at app start: + Add the folowing code to load the library at app start: @snippet samples/android/tutorial-1-camerapreview/src/org/opencv/samples/tutorial1/Tutorial1Activity.java ocv_loader_init Like this: ![](images/sample_code.png) @@ -111,3 +114,84 @@ In addition to this instruction you can use some video guide, for example [this 9. Choose a device to check the sample on and run the code by pressing `run` button ![](images/run_app.png) + +Camera view sample +------------------ + +In this section we'll extend our empty OpenCV app created in the previous section to support camera. We'll take camera frames and display them on the screen. + +1. Tell a system that we need camera permissions. + Add the following code to the file `MyApplication/app/src/main/AndroidManifest.xml`: + @snippet samples/android/tutorial-1-camerapreview/gradle/AndroidManifest.xml camera_permissions + Like this: + ![](images/camera_permissions.png) + +2. Go to `activity_main.xml` layout and delete TextView with text "Hello World!" + + ![](images/delete_text.png) + + This can also be done in Code or Split mode by removing the `TextView` block from XML file. + +3. Add camera view to the layout: + 1. Add a scheme into layout description: + @code{.xml} + xmlns:opencv="http://schemas.android.com/apk/res-auto" + @endcode + + 2. Replace `TextView` with `org.opencv.android.JavaCameraView` widget: + @snippet /samples/android/tutorial-1-camerapreview/res/layout/tutorial1_surface_view.xml camera_view + + 3. If you get a layout warning replace `fill_parent` values by `match_parent` for `android:layout_width` and `android:layout_height` properties + + You'll get a code like this: + + @include /samples/android/tutorial-1-camerapreview/res/layout/tutorial1_surface_view.xml + +4. Inherit the main class from `org.opencv.android.CameraActivity`. CameraActivity implements + camera perimission requiest and some other utilities needed for CV application. Methods we're + interested in to override are `onCreate`, `onDestroy`, `onPause`, `onResume` and `getCameraViewList` + +5. Implement the interface `org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2` + `onCameraFrame` method should return the `Mat` object with content for render. + The sample just returns camera frame for preview: `return inputFrame.rgba();` + +6. Allocate `org.opencv.android.CameraBridgeViewBase` object: + - It should be created at app start (`onCreate` method) and this class should be set as a listener + - At pause/resume (`onPause`, `onResume` methods) it should be disabled/enabled + - Should be disabled at app finish (`onDestroy` method) + - Should be returned in `getCameraViewList` + +7. Optionally you can forbid the phone to dim screen or lock: + + @snippet samples/android/tutorial-1-camerapreview/src/org/opencv/samples/tutorial1/Tutorial1Activity.java keep_screen + +Finally you'll get source code similar to this: + +@include samples/android/tutorial-1-camerapreview/src/org/opencv/samples/tutorial1/Tutorial1Activity.java + +This is it! Now you can run the code on your device to check it. + + +Let's discuss some most important steps +--------------------------------------- + +Every Android application with UI must implement Activity and View. By the first steps we create blank +activity and default view layout. The simplest OpenCV-centric application must perform OpenCV +initialization, create a view to show preview from camera and implement `CvCameraViewListener2` interface +to get frames from camera and process them. + +First of all we create our application view using XML layout. Our layout consists of the only one +full screen component of class `org.opencv.android.JavaCameraView`. This OpenCV class is inherited from + `CameraBridgeViewBase` that extends `SurfaceView` and under the hood uses standard Android camera API. + +The `CvCameraViewListener2` interface lets you add some processing steps after the frame is grabbed from +the camera and before it's rendered on the screen. The most important method is `onCameraFrame`. This is +a callback function and it's called on retrieving frame from camera. It expects that `onCameraFrame` +function returns RGBA frame that will be drawn on the screen. + +The callback passes a frame from camera to our class as an object of `CvCameraViewFrame` class. +This object has `rgba()` and `gray()` methods that let a user get colored or one-channel grayscale +frame as a `Mat` class object. + +@note Do not save or use `CvCameraViewFrame` object out of `onCameraFrame` callback. This object does +not have its own state and its behavior outside the callback is unpredictable! diff --git a/doc/tutorials/introduction/android_binary_package/images/camera_permissions.png b/doc/tutorials/introduction/android_binary_package/images/camera_permissions.png new file mode 100644 index 0000000000..f7622dee88 Binary files /dev/null and b/doc/tutorials/introduction/android_binary_package/images/camera_permissions.png differ diff --git a/doc/tutorials/introduction/android_binary_package/images/delete_text.png b/doc/tutorials/introduction/android_binary_package/images/delete_text.png new file mode 100644 index 0000000000..d865ff92cc Binary files /dev/null and b/doc/tutorials/introduction/android_binary_package/images/delete_text.png differ diff --git a/doc/tutorials/introduction/android_binary_package/images/usb_device_connect_13.png b/doc/tutorials/introduction/android_binary_package/images/usb_device_connect_13.png deleted file mode 100644 index 4d7c84fbc7..0000000000 Binary files a/doc/tutorials/introduction/android_binary_package/images/usb_device_connect_13.png and /dev/null differ diff --git a/samples/android/tutorial-1-camerapreview/gradle/AndroidManifest.xml b/samples/android/tutorial-1-camerapreview/gradle/AndroidManifest.xml index 79aaf3f5d4..98f2a2f35b 100644 --- a/samples/android/tutorial-1-camerapreview/gradle/AndroidManifest.xml +++ b/samples/android/tutorial-1-camerapreview/gradle/AndroidManifest.xml @@ -27,11 +27,13 @@ android:largeScreens="true" android:anyDensity="true" /> + //! [camera_permissions] + //! [camera_permissions] diff --git a/samples/android/tutorial-1-camerapreview/res/layout/tutorial1_surface_view.xml b/samples/android/tutorial-1-camerapreview/res/layout/tutorial1_surface_view.xml index 77f1c5fba8..398efca0bb 100644 --- a/samples/android/tutorial-1-camerapreview/res/layout/tutorial1_surface_view.xml +++ b/samples/android/tutorial-1-camerapreview/res/layout/tutorial1_surface_view.xml @@ -4,6 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" > + + diff --git a/samples/android/tutorial-1-camerapreview/src/org/opencv/samples/tutorial1/Tutorial1Activity.java b/samples/android/tutorial-1-camerapreview/src/org/opencv/samples/tutorial1/Tutorial1Activity.java index 1912eab785..e8bc5327cd 100644 --- a/samples/android/tutorial-1-camerapreview/src/org/opencv/samples/tutorial1/Tutorial1Activity.java +++ b/samples/android/tutorial-1-camerapreview/src/org/opencv/samples/tutorial1/Tutorial1Activity.java @@ -9,7 +9,6 @@ import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2; import android.os.Bundle; import android.util.Log; -import android.view.MenuItem; import android.view.SurfaceView; import android.view.WindowManager; import android.widget.Toast; @@ -21,8 +20,6 @@ public class Tutorial1Activity extends CameraActivity implements CvCameraViewLis private static final String TAG = "OCVSample::Activity"; private CameraBridgeViewBase mOpenCvCameraView; - private boolean mIsJavaCamera = true; - private MenuItem mItemSwitchCamera = null; public Tutorial1Activity() { Log.i(TAG, "Instantiated new " + this.getClass()); @@ -44,7 +41,9 @@ public class Tutorial1Activity extends CameraActivity implements CvCameraViewLis } //! [ocv_loader_init] + //! [keep_screen] getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + //! [keep_screen] setContentView(R.layout.tutorial1_surface_view); @@ -76,18 +75,22 @@ public class Tutorial1Activity extends CameraActivity implements CvCameraViewLis return Collections.singletonList(mOpenCvCameraView); } + @Override public void onDestroy() { super.onDestroy(); if (mOpenCvCameraView != null) mOpenCvCameraView.disableView(); } + @Override public void onCameraViewStarted(int width, int height) { } + @Override public void onCameraViewStopped() { } + @Override public Mat onCameraFrame(CvCameraViewFrame inputFrame) { return inputFrame.rgba(); }