diff --git a/samples/android/image-manipulations/res/layout/image_manipulations_surface_view.xml b/samples/android/image-manipulations/res/layout/image_manipulations_surface_view.xml
new file mode 100644
index 0000000000..23016a1c0f
--- /dev/null
+++ b/samples/android/image-manipulations/res/layout/image_manipulations_surface_view.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/ImageManipulationsActivity.java b/samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/ImageManipulationsActivity.java
index 5cbc3af06d..44a988ba67 100644
--- a/samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/ImageManipulationsActivity.java
+++ b/samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/ImageManipulationsActivity.java
@@ -1,12 +1,23 @@
package org.opencv.samples.imagemanipulations;
+import java.util.Arrays;
+
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
+import org.opencv.core.Core;
+import org.opencv.core.CvType;
+import org.opencv.core.Mat;
+import org.opencv.core.MatOfFloat;
+import org.opencv.core.MatOfInt;
+import org.opencv.core.Point;
+import org.opencv.core.Scalar;
+import org.opencv.core.Size;
+import org.opencv.framework.OpenCvJavaCameraView;
+import org.opencv.framework.OpenCvCameraBridgeViewBase.CvCameraViewListener;
+import org.opencv.imgproc.Imgproc;
import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
@@ -14,70 +25,64 @@ import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
-public class ImageManipulationsActivity extends Activity {
- private static final String TAG = "OCVSample::Activity";
+public class ImageManipulationsActivity extends Activity implements CvCameraViewListener {
+ private static final String TAG = "OCVSample::Activity";
- public static final int VIEW_MODE_RGBA = 0;
- public static final int VIEW_MODE_HIST = 1;
- public static final int VIEW_MODE_CANNY = 2;
- public static final int VIEW_MODE_SEPIA = 3;
- public static final int VIEW_MODE_SOBEL = 4;
- public static final int VIEW_MODE_ZOOM = 5;
- public static final int VIEW_MODE_PIXELIZE = 6;
- public static final int VIEW_MODE_POSTERIZE = 7;
+ public static final int VIEW_MODE_RGBA = 0;
+ public static final int VIEW_MODE_HIST = 1;
+ public static final int VIEW_MODE_CANNY = 2;
+ public static final int VIEW_MODE_SEPIA = 3;
+ public static final int VIEW_MODE_SOBEL = 4;
+ public static final int VIEW_MODE_ZOOM = 5;
+ public static final int VIEW_MODE_PIXELIZE = 6;
+ public static final int VIEW_MODE_POSTERIZE = 7;
- private MenuItem mItemPreviewRGBA;
- private MenuItem mItemPreviewHist;
- private MenuItem mItemPreviewCanny;
- private MenuItem mItemPreviewSepia;
- private MenuItem mItemPreviewSobel;
- private MenuItem mItemPreviewZoom;
- private MenuItem mItemPreviewPixelize;
- private MenuItem mItemPreviewPosterize;
- private ImageManipulationsView mView;
+ private MenuItem mItemPreviewRGBA;
+ private MenuItem mItemPreviewHist;
+ private MenuItem mItemPreviewCanny;
+ private MenuItem mItemPreviewSepia;
+ private MenuItem mItemPreviewSobel;
+ private MenuItem mItemPreviewZoom;
+ private MenuItem mItemPreviewPixelize;
+ private MenuItem mItemPreviewPosterize;
+ private OpenCvJavaCameraView mOpenCvCameraView;
+
+ private Size mSize0;
+ private Size mSizeRgba;
+ private Size mSizeRgbaInner;
+
+ private Mat mRgba;
+ private Mat mGray;
+ private Mat mIntermediateMat;
+ private Mat mHist;
+ private Mat mMat0;
+ private MatOfInt mChannels[];
+ private MatOfInt mHistSize;
+ private int mHistSizeNum;
+ private MatOfFloat mRanges;
+ private Scalar mColorsRGB[];
+ private Scalar mColorsHue[];
+ private Scalar mWhilte;
+ private Point mP1;
+ private Point mP2;
+ private float mBuff[];
+ private Mat mRgbaInnerWindow;
+ private Mat mGrayInnerWindow;
+ private Mat mBlurWindow;
+ private Mat mZoomWindow;
+ private Mat mZoomCorner;
+ private Mat mSepiaKernel;
public static int viewMode = VIEW_MODE_RGBA;
- private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
+ private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
- // Create and set View
- mView = new ImageManipulationsView(mAppContext);
- setContentView(mView);
-
- // Check native OpenCV camera
- if( !mView.openCamera() ) {
- AlertDialog ad = new AlertDialog.Builder(mAppContext).create();
- ad.setCancelable(false); // This blocks the 'BACK' button
- ad.setMessage("Fatal error: can't open camera!");
- ad.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- finish();
- }
- });
- ad.show();
- }
- } break;
-
- /** OpenCV loader cannot start Google Play **/
- case LoaderCallbackInterface.MARKET_ERROR:
- {
- Log.d(TAG, "Google Play service is not accessible!");
- AlertDialog MarketErrorMessage = new AlertDialog.Builder(mAppContext).create();
- MarketErrorMessage.setTitle("OpenCV Manager");
- MarketErrorMessage.setMessage("Google Play service is not accessible!\nTry to install the 'OpenCV Manager' and the appropriate 'OpenCV binary pack' APKs from OpenCV SDK manually via 'adb install' command.");
- MarketErrorMessage.setCancelable(false); // This blocks the 'BACK' button
- MarketErrorMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- finish();
- }
- });
- MarketErrorMessage.show();
+ mOpenCvCameraView.enableView();
} break;
default:
{
@@ -91,25 +96,6 @@ public class ImageManipulationsActivity extends Activity {
Log.i(TAG, "Instantiated new " + this.getClass());
}
- @Override
- protected void onPause() {
- Log.i(TAG, "called onPause");
- if (null != mView)
- mView.releaseCamera();
- super.onPause();
- }
-
- @Override
- protected void onResume() {
- Log.i(TAG, "called onResume");
- super.onResume();
-
- Log.i(TAG, "Trying to load OpenCV library");
- if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack)) {
- Log.e(TAG, "Cannot connect to OpenCV Manager");
- }
- }
-
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -117,6 +103,30 @@ public class ImageManipulationsActivity extends Activity {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ setContentView(R.layout.image_manipulations_surface_view);
+
+ mOpenCvCameraView = (OpenCvJavaCameraView)findViewById(R.id.image_manipulations_activity_surface_view);
+ mOpenCvCameraView.setCvCameraViewListener(this);
+ }
+
+ @Override
+ public void onPause()
+ {
+ mOpenCvCameraView.disableView();
+ super.onPause();
+ }
+
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+ OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mLoaderCallback);
+ }
+
+ public void onDestroy() {
+ super.onDestroy();
+ mOpenCvCameraView.disableView();
}
@Override
@@ -154,4 +164,202 @@ public class ImageManipulationsActivity extends Activity {
viewMode = VIEW_MODE_POSTERIZE;
return true;
}
+
+ public void onCameraViewStarted(int width, int height) {
+ mGray = new Mat();
+ mRgba = new Mat();
+ mIntermediateMat = new Mat();
+ mSize0 = new Size();
+ mHist = new Mat();
+ mChannels = new MatOfInt[] { new MatOfInt(0), new MatOfInt(1), new MatOfInt(2) };
+ mHistSizeNum = 25;
+ mBuff = new float[mHistSizeNum];
+ mHistSize = new MatOfInt(mHistSizeNum);
+ mRanges = new MatOfFloat(0f, 256f);
+ mMat0 = new Mat();
+ mColorsRGB = new Scalar[] { new Scalar(200, 0, 0, 255), new Scalar(0, 200, 0, 255), new Scalar(0, 0, 200, 255) };
+ mColorsHue = new Scalar[] {
+ new Scalar(255, 0, 0, 255), new Scalar(255, 60, 0, 255), new Scalar(255, 120, 0, 255), new Scalar(255, 180, 0, 255), new Scalar(255, 240, 0, 255),
+ new Scalar(215, 213, 0, 255), new Scalar(150, 255, 0, 255), new Scalar(85, 255, 0, 255), new Scalar(20, 255, 0, 255), new Scalar(0, 255, 30, 255),
+ new Scalar(0, 255, 85, 255), new Scalar(0, 255, 150, 255), new Scalar(0, 255, 215, 255), new Scalar(0, 234, 255, 255), new Scalar(0, 170, 255, 255),
+ new Scalar(0, 120, 255, 255), new Scalar(0, 60, 255, 255), new Scalar(0, 0, 255, 255), new Scalar(64, 0, 255, 255), new Scalar(120, 0, 255, 255),
+ new Scalar(180, 0, 255, 255), new Scalar(255, 0, 255, 255), new Scalar(255, 0, 215, 255), new Scalar(255, 0, 85, 255), new Scalar(255, 0, 0, 255)
+ };
+ mWhilte = Scalar.all(255);
+ mP1 = new Point();
+ mP2 = new Point();
+
+ // Fill sepia kernel
+ mSepiaKernel = new Mat(4, 4, CvType.CV_32F);
+ mSepiaKernel.put(0, 0, /* R */0.189f, 0.769f, 0.393f, 0f);
+ mSepiaKernel.put(1, 0, /* G */0.168f, 0.686f, 0.349f, 0f);
+ mSepiaKernel.put(2, 0, /* B */0.131f, 0.534f, 0.272f, 0f);
+ mSepiaKernel.put(3, 0, /* A */0.000f, 0.000f, 0.000f, 1f);
+ }
+
+ private void CreateAuxiliaryMats() {
+ if (mRgba.empty())
+ return;
+
+ mSizeRgba = mRgba.size();
+
+ int rows = (int) mSizeRgba.height;
+ int cols = (int) mSizeRgba.width;
+
+ int left = cols / 8;
+ int top = rows / 8;
+
+ int width = cols * 3 / 4;
+ int height = rows * 3 / 4;
+
+ if (mRgbaInnerWindow == null)
+ mRgbaInnerWindow = mRgba.submat(top, top + height, left, left + width);
+ mSizeRgbaInner = mRgbaInnerWindow.size();
+
+ if (mGrayInnerWindow == null && !mGray.empty())
+ mGrayInnerWindow = mGray.submat(top, top + height, left, left + width);
+
+ if (mBlurWindow == null)
+ mBlurWindow = mRgba.submat(0, rows, cols / 3, cols * 2 / 3);
+
+ if (mZoomCorner == null)
+ mZoomCorner = mRgba.submat(0, rows / 2 - rows / 10, 0, cols / 2 - cols / 10);
+
+ if (mZoomWindow == null)
+ mZoomWindow = mRgba.submat(rows / 2 - 9 * rows / 100, rows / 2 + 9 * rows / 100, cols / 2 - 9 * cols / 100, cols / 2 + 9 * cols / 100);
+ }
+
+ public void onCameraViewStopped() {
+ // Explicitly deallocate Mats
+ if (mZoomWindow != null)
+ mZoomWindow.release();
+ if (mZoomCorner != null)
+ mZoomCorner.release();
+ if (mBlurWindow != null)
+ mBlurWindow.release();
+ if (mGrayInnerWindow != null)
+ mGrayInnerWindow.release();
+ if (mRgbaInnerWindow != null)
+ mRgbaInnerWindow.release();
+ if (mRgba != null)
+ mRgba.release();
+ if (mGray != null)
+ mGray.release();
+ if (mIntermediateMat != null)
+ mIntermediateMat.release();
+
+ mRgba = null;
+ mGray = null;
+ mIntermediateMat = null;
+ mRgbaInnerWindow = null;
+ mGrayInnerWindow = null;
+ mBlurWindow = null;
+ mZoomCorner = null;
+ mZoomWindow = null;
+ }
+
+ public Mat onCameraFrame(Mat inputFrame) {
+
+ switch (ImageManipulationsActivity.viewMode) {
+ case ImageManipulationsActivity.VIEW_MODE_RGBA:
+ break;
+
+ case ImageManipulationsActivity.VIEW_MODE_HIST:
+ if ((mSizeRgba == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height))
+ CreateAuxiliaryMats();
+ int thikness = (int) (mSizeRgba.width / (mHistSizeNum + 10) / 5);
+ if(thikness > 5) thikness = 5;
+ int offset = (int) ((mSizeRgba.width - (5*mHistSizeNum + 4*10)*thikness)/2);
+ // RGB
+ for(int c=0; c<3; c++) {
+ Imgproc.calcHist(Arrays.asList(mRgba), mChannels[c], mMat0, mHist, mHistSize, mRanges);
+ Core.normalize(mHist, mHist, mSizeRgba.height/2, 0, Core.NORM_INF);
+ mHist.get(0, 0, mBuff);
+ for(int h=0; h 5) thikness = 5;
- int offset = (int) ((mSizeRgba.width - (5*mHistSizeNum + 4*10)*thikness)/2);
- // RGB
- for(int c=0; c<3; c++) {
- Imgproc.calcHist(Arrays.asList(mRgba), mChannels[c], mMat0, mHist, mHistSize, mRanges);
- Core.normalize(mHist, mHist, mSizeRgba.height/2, 0, Core.NORM_INF);
- mHist.get(0, 0, mBuff);
- for(int h=0; h sizes = mCamera.getSupportedPreviewSizes();
- int mFrameWidth = width;
- int mFrameHeight = height;
-
- // selecting optimal camera preview size
- {
- double minDiff = Double.MAX_VALUE;
- for (Size size : sizes) {
- if (Math.abs(size.height - height) < minDiff) {
- mFrameWidth = (int) size.width;
- mFrameHeight = (int) size.height;
- minDiff = Math.abs(size.height - height);
- }
- }
- }
-
- mCamera.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
- mCamera.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
- }
- }
-
- public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
- Log.i(TAG, "called surfaceChanged");
- setupCamera(width, height);
- }
-
- public void surfaceCreated(SurfaceHolder holder) {
- Log.i(TAG, "called surfaceCreated");
- (new Thread(this)).start();
- }
-
- public void surfaceDestroyed(SurfaceHolder holder) {
- Log.i(TAG, "called surfaceDestroyed");
- }
-
- protected abstract Bitmap processFrame(VideoCapture capture);
-
- public void run() {
- Log.i(TAG, "Started processing thread");
- mFps.init();
-
- while (true) {
- Bitmap bmp = null;
-
- synchronized (this) {
- if (mCamera == null)
- break;
-
- if (!mCamera.grab()) {
- Log.e(TAG, "mCamera.grab() failed");
- break;
- }
-
- bmp = processFrame(mCamera);
-
- mFps.measure();
- }
-
- if (bmp != null) {
- Canvas canvas = mHolder.lockCanvas();
- if (canvas != null) {
- canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
- canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()), null);
- mFps.draw(canvas, (canvas.getWidth() - bmp.getWidth()) / 2, 0);
- mHolder.unlockCanvasAndPost(canvas);
- }
- bmp.recycle();
- }
- }
- Log.i(TAG, "Finished processing thread");
- }
-}
\ No newline at end of file