mirror of
https://github.com/opencv/opencv.git
synced 2024-11-25 19:50:38 +08:00
New sample framework integrated to Java part of SDK;
Frame format setter added to both views.
This commit is contained in:
parent
9029acf6f0
commit
641ee645ab
@ -237,7 +237,7 @@ if(ANDROID)
|
|||||||
set(lib_target_files ${ANDROID_LIB_PROJECT_FILES})
|
set(lib_target_files ${ANDROID_LIB_PROJECT_FILES})
|
||||||
ocv_list_add_prefix(lib_target_files "${OpenCV_BINARY_DIR}/")
|
ocv_list_add_prefix(lib_target_files "${OpenCV_BINARY_DIR}/")
|
||||||
|
|
||||||
android_get_compatible_target(lib_target_sdk_target ${ANDROID_NATIVE_API_LEVEL} ${ANDROID_SDK_TARGET})
|
android_get_compatible_target(lib_target_sdk_target ${ANDROID_NATIVE_API_LEVEL} ${ANDROID_SDK_TARGET} 11)
|
||||||
|
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/android_lib/${ANDROID_MANIFEST_FILE}" "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}")
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/android_lib/${ANDROID_MANIFEST_FILE}" "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}")
|
||||||
|
|
||||||
|
@ -6,9 +6,11 @@ import org.opencv.android.Utils;
|
|||||||
import org.opencv.core.Mat;
|
import org.opencv.core.Mat;
|
||||||
import org.opencv.core.Size;
|
import org.opencv.core.Size;
|
||||||
import org.opencv.highgui.Highgui;
|
import org.opencv.highgui.Highgui;
|
||||||
import org.opencv.highgui.VideoCapture;
|
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@ -34,15 +36,15 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
protected int mMaxHeight;
|
protected int mMaxHeight;
|
||||||
protected int mMaxWidth;
|
protected int mMaxWidth;
|
||||||
|
|
||||||
|
protected int mPreviewFormat = Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA;
|
||||||
|
|
||||||
private Bitmap mCacheBitmap;
|
private Bitmap mCacheBitmap;
|
||||||
|
|
||||||
|
|
||||||
public OpenCvCameraBridgeViewBase(Context context, AttributeSet attrs) {
|
public OpenCvCameraBridgeViewBase(Context context, AttributeSet attrs) {
|
||||||
super(context,attrs);
|
super(context, attrs);
|
||||||
getHolder().addCallback(this);
|
getHolder().addCallback(this);
|
||||||
mMaxWidth = MAX_UNSPECIFIED;
|
mMaxWidth = MAX_UNSPECIFIED;
|
||||||
mMaxHeight = MAX_UNSPECIFIED;
|
mMaxHeight = MAX_UNSPECIFIED;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface CvCameraViewListener {
|
public interface CvCameraViewListener {
|
||||||
@ -69,20 +71,10 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FrameSize {
|
|
||||||
public int width;
|
|
||||||
public int height;
|
|
||||||
|
|
||||||
public FrameSize(int w, int h) {
|
|
||||||
width = w;
|
|
||||||
height = h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static final int STOPPED = 0;
|
private static final int STOPPED = 0;
|
||||||
private static final int STARTED = 1;
|
private static final int STARTED = 1;
|
||||||
private static final String TAG = "SampleCvBase";
|
|
||||||
|
private static final String TAG = "OpenCvCameraBridge";
|
||||||
|
|
||||||
private CvCameraViewListener mListener;
|
private CvCameraViewListener mListener;
|
||||||
private int mState = STOPPED;
|
private int mState = STOPPED;
|
||||||
@ -90,8 +82,6 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
private boolean mEnabled;
|
private boolean mEnabled;
|
||||||
private boolean mSurfaceExist;
|
private boolean mSurfaceExist;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Object mSyncObject = new Object();
|
private Object mSyncObject = new Object();
|
||||||
|
|
||||||
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
|
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
|
||||||
@ -122,10 +112,9 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is provided for clients, so they can enable the camera connection.
|
* This method is provided for clients, so they can enable the camera connection.
|
||||||
* The actuall onCameraViewStarted callback will be delivered only after both this method is called and surface is available
|
* The actual onCameraViewStarted callback will be delivered only after both this method is called and surface is available
|
||||||
*/
|
*/
|
||||||
public void enableView() {
|
public void enableView() {
|
||||||
synchronized(mSyncObject) {
|
synchronized(mSyncObject) {
|
||||||
@ -136,7 +125,7 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is provided for clients, so they can disable camera connection and stop
|
* This method is provided for clients, so they can disable camera connection and stop
|
||||||
* the delivery of frames eventhough the surfaceview itself is not destroyed and still stays on the scren
|
* the delivery of frames even though the surface view itself is not destroyed and still stays on the scren
|
||||||
*/
|
*/
|
||||||
public void disableView() {
|
public void disableView() {
|
||||||
synchronized(mSyncObject) {
|
synchronized(mSyncObject) {
|
||||||
@ -145,7 +134,6 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setCvCameraViewListener(CvCameraViewListener listener) {
|
public void setCvCameraViewListener(CvCameraViewListener listener) {
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
@ -155,15 +143,20 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
* size - the biggest size which less or equal the size set will be selected.
|
* size - the biggest size which less or equal the size set will be selected.
|
||||||
* As an example - we set setMaxFrameSize(200,200) and we have 176x152 and 320x240 sizes. The
|
* As an example - we set setMaxFrameSize(200,200) and we have 176x152 and 320x240 sizes. The
|
||||||
* preview frame will be selected with 176x152 size.
|
* preview frame will be selected with 176x152 size.
|
||||||
* This method is usefull when need to restrict the size of preview frame for some reason (for example for video recording)
|
* This method is useful when need to restrict the size of preview frame for some reason (for example for video recording)
|
||||||
* @param maxWidth - the maximum width allowed for camera frame.
|
* @param maxWidth - the maximum width allowed for camera frame.
|
||||||
* @param maxHeight - the maxumum height allowed for camera frame
|
* @param maxHeight - the maximum height allowed for camera frame
|
||||||
*/
|
*/
|
||||||
public void setMaxFrameSize(int maxWidth, int maxHeight) {
|
public void setMaxFrameSize(int maxWidth, int maxHeight) {
|
||||||
mMaxWidth = maxWidth;
|
mMaxWidth = maxWidth;
|
||||||
mMaxHeight = maxHeight;
|
mMaxHeight = maxHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetCaptureFormat(int format)
|
||||||
|
{
|
||||||
|
mPreviewFormat = format;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when mSyncObject lock is held
|
* Called when mSyncObject lock is held
|
||||||
*/
|
*/
|
||||||
@ -201,7 +194,6 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void processExitState(int state) {
|
private void processExitState(int state) {
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case STARTED:
|
case STARTED:
|
||||||
@ -221,23 +213,32 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
/* nothing to do */
|
/* nothing to do */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: The order of bitmap constructor and camera connection is important for android 4.1.x
|
||||||
|
// Bitmap must be constructed before surface
|
||||||
private void onEnterStartedState() {
|
private void onEnterStartedState() {
|
||||||
|
/* Connect camera */
|
||||||
|
if (!connectCamera(getWidth(), getHeight())) {
|
||||||
|
AlertDialog ad = new AlertDialog.Builder(getContext()).create();
|
||||||
|
ad.setCancelable(false); // This blocks the 'BACK' button
|
||||||
|
ad.setMessage("It seems that you device does not support camera (or it is locked). Application will be closed.");
|
||||||
|
ad.setButton(DialogInterface.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
((Activity) getContext()).finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ad.show();
|
||||||
|
|
||||||
connectCamera(getWidth(), getHeight());
|
}
|
||||||
/* Now create cahe Bitmap */
|
|
||||||
mCacheBitmap = Bitmap.createBitmap(mFrameWidth, mFrameHeight, Bitmap.Config.ARGB_8888);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onExitStartedState() {
|
private void onExitStartedState() {
|
||||||
|
|
||||||
disconnectCamera();
|
disconnectCamera();
|
||||||
if (mCacheBitmap != null) {
|
if (mCacheBitmap != null) {
|
||||||
mCacheBitmap.recycle();
|
mCacheBitmap.recycle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method shall be called by the subclasses when they have valid
|
* This method shall be called by the subclasses when they have valid
|
||||||
* object and want it to be delivered to external client (via callback) and
|
* object and want it to be delivered to external client (via callback) and
|
||||||
@ -253,13 +254,22 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
modified = frame;
|
modified = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean bmpValid = true;
|
||||||
if (modified != null) {
|
if (modified != null) {
|
||||||
|
try {
|
||||||
Utils.matToBitmap(modified, mCacheBitmap);
|
Utils.matToBitmap(modified, mCacheBitmap);
|
||||||
|
} catch(Exception e) {
|
||||||
|
Log.e(TAG, "Mat type: " + modified);
|
||||||
|
Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
|
||||||
|
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
|
||||||
|
bmpValid = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCacheBitmap != null) {
|
if (bmpValid && mCacheBitmap != null) {
|
||||||
Canvas canvas = getHolder().lockCanvas();
|
Canvas canvas = getHolder().lockCanvas();
|
||||||
if (canvas != null) {
|
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);
|
canvas.drawBitmap(mCacheBitmap, (canvas.getWidth() - mCacheBitmap.getWidth()) / 2, (canvas.getHeight() - mCacheBitmap.getHeight()) / 2, null);
|
||||||
getHolder().unlockCanvasAndPost(canvas);
|
getHolder().unlockCanvasAndPost(canvas);
|
||||||
}
|
}
|
||||||
@ -273,21 +283,25 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
* @param width - the width of this SurfaceView
|
* @param width - the width of this SurfaceView
|
||||||
* @param height - the height of this SurfaceView
|
* @param height - the height of this SurfaceView
|
||||||
*/
|
*/
|
||||||
protected abstract void connectCamera(int width, int height);
|
protected abstract boolean connectCamera(int width, int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnects and release the particular camera object beeing connected to this surface view.
|
* Disconnects and release the particular camera object being connected to this surface view.
|
||||||
* Called when syncObject lock is held
|
* Called when syncObject lock is held
|
||||||
*/
|
*/
|
||||||
protected abstract void disconnectCamera();
|
protected abstract void disconnectCamera();
|
||||||
|
|
||||||
|
// NOTE: On Android 4.1.x the function must be called before SurfaceTextre constructor!
|
||||||
|
protected void AllocateCache()
|
||||||
|
{
|
||||||
|
mCacheBitmap = Bitmap.createBitmap(mFrameWidth, mFrameHeight, Bitmap.Config.ARGB_8888);
|
||||||
|
}
|
||||||
|
|
||||||
public interface ListItemAccessor {
|
public interface ListItemAccessor {
|
||||||
public int getWidth(Object obj);
|
public int getWidth(Object obj);
|
||||||
public int getHeight(Object obj);
|
public int getHeight(Object obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This helper method can be called by subclasses to select camera preview size.
|
* This helper method can be called by subclasses to select camera preview size.
|
||||||
* It goes over the list of the supported preview sizes and selects the maximum one which
|
* It goes over the list of the supported preview sizes and selects the maximum one which
|
||||||
@ -297,7 +311,7 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
* @param surfaceHeight
|
* @param surfaceHeight
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected FrameSize calculateCameraFrameSize(List<?> supportedSizes, ListItemAccessor accessor, int surfaceWidth, int surfaceHeight) {
|
protected Size calculateCameraFrameSize(List<?> supportedSizes, ListItemAccessor accessor, int surfaceWidth, int surfaceHeight) {
|
||||||
int calcWidth = 0;
|
int calcWidth = 0;
|
||||||
int calcHeight = 0;
|
int calcHeight = 0;
|
||||||
|
|
||||||
@ -315,6 +329,7 @@ public abstract class OpenCvCameraBridgeViewBase extends SurfaceView implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new FrameSize(calcWidth, calcHeight);
|
|
||||||
|
return new Size(calcWidth, calcHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import android.view.SurfaceHolder;
|
|||||||
import org.opencv.core.CvType;
|
import org.opencv.core.CvType;
|
||||||
import org.opencv.core.Mat;
|
import org.opencv.core.Mat;
|
||||||
import org.opencv.core.Size;
|
import org.opencv.core.Size;
|
||||||
|
import org.opencv.highgui.Highgui;
|
||||||
import org.opencv.imgproc.Imgproc;
|
import org.opencv.imgproc.Imgproc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,13 +42,11 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements
|
|||||||
|
|
||||||
public static class JavaCameraSizeAccessor implements ListItemAccessor {
|
public static class JavaCameraSizeAccessor implements ListItemAccessor {
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getWidth(Object obj) {
|
public int getWidth(Object obj) {
|
||||||
Camera.Size size = (Camera.Size) obj;
|
Camera.Size size = (Camera.Size) obj;
|
||||||
return size.width;
|
return size.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHeight(Object obj) {
|
public int getHeight(Object obj) {
|
||||||
Camera.Size size = (Camera.Size) obj;
|
Camera.Size size = (Camera.Size) obj;
|
||||||
return size.height;
|
return size.height;
|
||||||
@ -189,7 +188,6 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements
|
|||||||
releaseCamera();
|
releaseCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPreviewFrame(byte[] frame, Camera arg1) {
|
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, "Preview Frame received. Need to create MAT and deliver it to clients");
|
||||||
Log.i(TAG, "Frame size is " + frame.length);
|
Log.i(TAG, "Frame size is " + frame.length);
|
||||||
@ -213,7 +211,6 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements
|
|||||||
mHeight = h;
|
mHeight = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
public void run() {
|
||||||
do {
|
do {
|
||||||
synchronized (OpenCvJavaCameraView.this) {
|
synchronized (OpenCvJavaCameraView.this) {
|
||||||
@ -227,7 +224,16 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements
|
|||||||
|
|
||||||
if (!mStopThread) {
|
if (!mStopThread) {
|
||||||
Mat frameMat = new Mat();
|
Mat frameMat = new Mat();
|
||||||
|
switch (mPreviewFormat) {
|
||||||
|
case Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA:
|
||||||
Imgproc.cvtColor(mBaseMat, frameMat, Imgproc.COLOR_YUV2RGBA_NV21, 4);
|
Imgproc.cvtColor(mBaseMat, frameMat, Imgproc.COLOR_YUV2RGBA_NV21, 4);
|
||||||
|
break;
|
||||||
|
case Highgui.CV_CAP_ANDROID_GREY_FRAME:
|
||||||
|
frameMat = mBaseMat.submat(0, mFrameHeight, 0, mFrameWidth);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Invalid frame format! Only RGBA and Gray Scale are supported!");
|
||||||
|
};
|
||||||
deliverAndDrawFrame(frameMat);
|
deliverAndDrawFrame(frameMat);
|
||||||
frameMat.release();
|
frameMat.release();
|
||||||
}
|
}
|
||||||
|
@ -66,13 +66,11 @@ public class OpenCvNativeCameraView extends OpenCvCameraBridgeViewBase {
|
|||||||
|
|
||||||
public static class OpenCvSizeAccessor implements ListItemAccessor {
|
public static class OpenCvSizeAccessor implements ListItemAccessor {
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getWidth(Object obj) {
|
public int getWidth(Object obj) {
|
||||||
Size size = (Size)obj;
|
Size size = (Size)obj;
|
||||||
return (int)size.width;
|
return (int)size.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHeight(Object obj) {
|
public int getHeight(Object obj) {
|
||||||
Size size = (Size)obj;
|
Size size = (Size)obj;
|
||||||
return (int)size.height;
|
return (int)size.height;
|
||||||
@ -112,6 +110,7 @@ public class OpenCvNativeCameraView extends OpenCvCameraBridgeViewBase {
|
|||||||
private class CameraWorker implements Runnable {
|
private class CameraWorker implements Runnable {
|
||||||
|
|
||||||
private Mat mRgba = new Mat();
|
private Mat mRgba = new Mat();
|
||||||
|
private Mat mGray = new Mat();
|
||||||
private int mWidth;
|
private int mWidth;
|
||||||
private int mHeight;
|
private int mHeight;
|
||||||
|
|
||||||
@ -120,7 +119,6 @@ public class OpenCvNativeCameraView extends OpenCvCameraBridgeViewBase {
|
|||||||
mHeight = h;
|
mHeight = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
public void run() {
|
||||||
Mat modified;
|
Mat modified;
|
||||||
|
|
||||||
@ -130,9 +128,20 @@ public class OpenCvNativeCameraView extends OpenCvCameraBridgeViewBase {
|
|||||||
Log.e(TAG, "Camera frame grab failed");
|
Log.e(TAG, "Camera frame grab failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mCamera.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
|
||||||
|
|
||||||
|
switch (mPreviewFormat) {
|
||||||
|
case Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA:
|
||||||
|
{
|
||||||
|
mCamera.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
|
||||||
deliverAndDrawFrame(mRgba);
|
deliverAndDrawFrame(mRgba);
|
||||||
|
} break;
|
||||||
|
case Highgui.CV_CAP_ANDROID_GREY_FRAME:
|
||||||
|
mCamera.retrieve(mGray, Highgui.CV_CAP_ANDROID_GREY_FRAME);
|
||||||
|
deliverAndDrawFrame(mGray);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Invalid frame format! Only RGBA and Gray Scale are supported!");
|
||||||
|
}
|
||||||
|
|
||||||
} while (!mStopThread);
|
} while (!mStopThread);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user