From c64ee44c9e12ef61df12c86d50c1a49630244173 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Mon, 22 Oct 2012 16:21:35 +0400 Subject: [PATCH] Color blob detection sample ported on new framework. --- .../layout/color_blob_detection_surface_view.xml | 11 ++ .../ColorBlobDetectionActivity.java | 194 +++++++++++++++------ .../colorblobdetect/ColorBlobDetectionView.java | 151 ---------------- .../samples/colorblobdetect/SampleCvViewBase.java | 117 ------------- 4 files changed, 150 insertions(+), 323 deletions(-) create mode 100644 samples/android/color-blob-detection/res/layout/color_blob_detection_surface_view.xml delete mode 100644 samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionView.java delete mode 100644 samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/SampleCvViewBase.java diff --git a/samples/android/color-blob-detection/res/layout/color_blob_detection_surface_view.xml b/samples/android/color-blob-detection/res/layout/color_blob_detection_surface_view.xml new file mode 100644 index 0000000..f31d046 --- /dev/null +++ b/samples/android/color-blob-detection/res/layout/color_blob_detection_surface_view.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionActivity.java b/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionActivity.java index 2ee1013..ccba0a1 100644 --- a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionActivity.java +++ b/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionActivity.java @@ -1,62 +1,53 @@ package org.opencv.samples.colorblobdetect; +import java.util.List; + 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.MatOfPoint; +import org.opencv.core.Rect; +import org.opencv.core.Scalar; +import org.opencv.core.Size; +import org.opencv.framework.OpenCvCameraBridgeViewBase.CvCameraViewListener; +import org.opencv.framework.OpenCvJavaCameraView; +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.MotionEvent; +import android.view.View; import android.view.Window; import android.view.WindowManager; +import android.view.View.OnTouchListener; + +public class ColorBlobDetectionActivity extends Activity implements OnTouchListener, CvCameraViewListener { + private static final String TAG = "OCVSample::Activity"; -public class ColorBlobDetectionActivity extends Activity { - private static final String TAG = "OCVSample::Activity"; + private boolean mIsColorSelected = false; + private Mat mRgba; + private Scalar mBlobColorRgba; + private Scalar mBlobColorHsv; + private ColorBlobDetector mDetector; + private Mat mSpectrum; + private Size SPECTRUM_SIZE; + private Scalar CONTOUR_COLOR; - private ColorBlobDetectionView mView; + private OpenCvJavaCameraView mOpenCvCameraView; - 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 ColorBlobDetectionView(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(); + mOpenCvCameraView.setOnTouchListener(ColorBlobDetectionActivity.this); } break; default: { @@ -70,31 +61,124 @@ public class ColorBlobDetectionActivity extends Activity { Log.i(TAG, "Instantiated new " + this.getClass()); } + /** Called when the activity is first created. */ @Override - protected void onPause() { - Log.i(TAG, "called onPause"); - if (null != mView) - mView.releaseCamera(); + public void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "called onCreate"); + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + setContentView(R.layout.color_blob_detection_surface_view); + + mOpenCvCameraView = (OpenCvJavaCameraView)findViewById(R.id.color_blob_detection_activity_surface_view); + mOpenCvCameraView.setCvCameraViewListener(this); + } + + @Override + public void onPause() + { + mOpenCvCameraView.disableView(); super.onPause(); } @Override - protected void onResume() { - Log.i(TAG, "called onResume"); + public void onResume() + { super.onResume(); + OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mLoaderCallback); + } + + public void onDestroy() { + super.onDestroy(); + mOpenCvCameraView.disableView(); + } + + public void onCameraViewStarted(int width, int height) { + mRgba = new Mat(height, width, CvType.CV_8UC4); + mDetector = new ColorBlobDetector(); + mSpectrum = new Mat(); + mBlobColorRgba = new Scalar(255); + mBlobColorHsv = new Scalar(255); + SPECTRUM_SIZE = new Size(200, 32); + CONTOUR_COLOR = new Scalar(255,0,0,255); + } + + public void onCameraViewStopped() { + mRgba.release(); + } + + public boolean onTouch(View v, MotionEvent event) { + int cols = mRgba.cols(); + int rows = mRgba.rows(); + + int xOffset = (mOpenCvCameraView.getWidth() - cols) / 2; + int yOffset = (mOpenCvCameraView.getHeight() - rows) / 2; + + int x = (int)event.getX() - xOffset; + int y = (int)event.getY() - yOffset; + + Log.i(TAG, "Touch image coordinates: (" + x + ", " + y + ")"); - 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"); + if ((x < 0) || (y < 0) || (x > cols) || (y > rows)) return false; + + Rect touchedRect = new Rect(); + + touchedRect.x = (x>4) ? x-4 : 0; + touchedRect.y = (y>4) ? y-4 : 0; + + touchedRect.width = (x+4 < cols) ? x + 4 - touchedRect.x : cols - touchedRect.x; + touchedRect.height = (y+4 < rows) ? y + 4 - touchedRect.y : rows - touchedRect.y; + + Mat touchedRegionRgba = mRgba.submat(touchedRect); + + Mat touchedRegionHsv = new Mat(); + Imgproc.cvtColor(touchedRegionRgba, touchedRegionHsv, Imgproc.COLOR_RGB2HSV_FULL); + + // Calculate average color of touched region + mBlobColorHsv = Core.sumElems(touchedRegionHsv); + int pointCount = touchedRect.width*touchedRect.height; + for (int i = 0; i < mBlobColorHsv.val.length; i++) + mBlobColorHsv.val[i] /= pointCount; + + mBlobColorRgba = converScalarHsv2Rgba(mBlobColorHsv); + + Log.i(TAG, "Touched rgba color: (" + mBlobColorRgba.val[0] + ", " + mBlobColorRgba.val[1] + + ", " + mBlobColorRgba.val[2] + ", " + mBlobColorRgba.val[3] + ")"); + + mDetector.setHsvColor(mBlobColorHsv); + + Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE); + + mIsColorSelected = true; + + return false; // don't need subsequent touch events + } + + public Mat onCameraFrame(Mat inputFrame) { + inputFrame.copyTo(mRgba); + + if (mIsColorSelected) { + mDetector.process(mRgba); + List contours = mDetector.getContours(); + Log.e(TAG, "Contours count: " + contours.size()); + Imgproc.drawContours(mRgba, contours, -1, CONTOUR_COLOR); + + Mat colorLabel = mRgba.submat(2, 34, 2, 34); + colorLabel.setTo(mBlobColorRgba); + + Mat spectrumLabel = mRgba.submat(2, 2 + mSpectrum.rows(), 38, 38 + mSpectrum.cols()); + mSpectrum.copyTo(spectrumLabel); } + + return mRgba; } - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - Log.i(TAG, "called onCreate"); - super.onCreate(savedInstanceState); - requestWindowFeature(Window.FEATURE_NO_TITLE); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + private Scalar converScalarHsv2Rgba(Scalar hsvColor) { + Mat pointMatRgba = new Mat(); + Mat pointMatHsv = new Mat(1, 1, CvType.CV_8UC3, hsvColor); + Imgproc.cvtColor(pointMatHsv, pointMatRgba, Imgproc.COLOR_HSV2RGB_FULL, 4); + + return new Scalar(pointMatRgba.get(0, 0)); } } \ No newline at end of file diff --git a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionView.java b/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionView.java deleted file mode 100644 index 6ad57da..0000000 --- a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionView.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.opencv.samples.colorblobdetect; - -import java.util.List; -import org.opencv.android.Utils; -import org.opencv.core.Core; -import org.opencv.core.CvType; -import org.opencv.core.Mat; -import org.opencv.core.MatOfPoint; -import org.opencv.core.Rect; -import org.opencv.core.Scalar; -import org.opencv.core.Size; -import org.opencv.highgui.Highgui; -import org.opencv.highgui.VideoCapture; -import org.opencv.imgproc.Imgproc; - -import android.content.Context; -import android.graphics.Bitmap; -import android.util.Log; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.View; -import android.view.View.OnTouchListener; - -public class ColorBlobDetectionView extends SampleCvViewBase implements OnTouchListener { - private static final String TAG = "OCVSample::View"; - - private Mat mRgba; - private boolean mIsColorSelected = false; - private Scalar mBlobColorRgba = new Scalar(255); - private Scalar mBlobColorHsv = new Scalar(255); - private ColorBlobDetector mDetector = new ColorBlobDetector(); - private Mat mSpectrum = new Mat(); - private static Size SPECTRUM_SIZE = new Size(200, 32); - private static final Scalar CONTOUR_COLOR = new Scalar(255,0,0,255); - - - public ColorBlobDetectionView(Context context) { - super(context); - setOnTouchListener(this); - Log.i(TAG, "Instantiated new " + this.getClass()); - } - - @Override - public void surfaceCreated(SurfaceHolder holder) { - Log.i(TAG, "called surfaceCreated"); - synchronized (this) { - // initialize Mat before usage - mRgba = new Mat(); - } - - super.surfaceCreated(holder); - } - - private Scalar converScalarHsv2Rgba(Scalar hsvColor) { - Mat pointMatRgba = new Mat(); - Mat pointMatHsv = new Mat(1, 1, CvType.CV_8UC3, hsvColor); - Imgproc.cvtColor(pointMatHsv, pointMatRgba, Imgproc.COLOR_HSV2RGB_FULL, 4); - - return new Scalar(pointMatRgba.get(0, 0)); - } - - public boolean onTouch(View v, MotionEvent event) { - int cols = mRgba.cols(); - int rows = mRgba.rows(); - - int xOffset = (getWidth() - cols) / 2; - int yOffset = (getHeight() - rows) / 2; - - int x = (int)event.getX() - xOffset; - int y = (int)event.getY() - yOffset; - - Log.i(TAG, "Touch image coordinates: (" + x + ", " + y + ")"); - - if ((x < 0) || (y < 0) || (x > cols) || (y > rows)) return false; - - Rect touchedRect = new Rect(); - - touchedRect.x = (x>4) ? x-4 : 0; - touchedRect.y = (y>4) ? y-4 : 0; - - touchedRect.width = (x+4 < cols) ? x + 4 - touchedRect.x : cols - touchedRect.x; - touchedRect.height = (y+4 < rows) ? y + 4 - touchedRect.y : rows - touchedRect.y; - - Mat touchedRegionRgba = mRgba.submat(touchedRect); - - Mat touchedRegionHsv = new Mat(); - Imgproc.cvtColor(touchedRegionRgba, touchedRegionHsv, Imgproc.COLOR_RGB2HSV_FULL); - - // Calculate average color of touched region - mBlobColorHsv = Core.sumElems(touchedRegionHsv); - int pointCount = touchedRect.width*touchedRect.height; - for (int i = 0; i < mBlobColorHsv.val.length; i++) - mBlobColorHsv.val[i] /= pointCount; - - mBlobColorRgba = converScalarHsv2Rgba(mBlobColorHsv); - - Log.i(TAG, "Touched rgba color: (" + mBlobColorRgba.val[0] + ", " + mBlobColorRgba.val[1] + - ", " + mBlobColorRgba.val[2] + ", " + mBlobColorRgba.val[3] + ")"); - - mDetector.setHsvColor(mBlobColorHsv); - - Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE); - - mIsColorSelected = true; - - return false; // don't need subsequent touch events - } - - @Override - protected Bitmap processFrame(VideoCapture capture) { - capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA); - - Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888); - - if (mIsColorSelected) { - mDetector.process(mRgba); - List contours = mDetector.getContours(); - Log.e(TAG, "Contours count: " + contours.size()); - Imgproc.drawContours(mRgba, contours, -1, CONTOUR_COLOR); - - Mat colorLabel = mRgba.submat(2, 34, 2, 34); - colorLabel.setTo(mBlobColorRgba); - - Mat spectrumLabel = mRgba.submat(2, 2 + mSpectrum.rows(), 38, 38 + mSpectrum.cols()); - mSpectrum.copyTo(spectrumLabel); - } - - try { - Utils.matToBitmap(mRgba, bmp); - } catch(Exception e) { - Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage()); - bmp.recycle(); - bmp = null; - } - - return bmp; - } - - @Override - public void run() { - super.run(); - - synchronized (this) { - // Explicitly deallocate Mats - if (mRgba != null) - mRgba.release(); - - mRgba = null; - } - } -} diff --git a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/SampleCvViewBase.java b/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/SampleCvViewBase.java deleted file mode 100644 index 47cc3c8..0000000 --- a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/SampleCvViewBase.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.opencv.samples.colorblobdetect; - -import java.util.List; - -import org.opencv.core.Size; -import org.opencv.highgui.VideoCapture; -import org.opencv.highgui.Highgui; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.util.Log; -import android.view.SurfaceHolder; -import android.view.SurfaceView; - -public abstract class SampleCvViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable { - private static final String TAG = "OCVSample::BaseView"; - - private SurfaceHolder mHolder; - private VideoCapture mCamera; - - public SampleCvViewBase(Context context) { - super(context); - mHolder = getHolder(); - mHolder.addCallback(this); - Log.i(TAG, "Instantiated new " + this.getClass()); - } - - public synchronized boolean openCamera() { - Log.i(TAG, "Opening Camera"); - mCamera = new VideoCapture(Highgui.CV_CAP_ANDROID); - if (!mCamera.isOpened()) { - releaseCamera(); - Log.e(TAG, "Can't open native camera"); - return false; - } - return true; - } - - public synchronized void releaseCamera() { - Log.i(TAG, "Releasing Camera"); - if (mCamera != null) { - mCamera.release(); - mCamera = null; - } - } - - public synchronized void setupCamera(int width, int height) { - if (mCamera != null && mCamera.isOpened()) { - Log.i(TAG, "Setup Camera - " + width + "x" + height); - List 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"); - while (true) { - Bitmap bmp = null; - - synchronized (this) { - if (mCamera == null) - break; - - if (!mCamera.grab()) { - Log.e(TAG, "mCamera.grab() failed"); - break; - } - - bmp = processFrame(mCamera); - } - - 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()) / 2, null); - mHolder.unlockCanvasAndPost(canvas); - } - bmp.recycle(); - } - } - Log.i(TAG, "Finished processing thread"); - } -} \ No newline at end of file -- 2.7.4