OpenCV app framework improved
authorAlexander Smorkalov <alexander.smorkalov@itseez.com>
Thu, 22 Nov 2012 11:56:55 +0000 (15:56 +0400)
committerAlexander Smorkalov <alexander.smorkalov@itseez.com>
Tue, 27 Nov 2012 08:47:41 +0000 (12:47 +0400)
FPS meter added;
Camera switching posibility added;
Attributes loading for layout filed implemented.

modules/java/android_lib/res/values/attrs.xml [new file with mode: 0644]
modules/java/generator/src/java/android+CameraBridgeViewBase.java
modules/java/generator/src/java/android+FpsMeter.java [new file with mode: 0644]
modules/java/generator/src/java/android+JavaCameraView.java
modules/java/generator/src/java/android+NativeCameraView.java

diff --git a/modules/java/android_lib/res/values/attrs.xml b/modules/java/android_lib/res/values/attrs.xml
new file mode 100644 (file)
index 0000000..0294ad6
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <attr name="show_fps" format="boolean"/>
+    <attr name="camera_index" format="integer"/>
+</resources>
\ No newline at end of file
index cbcd78b..c267df9 100644 (file)
@@ -30,6 +30,11 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac
 
     private static final int MAX_UNSPECIFIED = -1;
 
+    private static final int STOPPED = 0;
+    private static final int STARTED = 1;
+
+    private static final String TAG = "CameraBridge";
+
     protected int mFrameWidth;
     protected int mFrameHeight;
 
@@ -37,11 +42,26 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac
     protected int mMaxWidth;
 
     protected int mPreviewFormat = Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA;
+    protected int mCameraIndex = -1;
+    private boolean mEnabled;
 
     private Bitmap mCacheBitmap;
+    protected FpsMeter mFpsMeter = null;
+
+    private CvCameraViewListener mListener;
+    private int mState = STOPPED;
+
+    private boolean mSurfaceExist;
+
+    private Object mSyncObject = new Object();
 
     public CameraBridgeViewBase(Context context, AttributeSet attrs) {
         super(context, attrs);
+        if (attrs.getAttributeBooleanValue(null, "show_fps", false))
+            enableFpsMeter();
+
+        mCameraIndex = attrs.getAttributeIntValue(null,"camera_index", -1);
+
         getHolder().addCallback(this);
         mMaxWidth = MAX_UNSPECIFIED;
         mMaxHeight = MAX_UNSPECIFIED;
@@ -71,19 +91,6 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac
 
     }
 
-    private static final int STOPPED = 0;
-    private static final int STARTED = 1;
-
-    private static final String TAG = "CameraBridge";
-
-    private CvCameraViewListener mListener;
-    private int mState = STOPPED;
-
-    private boolean mEnabled;
-    private boolean mSurfaceExist;
-
-    private Object mSyncObject = new Object();
-
     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
         Log.d(TAG, "call surfaceChanged event");
         synchronized(mSyncObject) {
@@ -135,6 +142,24 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac
         }
     }
 
+    /**
+     * This method enables label with fps value on the screen
+     */
+    public void enableFpsMeter() {
+        if (mFpsMeter == null) {
+            mFpsMeter = new FpsMeter();
+        }
+    }
+
+    public void disableFpsMeter() {
+            mFpsMeter = null;
+    }
+
+    /**
+     *
+     * @param listener
+     */
+
     public void setCvCameraViewListener(CvCameraViewListener listener) {
         mListener = listener;
     }
@@ -272,6 +297,10 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac
             if (canvas != null) {
                 canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
                 canvas.drawBitmap(mCacheBitmap, (canvas.getWidth() - mCacheBitmap.getWidth()) / 2, (canvas.getHeight() - mCacheBitmap.getHeight()) / 2, null);
+                if (mFpsMeter != null) {
+                    mFpsMeter.measure();
+                    mFpsMeter.draw(canvas, 0, 0);
+                }
                 getHolder().unlockCanvasAndPost(canvas);
             }
         }
