diff --git a/samples/android/4-mixed/.classpath b/samples/android/4-mixed/.classpath new file mode 100644 index 0000000000..927cc0b57d --- /dev/null +++ b/samples/android/4-mixed/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/samples/android/4-mixed/.project b/samples/android/4-mixed/.project new file mode 100644 index 0000000000..fa9b217708 --- /dev/null +++ b/samples/android/4-mixed/.project @@ -0,0 +1,40 @@ + + + Sample 4 Mixed + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + OpenCVJavaAPI_src + 2 + _android_OpenCVJavaAPI_583dbd7b/src + + + diff --git a/samples/android/4-mixed/.settings/org.eclipse.jdt.core.prefs b/samples/android/4-mixed/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..d995784334 --- /dev/null +++ b/samples/android/4-mixed/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Wed Jun 29 04:36:40 MSD 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/samples/android/4-mixed/AndroidManifest.xml b/samples/android/4-mixed/AndroidManifest.xml new file mode 100644 index 0000000000..d8e64d5fe1 --- /dev/null +++ b/samples/android/4-mixed/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/android/4-mixed/default.properties b/samples/android/4-mixed/default.properties new file mode 100644 index 0000000000..b4a7e0f66a --- /dev/null +++ b/samples/android/4-mixed/default.properties @@ -0,0 +1,12 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-8 +android.library.reference.1=../../../android/build diff --git a/samples/android/4-mixed/jni/Android.mk b/samples/android/4-mixed/jni/Android.mk new file mode 100644 index 0000000000..b7d7111b4b --- /dev/null +++ b/samples/android/4-mixed/jni/Android.mk @@ -0,0 +1,17 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +OPENCV_CAMERA_MODULES:=off +OPENCV_MK_BUILD_PATH:=../../../../android/build/OpenCV.mk +ifeq ("$(wildcard $(OPENCV_MK_BUILD_PATH))","") + include $(TOOLCHAIN_PREBUILT_ROOT)/user/share/OpenCV/OpenCV.mk +else + include $(OPENCV_MK_BUILD_PATH) +endif + +LOCAL_MODULE := mixed_sample +LOCAL_SRC_FILES := jni_part.cpp +LOCAL_LDLIBS += -llog -ldl + +include $(BUILD_SHARED_LIBRARY) diff --git a/samples/android/4-mixed/jni/Application.mk b/samples/android/4-mixed/jni/Application.mk new file mode 100644 index 0000000000..c7de9c761b --- /dev/null +++ b/samples/android/4-mixed/jni/Application.mk @@ -0,0 +1,3 @@ +APP_STL := gnustl_static +APP_CPPFLAGS := -frtti -fexceptions +APP_ABI := armeabi-v7a diff --git a/samples/android/4-mixed/jni/jni_part.cpp b/samples/android/4-mixed/jni/jni_part.cpp new file mode 100644 index 0000000000..c2553a81b0 --- /dev/null +++ b/samples/android/4-mixed/jni/jni_part.cpp @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +extern "C" { +JNIEXPORT void JNICALL Java_org_opencv_samples_s4_Sample4View_FindFeatures(JNIEnv* env, jobject thiz, jlong addrGray, jlong addrRgba) +{ + Mat* pMatGr=(Mat*)addrGray; + Mat* pMatRgb=(Mat*)addrRgba; + vector v; + + FastFeatureDetector detector(50); + detector.detect(*pMatGr, v); + for( size_t i = 0; i < v.size(); i++ ) + circle(*pMatRgb, Point(v[i].pt.x, v[i].pt.y), 10, Scalar(255,0,0,255)); +} + +} diff --git a/samples/android/4-mixed/res/drawable/icon.png b/samples/android/4-mixed/res/drawable/icon.png new file mode 100644 index 0000000000..4e828bafd8 Binary files /dev/null and b/samples/android/4-mixed/res/drawable/icon.png differ diff --git a/samples/android/4-mixed/res/values/strings.xml b/samples/android/4-mixed/res/values/strings.xml new file mode 100644 index 0000000000..50d603646d --- /dev/null +++ b/samples/android/4-mixed/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Sample 4: Mixed + diff --git a/samples/android/4-mixed/src/org/opencv/samples/s4/Sample4Mixed.java b/samples/android/4-mixed/src/org/opencv/samples/s4/Sample4Mixed.java new file mode 100644 index 0000000000..fa34689b8b --- /dev/null +++ b/samples/android/4-mixed/src/org/opencv/samples/s4/Sample4Mixed.java @@ -0,0 +1,64 @@ +package org.opencv.samples.s4; + +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.Window; + +public class Sample4Mixed extends Activity { + private static final String TAG = "Sample4Mixed::Activity"; + + public static final int VIEW_MODE_RGBA = 0; + public static final int VIEW_MODE_GRAY = 1; + public static final int VIEW_MODE_CANNY = 2; + public static final int VIEW_MODE_SOBEL = 3; + public static final int VIEW_MODE_BLUR = 4; + public static final int VIEW_MODE_FEATURES = 5; + + private MenuItem mItemPreviewRGBA; + private MenuItem mItemPreviewGray; + private MenuItem mItemPreviewCanny; + private MenuItem mItemPreviewSobel; + private MenuItem mItemPreviewBlur; + private MenuItem mItemPreviewFeatures; + + public int viewMode; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(new Sample4View(this)); + viewMode = VIEW_MODE_RGBA; + } + + public boolean onCreateOptionsMenu(Menu menu) { + mItemPreviewRGBA = menu.add("Preview RGBA"); + mItemPreviewGray = menu.add("Preview GRAY"); + mItemPreviewCanny = menu.add("Canny"); + mItemPreviewSobel = menu.add("Sobel"); + mItemPreviewBlur = menu.add("Blur"); + mItemPreviewFeatures = menu.add("Find features"); + return true; + } + + public boolean onOptionsItemSelected(MenuItem item) { + Log.i(TAG, "Menu Item selected " + item); + if (item == mItemPreviewRGBA) + viewMode = VIEW_MODE_RGBA; + else if (item == mItemPreviewGray) + viewMode = VIEW_MODE_GRAY; + else if (item == mItemPreviewCanny) + viewMode = VIEW_MODE_CANNY; + else if (item == mItemPreviewSobel) + viewMode = VIEW_MODE_SOBEL; + else if (item == mItemPreviewBlur) + viewMode = VIEW_MODE_BLUR; + else if (item == mItemPreviewFeatures) + viewMode = VIEW_MODE_FEATURES; + return true; + } +} diff --git a/samples/android/4-mixed/src/org/opencv/samples/s4/Sample4View.java b/samples/android/4-mixed/src/org/opencv/samples/s4/Sample4View.java new file mode 100644 index 0000000000..8cbbe034b8 --- /dev/null +++ b/samples/android/4-mixed/src/org/opencv/samples/s4/Sample4View.java @@ -0,0 +1,179 @@ +package org.opencv.samples.s4; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.hardware.Camera; +import android.hardware.Camera.PreviewCallback; +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +import org.opencv.Mat; +import org.opencv.Size; +import org.opencv.core; +import org.opencv.imgproc; +import org.opencv.utils; + +import java.util.List; + +class Sample4View extends SurfaceView implements SurfaceHolder.Callback, Runnable { + private static final String TAG = "Sample4Mixed::View"; + + private Camera mCamera; + private SurfaceHolder mHolder; + private int mFrameWidth; + private int mFrameHeight; + private byte[] mFrame; + private boolean mThreadRun; + + private Mat mYuv; + private Mat mRgba; + private Mat mGraySubmat; + private Mat mIntermediateMat; + + public Sample4View(Context context) { + super(context); + mHolder = getHolder(); + mHolder.addCallback(this); + } + + public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) { + if ( mCamera != null) { + Camera.Parameters params = mCamera.getParameters(); + List sizes = params.getSupportedPreviewSizes(); + mFrameWidth = width; + mFrameHeight = height; + + //selecting optimal camera preview size + { + double minDiff = Double.MAX_VALUE; + for (Camera.Size size : sizes) { + if (Math.abs(size.height - height) < minDiff) { + mFrameWidth = size.width; + mFrameHeight = size.height; + minDiff = Math.abs(size.height - height); + } + } + } + params.setPreviewSize(mFrameWidth, mFrameHeight); + mCamera.setParameters(params); + mCamera.startPreview(); + + // initialize all required Mats before usage to minimize number of auxiliary jni calls + if(mYuv != null) mYuv.dispose(); + mYuv = new Mat(mFrameHeight+mFrameHeight/2, mFrameWidth, Mat.CvType.CV_8UC1); + + if(mRgba != null) mRgba.dispose(); + mRgba = new Mat(mFrameHeight, mFrameWidth, Mat.CvType.CV_8UC4); + + if(mGraySubmat != null) mGraySubmat.dispose(); + mGraySubmat = mYuv.submat(0, mFrameHeight, 0, mFrameWidth); + + if(mIntermediateMat != null) mIntermediateMat.dispose(); + mIntermediateMat = new Mat(mFrameHeight, mFrameWidth, Mat.CvType.CV_8UC1); + } + } + + public void surfaceCreated(SurfaceHolder holder) { + mCamera = Camera.open(); + mCamera.setPreviewCallback( + new PreviewCallback() { + public void onPreviewFrame(byte[] data, Camera camera) { + synchronized(Sample4View.this) { + mFrame = data; + Sample4View.this.notify(); + } + } + } + ); + (new Thread(this)).start(); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + mThreadRun = false; + if(mCamera != null) { + synchronized(Sample4View.this) { + mCamera.stopPreview(); + mCamera.setPreviewCallback(null); + mCamera.release(); + mCamera = null; + } + } + + // Explicitly dispose Mats + if(mYuv != null) { + mYuv.dispose(); + mYuv = null; + } + if(mRgba != null) { + mRgba.dispose(); + mRgba = null; + } + if(mGraySubmat != null) { + mGraySubmat.dispose(); + mGraySubmat = null; + } + if(mIntermediateMat != null) { + mIntermediateMat.dispose(); + mIntermediateMat = null; + } + } + + public void run() { + mThreadRun = true; + Log.i(TAG, "Starting thread"); + while(mThreadRun) { + synchronized(this) { + try { + this.wait(); + mYuv.put(0, 0, mFrame); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + Sample4Mixed a = (Sample4Mixed)getContext(); + + switch(a.viewMode) + { + case Sample4Mixed.VIEW_MODE_GRAY: + imgproc.cvtColor(mGraySubmat, mRgba, imgproc.CV_GRAY2RGBA, 4); + break; + case Sample4Mixed.VIEW_MODE_RGBA: + imgproc.cvtColor(mYuv, mRgba, imgproc.CV_YUV420i2RGB, 4); + break; + case Sample4Mixed.VIEW_MODE_CANNY: + imgproc.Canny(mGraySubmat, mIntermediateMat, 80, 100); + imgproc.cvtColor(mIntermediateMat, mRgba, imgproc.CV_GRAY2BGRA, 4); + break; + case Sample4Mixed.VIEW_MODE_SOBEL: + imgproc.Sobel(mGraySubmat, mIntermediateMat, core.CV_8U, 1, 1); + core.convertScaleAbs(mIntermediateMat, mIntermediateMat, 8); + imgproc.cvtColor(mIntermediateMat, mRgba, imgproc.CV_GRAY2BGRA, 4); + break; + case Sample4Mixed.VIEW_MODE_BLUR: + imgproc.cvtColor(mYuv, mRgba, imgproc.CV_YUV420i2RGB, 4); + imgproc.blur(mRgba, mRgba, new Size(15, 15)); + break; + case Sample4Mixed.VIEW_MODE_FEATURES: + imgproc.cvtColor(mYuv, mRgba, imgproc.CV_YUV420i2RGB, 4); + FindFeatures(mGraySubmat.getNativeObjAddr(), mRgba.getNativeObjAddr()); + break; + } + + Bitmap bmp = Bitmap.createBitmap(mFrameWidth, mFrameHeight, Bitmap.Config.ARGB_8888); + utils.MatToBitmap(mRgba, bmp); + + Canvas canvas = mHolder.lockCanvas(); + canvas.drawBitmap(bmp, (canvas.getWidth()-mFrameWidth)/2, (canvas.getHeight()-mFrameHeight)/2, null); + mHolder.unlockCanvasAndPost(canvas); + } + } + + public native void FindFeatures(long matAddrGr, long matAddrRgba); + + static { + System.loadLibrary("mixed_sample"); + } +} \ No newline at end of file