From a5ee07d340e9324ee2578843060a4492087e9c80 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Mon, 22 Oct 2012 17:06:15 +0400 Subject: [PATCH] Image manipulations sample ported on new framework. --- .../image_manipulations_surface_view.xml | 11 + .../ImageManipulationsActivity.java | 356 ++++++++++++++---- .../ImageManipulationsView.java | 283 -------------- .../imagemanipulations/SampleCvViewBase.java | 124 ------ 4 files changed, 293 insertions(+), 481 deletions(-) create mode 100644 samples/android/image-manipulations/res/layout/image_manipulations_surface_view.xml delete mode 100644 samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/ImageManipulationsView.java delete mode 100644 samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/SampleCvViewBase.java 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 000000000..23016a1c0 --- /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 5cbc3af06..44a988ba6 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