Fixed layout in third Android tutorial

This commit is contained in:
Andrey Kamaev 2012-08-17 18:12:40 +04:00
parent 3c8e151c73
commit 62f9c0e140
2 changed files with 240 additions and 224 deletions

View File

@ -175,6 +175,8 @@ a:hover {
div.body p, div.body dd, div.body li { div.body p, div.body dd, div.body li {
text-align: justify; text-align: justify;
line-height: 130%; line-height: 130%;
margin-top: 1em;
margin-bottom: 1em;
} }
div.body h1, div.body h1,
@ -327,9 +329,9 @@ table.field-list {
margin-top: 20px; margin-top: 20px;
} }
ul.simple { /*ul.simple {
list-style: none; list-style: none;
} }*/
em.menuselection, em.guilabel { em.menuselection, em.guilabel {
font-family: {{ theme_guifont }}; font-family: {{ theme_guifont }};
@ -384,3 +386,8 @@ margin-top: 0px;
div.body ul.search li { div.body ul.search li {
text-align: left; text-align: left;
} }
div.linenodiv {
min-width: 1em;
text-align: right;
}

View File

@ -57,7 +57,7 @@ Using async initialization is a **recommended** way for application development.
To run OpenCV Manager-based application the first time you need to install packages with the `OpenCV Manager` and `OpenCV binary pack` for you platform. To run OpenCV Manager-based application the first time you need to install packages with the `OpenCV Manager` and `OpenCV binary pack` for you platform.
You can do it using Google Play Market or manually with ``adb`` tool: You can do it using Google Play Market or manually with ``adb`` tool:
.. code-block:: sh .. code-block:: sh
:linenos: :linenos:
<Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.2_Manager.apk <Android SDK path>/platform-tools/adb install <OpenCV4Android SDK path>/apk/OpenCV_2.4.2_Manager.apk
@ -135,22 +135,22 @@ This approach is deprecated for the production code, release package is recommen
add the following two code lines after the ``"include $(CLEAR_VARS)"`` and before ``"include path_to_OpenCV-2.4.2-android-sdk/sdk/native/jni/OpenCV.mk"`` add the following two code lines after the ``"include $(CLEAR_VARS)"`` and before ``"include path_to_OpenCV-2.4.2-android-sdk/sdk/native/jni/OpenCV.mk"``
.. code-block:: make .. code-block:: make
:linenos: :linenos:
OPENCV_CAMERA_MODULES:=on OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on OPENCV_INSTALL_MODULES:=on
The result should look like the following: The result should look like the following:
.. code-block:: make .. code-block:: make
:linenos: :linenos:
include $(CLEAR_VARS) include $(CLEAR_VARS)
# OpenCV # OpenCV
OPENCV_CAMERA_MODULES:=on OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on OPENCV_INSTALL_MODULES:=on
include ../../sdk/native/jni/OpenCV.mk include ../../sdk/native/jni/OpenCV.mk
After that the OpenCV libraries will be copied to your application :file:`libs` folder during the JNI part build. After that the OpenCV libraries will be copied to your application :file:`libs` folder during the JNI part build.
@ -159,28 +159,28 @@ This approach is deprecated for the production code, release package is recommen
#. The last step of enabling OpenCV in your application is Java initialization code before call to OpenCV API. #. The last step of enabling OpenCV in your application is Java initialization code before call to OpenCV API.
It can be done, for example, in the static section of the ``Activity`` class: It can be done, for example, in the static section of the ``Activity`` class:
.. code-block:: java .. code-block:: java
:linenos: :linenos:
static { static {
if (!OpenCVLoader.initDebug()) { if (!OpenCVLoader.initDebug()) {
// Handle initialization error // Handle initialization error
} }
} }
If you application includes other OpenCV-dependent native libraries you should load them **after** OpenCV initialization: If you application includes other OpenCV-dependent native libraries you should load them **after** OpenCV initialization:
.. code-block:: java .. code-block:: java
:linenos: :linenos:
static { static {
if (!OpenCVLoader.initDebug()) { if (!OpenCVLoader.initDebug()) {
// Handle initialization error // Handle initialization error
} else { } else {
System.loadLibrary("my_jni_lib1"); System.loadLibrary("my_jni_lib1");
System.loadLibrary("my_jni_lib2"); System.loadLibrary("my_jni_lib2");
} }
} }
Native/C++ Native/C++
---------- ----------
@ -198,13 +198,13 @@ To build your own Android application, which uses OpenCV from native part, the f
.. code-block:: make .. code-block:: make
include C:\Work\OpenCV4Android\OpenCV-2.4.2-android-sdk\sdk\native\jni\OpenCV.mk include C:\Work\OpenCV4Android\OpenCV-2.4.2-android-sdk\sdk\native\jni\OpenCV.mk
should be inserted into the :file:`jni/Android.mk` file **after** the line should be inserted into the :file:`jni/Android.mk` file **after** the line
.. code-block:: make .. code-block:: make
include $(CLEAR_VARS) include $(CLEAR_VARS)
#. Several variables can be used to customize OpenCV stuff, but you **don't need** to use them when your application uses the `async initialization` via the `OpenCV Manager` API. #. Several variables can be used to customize OpenCV stuff, but you **don't need** to use them when your application uses the `async initialization` via the `OpenCV Manager` API.
@ -212,19 +212,19 @@ To build your own Android application, which uses OpenCV from native part, the f
.. code-block:: make .. code-block:: make
OPENCV_INSTALL_MODULES:=on OPENCV_INSTALL_MODULES:=on
Copies necessary OpenCV dynamic libs to the project ``libs`` folder in order to include them into the APK. Copies necessary OpenCV dynamic libs to the project ``libs`` folder in order to include them into the APK.
.. code-block:: make .. code-block:: make
OPENCV_CAMERA_MODULES:=off OPENCV_CAMERA_MODULES:=off
Skip native OpenCV camera related libs copying to the project ``libs`` folder. Skip native OpenCV camera related libs copying to the project ``libs`` folder.
.. code-block:: make .. code-block:: make
OPENCV_LIB_TYPE:=STATIC OPENCV_LIB_TYPE:=STATIC
Perform static link with OpenCV. By default dynamic link is used and the project JNI lib depends on ``libopencv_java.so``. Perform static link with OpenCV. By default dynamic link is used and the project JNI lib depends on ``libopencv_java.so``.
@ -232,14 +232,14 @@ To build your own Android application, which uses OpenCV from native part, the f
.. code-block:: make .. code-block:: make
APP_STL := gnustl_static APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions APP_CPPFLAGS := -frtti -fexceptions
Also the line like this one: Also the line like this one:
.. code-block:: make .. code-block:: make
APP_ABI := armeabi-v7a APP_ABI := armeabi-v7a
should specify the application target platforms. should specify the application target platforms.
@ -249,7 +249,7 @@ To build your own Android application, which uses OpenCV from native part, the f
.. code-block:: make .. code-block:: make
APP_PLATFORM := android-9 APP_PLATFORM := android-9
#. Either use :ref:`manual <NDK_build_cli>` ``ndk-build`` invocation or :ref:`setup Eclipse CDT Builder <CDT_Builder>` to build native JNI lib before Java part [re]build and APK creation. #. Either use :ref:`manual <NDK_build_cli>` ``ndk-build`` invocation or :ref:`setup Eclipse CDT Builder <CDT_Builder>` to build native JNI lib before Java part [re]build and APK creation.
@ -266,204 +266,213 @@ It will be capable of accessing camera output, processing it and displaying the
#. Set name, target, package and minSDKVersion accordingly. #. Set name, target, package and minSDKVersion accordingly.
#. Create a new class (*File -> New -> Class*). Name it for example: *HelloOpenCVView*. #. Create a new class (*File -> New -> Class*). Name it for example: *HelloOpenCVView*.
.. image:: images/dev_OCV_new_class.png
:alt: Add a new class.
:align: center
* It should extend *SurfaceView* class. .. image:: images/dev_OCV_new_class.png
:alt: Add a new class.
:align: center
* It also should implement *SurfaceHolder.Callback*, *Runnable*. * It should extend *SurfaceView* class.
* It also should implement *SurfaceHolder.Callback*, *Runnable*.
#. Edit *HelloOpenCVView* class. #. Edit *HelloOpenCVView* class.
* Add an *import* line for *android.content.context*. * Add an *import* line for *android.content.context*.
* Modify autogenerated stubs: *HelloOpenCVView*, *surfaceCreated*, *surfaceDestroyed* and *surfaceChanged*. * Modify autogenerated stubs: *HelloOpenCVView*, *surfaceCreated*, *surfaceDestroyed* and *surfaceChanged*.
.. code-block:: java
package com.hello.opencv.test; .. code-block:: java
:linenos:
import android.content.Context; package com.hello.opencv.test;
public class HelloOpenCVView extends SurfaceView implements Callback, Runnable { import android.content.Context;
public HelloOpenCVView(Context context) { public class HelloOpenCVView extends SurfaceView implements Callback, Runnable {
super(context);
getHolder().addCallback(this);
}
public void surfaceCreated(SurfaceHolder holder) { public HelloOpenCVView(Context context) {
(new Thread(this)).start(); super(context);
} getHolder().addCallback(this);
}
public void surfaceDestroyed(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
cameraRelease(); (new Thread(this)).start();
} }
public void surfaceChanged(SurfaceHolder holder, int format, int width, public void surfaceDestroyed(SurfaceHolder holder) {
int height) { cameraRelease();
cameraSetup(width, height); }
}
* Add *cameraOpen*, *cameraRelease* and *cameraSetup* voids as shown below. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
cameraSetup(width, height);
}
* Also, don't forget to add the public void *run()* as follows: //...
.. code-block:: java * Add *cameraOpen*, *cameraRelease* and *cameraSetup* voids as shown below.
public void run() { * Also, don't forget to add the public void *run()* as follows:
// TODO: loop { getFrame(), processFrame(), drawFrame() }
}
public boolean cameraOpen() { .. code-block:: java
return false; //TODO: open camera :linenos:
}
private void cameraRelease() { public void run() {
// TODO release camera // TODO: loop { getFrame(), processFrame(), drawFrame() }
} }
private void cameraSetup(int width, int height) { public boolean cameraOpen() {
// TODO setup camera return false; //TODO: open camera
} }
private void cameraRelease() {
// TODO release camera
}
.. private void cameraSetup(int width, int height) {
// TODO setup camera
}
#. Create a new *Activity* (*New -> Other -> Android -> Android Activity*) and name it, for example: *HelloOpenCVActivity*. For this activity define *onCreate*, *onResume* and *onPause* voids. #. Create a new *Activity* (*New -> Other -> Android -> Android Activity*) and name it, for example: *HelloOpenCVActivity*. For this activity define *onCreate*, *onResume* and *onPause* voids.
.. code-block:: java
public void onCreate (Bundle savedInstanceState) { .. code-block:: java
super.onCreate(savedInstanceState); :linenos:
mView = new HelloOpenCVView(this);
setContentView (mView);
}
protected void onPause() { public void onCreate (Bundle savedInstanceState) {
super.onPause(); super.onCreate(savedInstanceState);
mView.cameraRelease(); mView = new HelloOpenCVView(this);
} setContentView (mView);
}
protected void onResume() { protected void onPause() {
super.onResume(); super.onPause();
if( !mView.cameraOpen() ) { mView.cameraRelease();
// MessageBox and exit app }
AlertDialog ad = new AlertDialog.Builder(this).create();
ad.setCancelable(false); // This blocks the "BACK" button
ad.setMessage("Fatal error: can't open camera!");
ad.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
});
ad.show();
}
} protected void onResume() {
super.onResume();
if( !mView.cameraOpen() ) {
// MessageBox and exit app
AlertDialog ad = new AlertDialog.Builder(this).create();
ad.setCancelable(false); // This blocks the "BACK" button
ad.setMessage("Fatal error: can't open camera!");
ad.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
});
ad.show();
}
}
#. Add the following permissions to the AndroidManifest.xml file: #. Add the following permissions to the AndroidManifest.xml file:
.. code-block:: xml
</application> .. code-block:: xml
:linenos:
<uses-permission android:name="android.permission.CAMERA" /> </application>
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
#. Reference OpenCV library within your project properties. #. Reference OpenCV library within your project properties.
.. image:: images/dev_OCV_reference.png
:alt: Reference OpenCV library. .. image:: images/dev_OCV_reference.png
:align: center :alt: Reference OpenCV library.
:align: center
#. We now need some code to handle the camera. Update the *HelloOpenCVView* class as follows: #. We now need some code to handle the camera. Update the *HelloOpenCVView* class as follows:
.. code-block:: java
private VideoCapture mCamera; .. code-block:: java
:linenos:
public boolean cameraOpen() { private VideoCapture mCamera;
synchronized (this) {
cameraRelease(); public boolean cameraOpen() {
mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID); synchronized (this) {
if (!mCamera.isOpened()) { cameraRelease();
mCamera.release(); mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
mCamera = null; if (!mCamera.isOpened()) {
Log.e("HelloOpenCVView", "Failed to open native camera"); mCamera.release();
return false; mCamera = null;
} Log.e("HelloOpenCVView", "Failed to open native camera");
} return false;
return true; }
} }
public void cameraRelease() { return true;
synchronized(this) { }
if (mCamera != null) {
mCamera.release(); public void cameraRelease() {
mCamera = null; synchronized(this) {
} if (mCamera != null) {
} mCamera.release();
} mCamera = null;
private void cameraSetup(int width, int height) { }
synchronized (this) { }
if (mCamera != null && mCamera.isOpened()) { }
List<Size> sizes = mCamera.getSupportedPreviewSizes();
int mFrameWidth = width; private void cameraSetup(int width, int height) {
int mFrameHeight = height; synchronized (this) {
{ // selecting optimal camera preview size if (mCamera != null && mCamera.isOpened()) {
double minDiff = Double.MAX_VALUE; List<Size> sizes = mCamera.getSupportedPreviewSizes();
for (Size size : sizes) { int mFrameWidth = width;
if (Math.abs(size.height - height) < minDiff) { int mFrameHeight = height;
mFrameWidth = (int) size.width; { // selecting optimal camera preview size
mFrameHeight = (int) size.height; double minDiff = Double.MAX_VALUE;
minDiff = Math.abs(size.height - height); for (Size size : sizes) {
} if (Math.abs(size.height - height) < minDiff) {
} mFrameWidth = (int) size.width;
} mFrameHeight = (int) size.height;
mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth); minDiff = Math.abs(size.height - height);
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight); }
} }
} }
} mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
}
}
}
#. The last step would be to update the *run()* void in *HelloOpenCVView* class as follows: #. The last step would be to update the *run()* void in *HelloOpenCVView* class as follows:
.. code-block:: java
public void run() { .. code-block:: java
while (true) { :linenos:
Bitmap bmp = null;
synchronized (this) {
if (mCamera == null)
break;
if (!mCamera.grab())
break;
bmp = processFrame(mCamera); public void run() {
} while (true) {
if (bmp != null) { Bitmap bmp = null;
Canvas canvas = getHolder().lockCanvas(); synchronized (this) {
if (canvas != null) { if (mCamera == null)
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, break;
(canvas.getHeight() - bmp.getHeight()) / 2, null); if (!mCamera.grab())
getHolder().unlockCanvasAndPost(canvas); break;
} bmp = processFrame(mCamera);
bmp.recycle(); }
} if (bmp != null) {
} Canvas canvas = getHolder().lockCanvas();
} if (canvas != null) {
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2,
protected Bitmap processFrame(VideoCapture capture) { (canvas.getHeight() - bmp.getHeight()) / 2, null);
Mat mRgba = new Mat(); getHolder().unlockCanvasAndPost(canvas);
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
//process mRgba
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
try {
Utils.matToBitmap(mRgba, bmp);
} catch(Exception e) {
Log.e("processFrame", "Utils.matToBitmap() throws an exception: " + e.getMessage());
bmp.recycle();
bmp = null;
}
return bmp;
}
}
bmp.recycle();
}
}
}
protected Bitmap processFrame(VideoCapture capture) {
Mat mRgba = new Mat();
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
//process mRgba
Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
try {
Utils.matToBitmap(mRgba, bmp);
} catch(Exception e) {
Log.e("processFrame", "Utils.matToBitmap() throws an exception: " + e.getMessage());
bmp.recycle();
bmp = null;
}
return bmp;
}