diff --git a/modules/java/generator/src/java/android+FpsMeter.java b/modules/java/generator/src/java/android+FpsMeter.java
new file mode 100644 (file)
index 0000000..858d95a
--- /dev/null
@@ -0,0 +1,57 @@
+package org.opencv.android;
+
+import java.text.DecimalFormat;
+
+import org.opencv.core.Core;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.Log;
+
+public class FpsMeter {
+    private static final String TAG       = "OCVSample::FpsMeter";
+    int                         step;
+    int                         framesCouner;
+    double                      freq;
+    long                        prevFrameTime;
+    String                      strfps;
+    DecimalFormat               twoPlaces = new DecimalFormat("0.00");
+    Paint                       paint;
+    boolean                     isInitialized = false;
+
+    public void init() {
+        step = 20;
+        framesCouner = 0;
+        freq = Core.getTickFrequency();
+        prevFrameTime = Core.getTickCount();
+        strfps = "";
+
+        paint = new Paint();
+        paint.setColor(Color.BLUE);
+        paint.setTextSize(50);
+    }
+
+    public void measure() {
+        if (!isInitialized) {
+            init();
+            isInitialized = true;
+        } else {
+            framesCouner++;
+            if (framesCouner % step == 0) {
+                long time = Core.getTickCount();
+                double fps = step * freq / (time - prevFrameTime);
+                prevFrameTime = time;
+                DecimalFormat twoPlaces = new DecimalFormat("0.00");
+                strfps = twoPlaces.format(fps) + " FPS";
+                Log.i(TAG, strfps);
+            }
+        }
+    }
+
+    public void draw(Canvas canvas, float offsetx, float offsety) {
+        Log.d(TAG, strfps);
+        canvas.drawText(strfps, 20 + offsetx, 10 + 50 + offsety, paint);
+    }
+
+}
index f8b3787..f41cc8e 100644 (file)
@@ -40,6 +40,8 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
     private Thread mThread;
     private boolean mStopThread;
 
+    protected Camera mCamera;
+
     private SurfaceTexture mSurfaceTexture;
 
     public static class JavaCameraSizeAccessor implements ListItemAccessor {
@@ -55,8 +57,6 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
         }
     }
 
-    private Camera mCamera;
-
     public JavaCameraView(Context context, AttributeSet attrs) {
         super(context, attrs);
         Log.d(TAG, "Java camera view ctor");
@@ -69,25 +69,36 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
         synchronized (this) {
             mCamera = null;
 
-            Log.d(TAG, "Trying to open camera with old open()");
-            try {
-                mCamera = Camera.open();
-            }
-            catch (Exception e){
-                Log.e(TAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage());
-            }
+            if (mCameraIndex == -1) {
+                Log.d(TAG, "Trying to open camera with old open()");
+                try {
+                    mCamera = Camera.open();
+                }
+                catch (Exception e){
+                    Log.e(TAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage());
+                }
 
-            if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
-                boolean connected = false;
-                for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
-                    Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(camIdx) + ")");
+                if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
+                    boolean connected = false;
+                    for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
+                        Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(camIdx) + ")");
+                        try {
+                            mCamera = Camera.open(camIdx);
+                            connected = true;
+                        } catch (RuntimeException e) {
+                            Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
+                        }
+                        if (connected) break;
+                    }
+                }
+            } else {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
+                    Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(mCameraIndex) + ")");
                     try {
-                        mCamera = Camera.open(camIdx);
-                        connected = true;
+                        mCamera = Camera.open(mCameraIndex);
                     } catch (RuntimeException e) {
-                        Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
+                        Log.e(TAG, "Camera #" + mCameraIndex + "failed to open: " + e.getLocalizedMessage());
                     }
-                    if (connected) break;
                 }
             }
 
@@ -217,6 +228,7 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
         releaseCamera();
     }
 
+    @TargetApi(Build.VERSION_CODES.FROYO)
     public void onPreviewFrame(byte[] frame, Camera arg1) {
         Log.i(TAG, "Preview Frame received. Need to create MAT and deliver it to clients");
         Log.i(TAG, "Frame size  is " + frame.length);
index a62d6bb..1a92d00 100644 (file)
@@ -19,7 +19,8 @@ public class NativeCameraView extends CameraBridgeViewBase {
     public static final String TAG = "NativeCameraView";
     private boolean mStopThread;
     private Thread mThread;
-    private VideoCapture mCamera;
+
+    protected VideoCapture mCamera;
 
     public NativeCameraView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -77,12 +78,17 @@ public class NativeCameraView extends CameraBridgeViewBase {
 
     private boolean initializeCamera(int width, int height) {
         synchronized (this) {
-            mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
+
+            if (mCameraIndex == -1)
+                mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID);
+            else
+                mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID + mCameraIndex);
 
             if (mCamera == null)
                 return false;
 
-            //TODO: improve error handling
+            if (mCamera.isOpened() == false)
+                return false;
 
             java.util.List<Size> sizes = mCamera.getSupportedPreviewSizes();