diff --git a/samples/android/CMakeLists.txt b/samples/android/CMakeLists.txt
index 0dc4a3cd6..d938580b1 100644
--- a/samples/android/CMakeLists.txt
+++ b/samples/android/CMakeLists.txt
@@ -15,6 +15,10 @@ add_subdirectory(tutorial-1-camerapreview)
add_subdirectory(tutorial-2-mixedprocessing)
add_subdirectory(tutorial-3-cameracontrol)
+if (HAVE_opencv_gpu)
+ add_subdirectory(tutorial-4-cuda)
+endif()
+
add_subdirectory(native-activity)
# hello-android sample
diff --git a/samples/android/tutorial-4-cuda/.classpath b/samples/android/tutorial-4-cuda/.classpath
new file mode 100644
index 000000000..3f9691c5d
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/samples/android/tutorial-4-cuda/.cproject b/samples/android/tutorial-4-cuda/.cproject
new file mode 100644
index 000000000..80a50514d
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/.cproject
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/android/tutorial-4-cuda/.project b/samples/android/tutorial-4-cuda/.project
new file mode 100644
index 000000000..6366dfb64
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/.project
@@ -0,0 +1,101 @@
+
+
+ OpenCV Tutorial 4 - CUDA
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ auto,full,incremental,
+
+
+ ?name?
+
+
+
+ org.eclipse.cdt.make.core.append_environment
+ true
+
+
+ org.eclipse.cdt.make.core.autoBuildTarget
+
+
+
+ org.eclipse.cdt.make.core.buildArguments
+
+
+
+ org.eclipse.cdt.make.core.buildCommand
+ ${NDKROOT}/ndk-build.cmd
+
+
+ org.eclipse.cdt.make.core.cleanBuildTarget
+ clean
+
+
+ org.eclipse.cdt.make.core.contents
+ org.eclipse.cdt.make.core.activeConfigSettings
+
+
+ org.eclipse.cdt.make.core.enableAutoBuild
+ true
+
+
+ org.eclipse.cdt.make.core.enableCleanBuild
+ false
+
+
+ org.eclipse.cdt.make.core.enableFullBuild
+ true
+
+
+ org.eclipse.cdt.make.core.fullBuildTarget
+
+
+
+ org.eclipse.cdt.make.core.stopOnError
+ true
+
+
+ org.eclipse.cdt.make.core.useDefaultBuildCmd
+ false
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/samples/android/tutorial-4-cuda/.settings/org.eclipse.jdt.core.prefs b/samples/android/tutorial-4-cuda/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..b080d2ddc
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/samples/android/tutorial-4-cuda/AndroidManifest.xml b/samples/android/tutorial-4-cuda/AndroidManifest.xml
new file mode 100644
index 000000000..7c8bb0dce
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/AndroidManifest.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/android/tutorial-4-cuda/CMakeLists.txt b/samples/android/tutorial-4-cuda/CMakeLists.txt
new file mode 100644
index 000000000..a011b3349
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(sample example-tutorial-4-cuda)
+
+ocv_check_dependencies(opencv_core opencv_java opencv_gpu)
+
+if (OCV_DEPENDENCIES_FOUND)
+ if(BUILD_FAT_JAVA_LIB)
+ set(native_deps opencv_java opencv_gpu)
+ else()
+ set(native_deps opencv_gpu)
+ endif()
+
+ add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 11 ${ANDROID_SDK_TARGET} NATIVE_DEPS ${native_deps})
+ if(TARGET ${sample})
+ add_dependencies(opencv_android_examples ${sample})
+ endif()
+endif()
diff --git a/samples/android/tutorial-4-cuda/jni/Android.mk b/samples/android/tutorial-4-cuda/jni/Android.mk
new file mode 100644
index 000000000..3d709dff3
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/jni/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+CUDA_TOOLKIT_DIR=$(CUDA_TOOLKIT_ROOT)
+include ../../sdk/native/jni/OpenCV.mk
+
+LOCAL_MODULE := cuda_sample
+LOCAL_SRC_FILES := jni_part.cpp
+LOCAL_LDLIBS += -llog -ldl
+LOCAL_LDFLAGS += -Os
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/samples/android/tutorial-4-cuda/jni/Application.mk b/samples/android/tutorial-4-cuda/jni/Application.mk
new file mode 100644
index 000000000..4fffcb283
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/jni/Application.mk
@@ -0,0 +1,4 @@
+APP_STL := gnustl_static
+APP_CPPFLAGS := -frtti -fexceptions
+APP_ABI := armeabi-v7a
+APP_PLATFORM := android-8
diff --git a/samples/android/tutorial-4-cuda/jni/jni_part.cpp b/samples/android/tutorial-4-cuda/jni/jni_part.cpp
new file mode 100644
index 000000000..fdb47dec1
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/jni/jni_part.cpp
@@ -0,0 +1,35 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+using namespace cv;
+using namespace cv::gpu;
+
+#include
+
+#define LOG_TAG "Cuda"
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+
+extern "C" {
+JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_Tutorial4Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);
+
+JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_Tutorial4Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
+{
+ Mat& mGr = *(Mat*)addrGray;
+ Mat& mRgb = *(Mat*)addrRgba;
+ vector keypoints;
+ GpuMat grGpu(mGr);
+
+ FAST_GPU fast(50);
+ fast(grGpu, GpuMat(), keypoints);
+ for( unsigned int i = 0; i < keypoints.size(); i++ )
+ {
+ const KeyPoint& kp = keypoints[i];
+ circle(mRgb, Point(kp.pt.x, kp.pt.y), 10, Scalar(255,0,0,255));
+ }
+}
+}
diff --git a/samples/android/tutorial-4-cuda/res/drawable/icon.png b/samples/android/tutorial-4-cuda/res/drawable/icon.png
new file mode 100644
index 000000000..630454927
Binary files /dev/null and b/samples/android/tutorial-4-cuda/res/drawable/icon.png differ
diff --git a/samples/android/tutorial-4-cuda/res/layout/tutorial4_surface_view.xml b/samples/android/tutorial-4-cuda/res/layout/tutorial4_surface_view.xml
new file mode 100644
index 000000000..71cd6e04c
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/res/layout/tutorial4_surface_view.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/samples/android/tutorial-4-cuda/res/values/strings.xml b/samples/android/tutorial-4-cuda/res/values/strings.xml
new file mode 100644
index 000000000..ff20b925f
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ OCV T4 CUDA
+
diff --git a/samples/android/tutorial-4-cuda/src/org/opencv/samples/tutorial4/Tutorial4Activity.java b/samples/android/tutorial-4-cuda/src/org/opencv/samples/tutorial4/Tutorial4Activity.java
new file mode 100644
index 000000000..2f6a48a50
--- /dev/null
+++ b/samples/android/tutorial-4-cuda/src/org/opencv/samples/tutorial4/Tutorial4Activity.java
@@ -0,0 +1,166 @@
+package org.opencv.samples.tutorial4;
+
+import org.opencv.android.BaseLoaderCallback;
+import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
+import org.opencv.android.LoaderCallbackInterface;
+import org.opencv.android.OpenCVLoader;
+import org.opencv.core.CvType;
+import org.opencv.core.Mat;
+import org.opencv.android.CameraBridgeViewBase;
+import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
+import org.opencv.imgproc.Imgproc;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.WindowManager;
+
+public class Tutorial4Activity extends Activity implements CvCameraViewListener2 {
+ private static final String TAG = "OCVSample::Activity";
+
+ private static final int VIEW_MODE_RGBA = 0;
+ private static final int VIEW_MODE_GRAY = 1;
+ private static final int VIEW_MODE_CANNY = 2;
+ private static final int VIEW_MODE_FEATURES = 5;
+
+ private int mViewMode;
+ private Mat mRgba;
+ private Mat mIntermediateMat;
+ private Mat mGray;
+
+ private MenuItem mItemPreviewRGBA;
+ private MenuItem mItemPreviewGray;
+ private MenuItem mItemPreviewCanny;
+ private MenuItem mItemPreviewFeatures;
+
+ private CameraBridgeViewBase mOpenCvCameraView;
+
+ private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
+ @Override
+ public void onManagerConnected(int status) {
+ switch (status) {
+ case LoaderCallbackInterface.SUCCESS:
+ {
+ Log.i(TAG, "OpenCV loaded successfully");
+
+ // Load native library after(!) OpenCV initialization
+ System.loadLibrary("cuda_sample");
+
+ mOpenCvCameraView.enableView();
+ } break;
+ default:
+ {
+ super.onManagerConnected(status);
+ } break;
+ }
+ }
+ };
+
+ public Tutorial4Activity() {
+ Log.i(TAG, "Instantiated new " + this.getClass());
+ }
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "called onCreate");
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ setContentView(R.layout.tutorial4_surface_view);
+
+ mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial4_activity_surface_view);
+ mOpenCvCameraView.setCvCameraViewListener(this);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ Log.i(TAG, "called onCreateOptionsMenu");
+ mItemPreviewRGBA = menu.add("Preview RGBA");
+ mItemPreviewGray = menu.add("Preview GRAY");
+ mItemPreviewCanny = menu.add("Canny");
+ mItemPreviewFeatures = menu.add("Find features");
+ return true;
+ }
+
+ @Override
+ public void onPause()
+ {
+ super.onPause();
+ if (mOpenCvCameraView != null)
+ mOpenCvCameraView.disableView();
+ }
+
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+ OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_8, this, mLoaderCallback);
+ }
+
+ public void onDestroy() {
+ super.onDestroy();
+ if (mOpenCvCameraView != null)
+ mOpenCvCameraView.disableView();
+ }
+
+ public void onCameraViewStarted(int width, int height) {
+ mRgba = new Mat(height, width, CvType.CV_8UC4);
+ mIntermediateMat = new Mat(height, width, CvType.CV_8UC4);
+ mGray = new Mat(height, width, CvType.CV_8UC1);
+ }
+
+ public void onCameraViewStopped() {
+ mRgba.release();
+ mGray.release();
+ mIntermediateMat.release();
+ }
+
+ public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
+ final int viewMode = mViewMode;
+ switch (viewMode) {
+ case VIEW_MODE_GRAY:
+ // input frame has gray scale format
+ Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
+ break;
+ case VIEW_MODE_RGBA:
+ // input frame has RBGA format
+ mRgba = inputFrame.rgba();
+ break;
+ case VIEW_MODE_CANNY:
+ // input frame has gray scale format
+ mRgba = inputFrame.rgba();
+ Imgproc.Canny(inputFrame.gray(), mIntermediateMat, 80, 100);
+ Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
+ break;
+ case VIEW_MODE_FEATURES:
+ // input frame has RGBA format
+ mRgba = inputFrame.rgba();
+ mGray = inputFrame.gray();
+ FindFeatures(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr());
+ break;
+ }
+
+ return mRgba;
+ }
+
+ public boolean onOptionsItemSelected(MenuItem item) {
+ Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
+
+ if (item == mItemPreviewRGBA) {
+ mViewMode = VIEW_MODE_RGBA;
+ } else if (item == mItemPreviewGray) {
+ mViewMode = VIEW_MODE_GRAY;
+ } else if (item == mItemPreviewCanny) {
+ mViewMode = VIEW_MODE_CANNY;
+ } else if (item == mItemPreviewFeatures) {
+ mViewMode = VIEW_MODE_FEATURES;
+ }
+
+ return true;
+ }
+
+ public native void FindFeatures(long matAddrGr, long matAddrRgba);
+}