diff --git a/android/Android.mk.in b/android/Android.mk.in
new file mode 100644
index 0000000000..2e895613ce
--- /dev/null
+++ b/android/Android.mk.in
@@ -0,0 +1,13 @@
+LOCAL_PATH := ${CMAKE_CURRENT_SOURCE_DIR}
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ${android_module_name}
+
+LOCAL_SRC_FILES := ${android_srcs}
+
+LOCAL_CFLAGS := ${android_defs}
+
+LOCAL_C_INCLUDES := ${include_dirs} $(LOCAL_PATH)
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/android/Android.mk.master.in b/android/Android.mk.master.in
new file mode 100644
index 0000000000..c810c070be
--- /dev/null
+++ b/android/Android.mk.master.in
@@ -0,0 +1,5 @@
+include android-opencv.mk
+include modules/Android.mk
+include 3rdparty/Android.mk
+include zlib-android/Android.mk
+
diff --git a/android/Android.mk.modules.in b/android/Android.mk.modules.in
new file mode 100644
index 0000000000..8338432200
--- /dev/null
+++ b/android/Android.mk.modules.in
@@ -0,0 +1,2 @@
+include $(call all-subdir-makefiles)
+
diff --git a/android/AndroidCVModule.cmake b/android/AndroidCVModule.cmake
new file mode 100644
index 0000000000..d08de7c402
--- /dev/null
+++ b/android/AndroidCVModule.cmake
@@ -0,0 +1,28 @@
+macro(define_android_manual name lib_srcs includes)
+set(android_module_name ${name})
+set(android_srcs "")
+set(include_dirs "${includes}")
+foreach(f ${lib_srcs})
+ string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" n_f ${f})
+ set(android_srcs "${android_srcs} ${n_f}")
+endforeach()
+configure_file("${CMAKE_SOURCE_DIR}/Android.mk.in" "${CMAKE_CURRENT_BINARY_DIR}/Android.mk")
+endmacro()
+
+
+macro(define_3rdparty_module name)
+ file(GLOB lib_srcs "*.c" "*.cpp")
+ file(GLOB lib_int_hdrs "*.h*")
+ define_android_manual(${name} "${lib_srcs}" "$(LOCAL_PATH)/../include")
+endmacro()
+
+macro(define_opencv_module name)
+ file(GLOB lib_srcs "src/*.cpp")
+ file(GLOB lib_int_hdrs "src/*.h*")
+ define_android_manual(${name} "${lib_srcs}" "$(LOCAL_PATH)/src $(OPENCV_INCLUDES)")
+endmacro()
+
+
+
+
+
diff --git a/android/AndroidManifest.xml.in b/android/AndroidManifest.xml.in
new file mode 100644
index 0000000000..3ce558f302
--- /dev/null
+++ b/android/AndroidManifest.xml.in
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/android/Application.mk.in b/android/Application.mk.in
new file mode 100644
index 0000000000..b7431d5503
--- /dev/null
+++ b/android/Application.mk.in
@@ -0,0 +1,6 @@
+APP_BUILD_SCRIPT := $(call my-dir)/Android.mk
+APP_PROJECT_PATH := $(call my-dir)
+# The ARMv7 is significanly faster due to the use of the hardware FPU
+APP_ABI := armeabi armeabi-v7a
+APP_MODULES := png jpeg jasper zlib opencv_lapack core imgproc ml highgui features2d \
+ legacy objdetect calib3d video contrib flann
diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt
new file mode 100644
index 0000000000..e2cc1f50b3
--- /dev/null
+++ b/android/CMakeLists.txt
@@ -0,0 +1,90 @@
+# ----------------------------------------------------------------------------
+# Root CMake file for Android Opencv Build
+#
+# To build with cmake
+# $ mkdir build
+# $ cd build
+# $ cmake ..
+# $ make
+# Make sure to set the path in the cache for the crystax ndk available
+# here:
+# http://www.crystax.net/android/ndk-r4.php
+#
+# - initial version August 2010 Ethan Rublee ethan.ruble@gmail.com
+#
+# ----------------------------------------------------------------------------
+
+project(android-opencv)
+
+cmake_minimum_required(VERSION 2.8)
+
+include(AndroidCVModule.cmake REQUIRED)
+
+set(opencv_root "${CMAKE_SOURCE_DIR}/.." CACHE STRING "opencv source root directory")
+if(NOT EXISTS ${opencv_root})
+message(FATAL_ERROR "Cannot find your opencv root directory!" )
+endif()
+set(ANDROID true)
+set(WITH_JASPER true)
+set(JASPER_FOUND false)
+set(WITH_PNG true)
+set(WITH_JPEG true)
+
+file(GLOB module_includes "${opencv_root}/modules/[a-zA-Z]*")
+
+list(REMOVE_ITEM module_includes ${opencv_root}/modules/CMakeLists.txt)
+
+set(module_includes ${module_includes} ${CMAKE_SOURCE_DIR}/../3rdparty $(OPENCV_BUILD_ROOT) )
+foreach(mdir ${module_includes})
+ string(REPLACE "${opencv_root}" "$(OPENCV_ROOT)" n_f ${mdir})
+ set(android_module_include_dirs "${android_module_include_dirs} ${n_f}/include")
+endforeach()
+
+configure_file("${CMAKE_SOURCE_DIR}/Android.mk.master.in" "${CMAKE_BINARY_DIR}/Android.mk")
+configure_file("${CMAKE_SOURCE_DIR}/Application.mk.in" "${CMAKE_BINARY_DIR}/Application.mk")
+configure_file("${CMAKE_SOURCE_DIR}/AndroidManifest.xml.in" "${CMAKE_BINARY_DIR}/AndroidManifest.xml")
+configure_file("${CMAKE_SOURCE_DIR}/default.properties.in" "${CMAKE_BINARY_DIR}/default.properties")
+configure_file("${CMAKE_SOURCE_DIR}/cvconfig.h.in" "${CMAKE_BINARY_DIR}/include/cvconfig.h")
+
+add_subdirectory(${CMAKE_SOURCE_DIR}/zlib-android)
+
+
+add_subdirectory(${opencv_root}/modules "${CMAKE_BINARY_DIR}/modules")
+
+
+add_subdirectory(${opencv_root}/3rdparty "${CMAKE_BINARY_DIR}/3rdparty")
+
+set(NDK_ROOT "$ENV{HOME}/android-ndk-r4-crystax" CACHE STRING "the crystax ndk directory")
+if(NOT EXISTS ${NDK_ROOT})
+message(FATAL_ERROR "Cannot find your ndk root directory! please download and
+unzip the android ndk from crystax to the directory specified by NDK_ROOT
+You may download the crystax ndk from:
+ http://www.crystax.net/android/ndk-r4.php" )
+endif()
+set(J "2" CACHE STRING "how many processes for make -j ")
+
+ADD_CUSTOM_COMMAND(
+OUTPUT android-opencv
+DEPENDS ${CMAKE_BINARY_DIR}/Android.mk
+COMMAND "${NDK_ROOT}/ndk-build"
+ARGS --directory=${CMAKE_BINARY_DIR} NDK_APPLICATION_MK=Application.mk -j${J}
+)
+
+configure_file("${CMAKE_SOURCE_DIR}/android-opencv.mk.in" "${CMAKE_BINARY_DIR}/android-opencv.mk")
+
+ADD_CUSTOM_TARGET(ndk ALL echo
+ DEPENDS android-opencv
+)
+
+message(STATUS "Make will use make -j${J} - for speeding up build - you may change this in the cache")
+message(STATUS "The NDK directory is ${NDK_ROOT}")
+message(STATUS "OpenCV source root is ${opencv_root}")
+message(STATUS "just run make - and grab some coffee or tea ;)")
+message(STATUS "The android opencv libs will be located in ${CMAKE_BINARY_DIR}/obj/local/armeabi*/")
+
+
+
+
+
+
+
diff --git a/android/README.android.txt b/android/README.android.txt
new file mode 100644
index 0000000000..0e96e96021
--- /dev/null
+++ b/android/README.android.txt
@@ -0,0 +1,35 @@
+Author: Ethan Rublee
+email: ethan.rublee@gmail.com
+
+
+To build with cmake:
+
+mkdir build
+cd build
+cmake ..
+make
+
+
+
+Make sure to set the path in the cache for the crystax ndk available
+here:
+ http://www.crystax.net/android/ndk-r4.php
+
+
+to include in an android project -
+just include the generated android-opencv.mk in you android ndk project
+with:
+
+include android-opencv.mk
+
+this defines OPENCV_INCLUDES and OPENCV_LIBS - which you should add to your
+makefiles like:
+
+#define OPENCV_INCLUDES and OPENCV_LIBS
+include $(PATH_TO_OPENCV_ANDROID_BUILD)/android-opencv.mk
+
+LOCAL_LDLIBS += $(OPENCV_LIBS)
+
+LOCAL_C_INCLUDES += $(OPENCV_INCLUDES)
+
+
diff --git a/android/android-cmake/CMakeLists.txt b/android/android-cmake/CMakeLists.txt
new file mode 100644
index 0000000000..b545d173ba
--- /dev/null
+++ b/android/android-cmake/CMakeLists.txt
@@ -0,0 +1,90 @@
+# ----------------------------------------------------------------------------
+# Root CMake file for Android Opencv Build
+#
+# To build with cmake
+# $ mkdir build
+# $ cd build
+# $ cmake ..
+# $ make
+# Make sure to set the path in the cache for the crystax ndk available
+# here:
+# http://www.crystax.net/android/ndk-r4.php
+#
+# - initial version August 2010 Ethan Rublee ethan.ruble@gmail.com
+#
+# ----------------------------------------------------------------------------
+
+project(android-opencv-shared)
+
+cmake_minimum_required(VERSION 2.8)
+
+set(opencv_root "$ENV{HOME}/opencv" CACHE PATH "opencv source root directory")
+if(NOT EXISTS ${opencv_root})
+message(FATAL_ERROR "Cannot find your opencv root directory!" )
+endif()
+
+set(android_opencv_mk "${opencv_root}/android/build/android-opencv.mk" cache FILE "the generated android-opencv.mk file")
+if(NOT EXISTS ${android_opencv_mk})
+message(FATAL_ERROR "please locate the cmake generated android-opencv.mk file, usually in the android/build directory...")
+endif()
+
+set(ANDROID true)
+
+file(GLOB module_includes "${opencv_root}/modules/[a-zA-Z]*")
+
+list(REMOVE_ITEM module_includes ${opencv_root}/modules/CMakeLists.txt)
+
+set(module_includes ${module_includes} ${CMAKE_SOURCE_DIR}/../3rdparty $(OPENCV_BUILD_ROOT) )
+foreach(mdir ${module_includes})
+ string(REPLACE "${opencv_root}" "$(OPENCV_ROOT)" n_f ${mdir})
+ set(android_module_include_dirs "${android_module_include_dirs} ${n_f}/include")
+endforeach()
+
+configure_file("${CMAKE_SOURCE_DIR}/Android.mk.master.in" "${CMAKE_BINARY_DIR}/Android.mk")
+configure_file("${CMAKE_SOURCE_DIR}/Application.mk.in" "${CMAKE_BINARY_DIR}/Application.mk")
+configure_file("${CMAKE_SOURCE_DIR}/AndroidManifest.xml.in" "${CMAKE_BINARY_DIR}/AndroidManifest.xml")
+configure_file("${CMAKE_SOURCE_DIR}/default.properties.in" "${CMAKE_BINARY_DIR}/default.properties")
+
+set(NDK_ROOT "$ENV{HOME}/android-ndk-r4-crystax" CACHE STRING "the crystax ndk directory")
+if(NOT EXISTS ${NDK_ROOT})
+message(FATAL_ERROR "Cannot find your ndk root directory! please download and
+unzip the android ndk from crystax to the directory specified by NDK_ROOT
+You may download the crystax ndk from:
+ http://www.crystax.net/android/ndk-r4.php" )
+endif()
+
+set(J "2" CACHE STRING "how many processes for make -j ")
+
+ADD_CUSTOM_COMMAND(
+OUTPUT android-ndk
+DEPENDS ${CMAKE_BINARY_DIR}/Android.mk
+COMMAND "${NDK_ROOT}/ndk-build"
+ARGS --directory=${CMAKE_BINARY_DIR} NDK_APPLICATION_MK=Application.mk -j${J}
+)
+
+ADD_CUSTOM_COMMAND(
+OUTPUT android-swig
+DEPENDS ${SWIG_MAIN}
+COMMAND "swig"
+ARGS --directory=${CMAKE_BINARY_DIR} NDK_APPLICATION_MK=Application.mk -j${J}
+)
+
+
+configure_file("${CMAKE_SOURCE_DIR}/android-opencv.mk.in" "${CMAKE_BINARY_DIR}/android-opencv.mk")
+
+ADD_CUSTOM_TARGET(ndk ALL echo
+ DEPENDS android-ndk
+)
+
+message(STATUS "Make will use make -j${J} - for speeding up build - you may change this in the cache")
+message(STATUS "The NDK directory is ${NDK_ROOT}")
+message(STATUS "OpenCV source root is ${opencv_root}")
+message(STATUS "just run make - and grab some coffee or tea ;)")
+message(STATUS "The android opencv libs will be located in ${CMAKE_BINARY_DIR}/obj/local/armeabi*/")
+
+
+
+
+
+
+
diff --git a/android/android-jni/AndroidManifest.xml b/android/android-jni/AndroidManifest.xml
new file mode 100644
index 0000000000..64b428a1fd
--- /dev/null
+++ b/android/android-jni/AndroidManifest.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/android-jni/Makefile b/android/android-jni/Makefile
new file mode 100644
index 0000000000..252fde4532
--- /dev/null
+++ b/android/android-jni/Makefile
@@ -0,0 +1,75 @@
+# The path to the NDK, requires crystax version r-4 for now, due to support
+#for the standard library
+
+#load environment from local make file
+LOCAL_ENV_MK=local.env.mk
+ifneq "$(wildcard $(LOCAL_ENV_MK))" ""
+include $(LOCAL_ENV_MK)
+else
+$(shell cp sample.$(LOCAL_ENV_MK) $(LOCAL_ENV_MK))
+$(info ERROR local environement not setup! try:)
+$(info gedit $(LOCAL_ENV_MK))
+$(info Please setup the $(LOCAL_ENV_MK) - the default was just created')
+include $(LOCAL_ENV_MK)
+endif
+
+ANDROID_NDK_BASE = $(ANDROID_NDK_ROOT)
+
+$(info OPENCV_CONFIG = $(OPENCV_CONFIG))
+
+# The name of the native library
+LIBNAME = libandroid-opencv.so
+
+# Find all the C++ sources in the native folder
+SOURCES = $(wildcard jni/*.cpp)
+HEADERS = $(wildcard jni/*.h)
+SWIG_IS = $(wildcard jni/*.i)
+
+ANDROID_MKS = $(wildcard jni/*.mk)
+
+SWIG_MAIN = jni/android-cv.i
+
+SWIG_JAVA_DIR = src/com/opencv/jni
+SWIG_JAVA_OUT = $(wildcard $(SWIG_JAVA_DIR)/*.java)
+
+SWIG_C_DIR = jni/gen
+SWIG_C_OUT = $(SWIG_C_DIR)/android_cv_wrap.cpp
+
+# The real native library stripped of symbols
+LIB = libs/armeabi-v7a/$(LIBNAME) libs/armeabi/$(LIBNAME)
+
+
+all: $(LIB)
+
+
+#calls the ndk-build script, passing it OPENCV_ROOT and OPENCV_LIBS_DIR
+$(LIB): $(SWIG_C_OUT) $(SOURCES) $(HEADERS) $(ANDROID_MKS)
+ $(ANDROID_NDK_BASE)/ndk-build OPENCV_CONFIG=$(OPENCV_CONFIG) \
+ PROJECT_PATH=$(PROJECT_PATH) V=$(V) $(NDK_FLAGS)
+
+
+#this creates the swig wrappers
+$(SWIG_C_OUT): $(SWIG_IS)
+ make clean-swig &&\
+ mkdir -p $(SWIG_C_DIR) &&\
+ mkdir -p $(SWIG_JAVA_DIR) &&\
+ swig -java -c++ -package "com.opencv.jni" \
+ -outdir $(SWIG_JAVA_DIR) \
+ -o $(SWIG_C_OUT) $(SWIG_MAIN)
+
+
+#clean targets
+.PHONY: clean clean-swig cleanall nogdb
+
+nogdb: $(LIB)
+ rm -f libs/armeabi*/gdb*
+
+#this deletes the generated swig java and the generated c wrapper
+clean-swig:
+ rm -f $(SWIG_JAVA_OUT) $(SWIG_C_OUT)
+
+#does clean-swig and then uses the ndk-build clean
+clean: clean-swig
+ $(ANDROID_NDK_BASE)/ndk-build OPENCV_CONFIG=$(OPENCV_CONFIG) \
+ PROJECT_PATH=$(PROJECT_PATH) clean V=$(V) $(NDK_FLAGS)
+
diff --git a/android/android-jni/README.txt b/android/android-jni/README.txt
new file mode 100644
index 0000000000..65ea9124d0
--- /dev/null
+++ b/android/android-jni/README.txt
@@ -0,0 +1,18 @@
+android-opencv
+
+this is an example of an android library project that has some reusable
+code that exposes part of OpenCV to android. In particular this provides a
+native camera interface for loading live video frames from the android camera
+into native opencv functions(as cv::Mat's)
+
+to build make sure you have swig and the crystax ndk in your path
+
+cp sample.local.env.mk local.env.mk
+make
+
+that should work...
+
+more later on how to build actual project for android
+ - see the code.google.com/p/android-opencv for details on this
+
+
diff --git a/android/android-jni/default.properties b/android/android-jni/default.properties
new file mode 100644
index 0000000000..b586c7619c
--- /dev/null
+++ b/android/android-jni/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.
+
+android.library=true
+# Project target.
+target=android-7
diff --git a/android/android-jni/jni/Android.mk b/android/android-jni/jni/Android.mk
new file mode 100644
index 0000000000..98b101c8e9
--- /dev/null
+++ b/android/android-jni/jni/Android.mk
@@ -0,0 +1,22 @@
+# date: Summer, 2010
+# author: Ethan Rublee
+# contact: ethan.rublee@gmail.com
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+#define OPENCV_INCLUDES and OPENCV_LIBS
+include $(OPENCV_CONFIG)
+
+LOCAL_LDLIBS += $(OPENCV_LIBS) -llog -lGLESv2
+
+LOCAL_C_INCLUDES += $(OPENCV_INCLUDES)
+
+LOCAL_MODULE := android-opencv
+
+LOCAL_SRC_FILES := gen/android_cv_wrap.cpp image_pool.cpp \
+ yuv420sp2rgb.c gl_code.cpp Calibration.cpp
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/android/android-jni/jni/Application.mk b/android/android-jni/jni/Application.mk
new file mode 100644
index 0000000000..37e67d8703
--- /dev/null
+++ b/android/android-jni/jni/Application.mk
@@ -0,0 +1,4 @@
+# The ARMv7 is significanly faster due to the use of the hardware FPU
+APP_ABI := armeabi armeabi-v7a
+APP_BUILD_SCRIPT := $(call my-dir)/Android.mk
+APP_PROJECT_PATH := $(PROJECT_PATH)
\ No newline at end of file
diff --git a/android/android-jni/jni/Calibration.cpp b/android/android-jni/jni/Calibration.cpp
new file mode 100644
index 0000000000..c9df5ee2ed
--- /dev/null
+++ b/android/android-jni/jni/Calibration.cpp
@@ -0,0 +1,261 @@
+/*
+ * Processor.cpp
+ *
+ * Created on: Jun 13, 2010
+ * Author: ethan
+ */
+
+#include "Calibration.h"
+
+
+#include
+
+using namespace cv;
+
+Calibration::Calibration():patternsize(6,8)
+{
+
+}
+
+Calibration::~Calibration() {
+
+}
+
+
+namespace
+{
+double computeReprojectionErrors(
+ const vector >& objectPoints, const vector >& imagePoints, const vector& rvecs,
+ const vector& tvecs, const Mat& cameraMatrix,
+ const Mat& distCoeffs, vector& perViewErrors) {
+ vector imagePoints2;
+ int i, totalPoints = 0;
+ double totalErr = 0, err;
+ perViewErrors.resize(objectPoints.size());
+
+ for (i = 0; i < (int) objectPoints.size(); i++) {
+ projectPoints(Mat(objectPoints[i]), rvecs[i], tvecs[i], cameraMatrix,
+ distCoeffs, imagePoints2);
+ err = norm(Mat(imagePoints[i]), Mat(imagePoints2), CV_L1 );
+ int n = (int) objectPoints[i].size();
+ perViewErrors[i] = err / n;
+ totalErr += err;
+ totalPoints += n;
+ }
+
+ return totalErr / totalPoints;
+}
+
+
+void calcChessboardCorners(Size boardSize, float squareSize, vector<
+ Point3f>& corners) {
+ corners.resize(0);
+
+ for (int i = 0; i < boardSize.height; i++)
+ for (int j = 0; j < boardSize.width; j++)
+ corners.push_back(Point3f(float(j * squareSize), float(i
+ * squareSize), 0));
+}
+
+/**from opencv/samples/cpp/calibration.cpp
+ *
+ */
+bool runCalibration(vector > imagePoints,
+ Size imageSize, Size boardSize, float squareSize, float aspectRatio,
+ int flags, Mat& cameraMatrix, Mat& distCoeffs, vector& rvecs,
+ vector& tvecs, vector& reprojErrs, double& totalAvgErr) {
+ cameraMatrix = Mat::eye(3, 3, CV_64F);
+ if (flags & CV_CALIB_FIX_ASPECT_RATIO)
+ cameraMatrix.at (0, 0) = aspectRatio;
+
+ distCoeffs = Mat::zeros(5, 1, CV_64F);
+
+ vector > objectPoints(1);
+ calcChessboardCorners(boardSize, squareSize, objectPoints[0]);
+ for (size_t i = 1; i < imagePoints.size(); i++)
+ objectPoints.push_back(objectPoints[0]);
+
+ calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix,
+ distCoeffs, rvecs, tvecs, flags);
+
+ bool ok = checkRange(cameraMatrix, CV_CHECK_QUIET ) && checkRange(
+ distCoeffs, CV_CHECK_QUIET );
+
+ totalAvgErr = computeReprojectionErrors(objectPoints, imagePoints, rvecs,
+ tvecs, cameraMatrix, distCoeffs, reprojErrs);
+
+ return ok;
+}
+void saveCameraParams(const string& filename, Size imageSize, Size boardSize,
+ float squareSize, float aspectRatio, int flags,
+ const Mat& cameraMatrix, const Mat& distCoeffs,
+ const vector& rvecs, const vector& tvecs,
+ const vector& reprojErrs,
+ const vector >& imagePoints, double totalAvgErr) {
+ FileStorage fs(filename, FileStorage::WRITE);
+
+ time_t t;
+ time(&t);
+ struct tm *t2 = localtime(&t);
+ char buf[1024];
+ strftime(buf, sizeof(buf) - 1, "%c", t2);
+
+ fs << "calibration_time" << buf;
+
+ if (!rvecs.empty() || !reprojErrs.empty())
+ fs << "nframes" << (int) std::max(rvecs.size(), reprojErrs.size());
+ fs << "image_width" << imageSize.width;
+ fs << "image_height" << imageSize.height;
+ fs << "board_width" << boardSize.width;
+ fs << "board_height" << boardSize.height;
+ fs << "squareSize" << squareSize;
+
+ if (flags & CV_CALIB_FIX_ASPECT_RATIO)
+ fs << "aspectRatio" << aspectRatio;
+
+ if (flags != 0) {
+ sprintf(buf, "flags: %s%s%s%s",
+ flags & CV_CALIB_USE_INTRINSIC_GUESS ? "+use_intrinsic_guess"
+ : "",
+ flags & CV_CALIB_FIX_ASPECT_RATIO ? "+fix_aspectRatio" : "",
+ flags & CV_CALIB_FIX_PRINCIPAL_POINT ? "+fix_principal_point"
+ : "",
+ flags & CV_CALIB_ZERO_TANGENT_DIST ? "+zero_tangent_dist" : "");
+ cvWriteComment(*fs, buf, 0);
+ }
+
+ fs << "flags" << flags;
+
+ fs << "camera_matrix" << cameraMatrix;
+ fs << "distortion_coefficients" << distCoeffs;
+
+ fs << "avg_reprojection_error" << totalAvgErr;
+ if (!reprojErrs.empty())
+ fs << "per_view_reprojection_errors" << Mat(reprojErrs);
+
+ if (!rvecs.empty() && !tvecs.empty()) {
+ Mat bigmat(rvecs.size(), 6, CV_32F);
+ for (size_t i = 0; i < rvecs.size(); i++) {
+ Mat r = bigmat(Range(i, i + 1), Range(0, 3));
+ Mat t = bigmat(Range(i, i + 1), Range(3, 6));
+ rvecs[i].copyTo(r);
+ tvecs[i].copyTo(t);
+ }
+ cvWriteComment(
+ *fs,
+ "a set of 6-tuples (rotation vector + translation vector) for each view",
+ 0);
+ fs << "extrinsic_parameters" << bigmat;
+ }
+
+ if (!imagePoints.empty()) {
+ Mat imagePtMat(imagePoints.size(), imagePoints[0].size(), CV_32FC2);
+ for (size_t i = 0; i < imagePoints.size(); i++) {
+ Mat r = imagePtMat.row(i).reshape(2, imagePtMat.cols);
+ Mat(imagePoints[i]).copyTo(r);
+ }
+ fs << "image_points" << imagePtMat;
+ }
+}
+}//anon namespace
+bool Calibration::detectAndDrawChessboard(int idx,image_pool* pool) {
+
+ Mat grey;
+ pool->getGrey(idx, grey);
+ if (grey.empty())
+ return false;
+ vector corners;
+
+
+ IplImage iplgrey = grey;
+ if (!cvCheckChessboard(&iplgrey, patternsize))
+ return false;
+ bool patternfound = findChessboardCorners(grey, patternsize, corners);
+
+ Mat * img = pool->getImage(idx);
+
+ if (corners.size() < 1)
+ return false;
+
+ cornerSubPix(grey, corners, Size(11, 11), Size(-1, -1), TermCriteria(
+ CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
+
+ if(patternfound)
+ imagepoints.push_back(corners);
+
+ drawChessboardCorners(*img, patternsize, Mat(corners), patternfound);
+
+ imgsize = grey.size();
+
+ return patternfound;
+
+}
+
+void Calibration::drawText(int i, image_pool* pool, const char* ctext){
+ // Use "y" to show that the baseLine is about
+ string text = ctext;
+ int fontFace = FONT_HERSHEY_COMPLEX_SMALL;
+ double fontScale = .8;
+ int thickness = .5;
+
+ Mat img = *pool->getImage(i);
+
+ int baseline=0;
+ Size textSize = getTextSize(text, fontFace,
+ fontScale, thickness, &baseline);
+ baseline += thickness;
+
+ // center the text
+ Point textOrg((img.cols - textSize.width)/2,
+ (img.rows - textSize.height *2));
+
+ // draw the box
+ rectangle(img, textOrg + Point(0, baseline),
+ textOrg + Point(textSize.width, -textSize.height),
+ Scalar(0,0,255),CV_FILLED);
+ // ... and the baseline first
+ line(img, textOrg + Point(0, thickness),
+ textOrg + Point(textSize.width, thickness),
+ Scalar(0, 0, 255));
+
+ // then put the text itself
+ putText(img, text, textOrg, fontFace, fontScale,
+ Scalar::all(255), thickness, 8);
+}
+
+void Calibration::resetChess() {
+
+ imagepoints.clear();
+}
+
+void Calibration::calibrate(const char* filename) {
+
+ vector rvecs, tvecs;
+ vector reprojErrs;
+ double totalAvgErr = 0;
+ int flags = 0;
+ flags |= CV_CALIB_FIX_PRINCIPAL_POINT | CV_CALIB_FIX_ASPECT_RATIO;
+ bool writeExtrinsics = true;
+ bool writePoints = true;
+
+ bool ok = runCalibration(imagepoints, imgsize, patternsize, 1.f, 1.f,
+ flags, K, distortion, rvecs, tvecs, reprojErrs, totalAvgErr);
+
+
+
+ if (ok){
+
+ saveCameraParams(filename, imgsize, patternsize, 1.f,
+ 1.f, flags, K, distortion, writeExtrinsics ? rvecs
+ : vector (), writeExtrinsics ? tvecs
+ : vector (), writeExtrinsics ? reprojErrs
+ : vector (), writePoints ? imagepoints : vector<
+ vector > (), totalAvgErr);
+ }
+
+}
+
+int Calibration::getNumberDetectedChessboards() {
+ return imagepoints.size();
+}
diff --git a/android/android-jni/jni/Calibration.h b/android/android-jni/jni/Calibration.h
new file mode 100644
index 0000000000..f3a9453ea9
--- /dev/null
+++ b/android/android-jni/jni/Calibration.h
@@ -0,0 +1,59 @@
+/*
+ * Processor.h
+ *
+ * Created on: Jun 13, 2010
+ * Author: ethan
+ */
+
+#ifndef PROCESSOR_H_
+#define PROCESSOR_H_
+
+#include
+#include
+#include
+#include
+#include
+
+
+
+#include
+
+#include "image_pool.h"
+
+#define DETECT_FAST 0
+#define DETECT_STAR 1
+#define DETECT_SURF 2
+
+
+class Calibration {
+ std::vector keypoints;
+
+ vector > imagepoints;
+
+ cv::Mat K;
+ cv::Mat distortion;
+ cv::Size imgsize;
+
+
+
+public:
+
+ cv::Size patternsize;
+
+ Calibration();
+ virtual ~Calibration();
+
+ bool detectAndDrawChessboard(int idx, image_pool* pool);
+
+ void resetChess();
+
+ int getNumberDetectedChessboards();
+
+ void calibrate(const char* filename);
+
+ void drawText(int idx, image_pool* pool, const char* text);
+};
+
+
+
+#endif /* PROCESSOR_H_ */
diff --git a/android/android-jni/jni/Calibration.i b/android/android-jni/jni/Calibration.i
new file mode 100644
index 0000000000..ba6154b3c7
--- /dev/null
+++ b/android/android-jni/jni/Calibration.i
@@ -0,0 +1,28 @@
+/*
+ * include the headers required by the generated cpp code
+ */
+%{
+#include "Calibration.h"
+#include "image_pool.h"
+using namespace cv;
+%}
+
+
+class Calibration {
+public:
+
+ Size patternsize;
+
+ Calibration();
+ virtual ~Calibration();
+
+ bool detectAndDrawChessboard(int idx, image_pool* pool);
+
+ void resetChess();
+
+ int getNumberDetectedChessboards();
+
+ void calibrate(const char* filename);
+
+ void drawText(int idx, image_pool* pool, const char* text);
+};
diff --git a/android/android-jni/jni/android-cv-typemaps.i b/android/android-jni/jni/android-cv-typemaps.i
new file mode 100644
index 0000000000..cae2d6b63b
--- /dev/null
+++ b/android/android-jni/jni/android-cv-typemaps.i
@@ -0,0 +1,6 @@
+%feature("director") Mat;
+%feature("director") glcamera;
+%feature("director") image_pool;
+%typemap("javapackage") Mat, Mat *, Mat & "com.opencv.jni";
+%typemap("javapackage") glcamera, glcamera *, glcamera & "com.opencv.jni";
+%typemap("javapackage") image_pool, image_pool *, image_pool & "com.opencv.jni";
\ No newline at end of file
diff --git a/android/android-jni/jni/android-cv.i b/android/android-jni/jni/android-cv.i
new file mode 100644
index 0000000000..c8f9364dc2
--- /dev/null
+++ b/android/android-jni/jni/android-cv.i
@@ -0,0 +1,57 @@
+/* File : android-cv.i
+
+import this file, and make sure to add the System.loadlibrary("android-opencv")
+before loading any lib that depends on this.
+ */
+
+%module opencv
+%{
+#include "image_pool.h"
+#include "glcamera.h"
+
+using namespace cv;
+%}
+#ifndef SWIGIMPORTED
+%include "various.i"
+%include "typemaps.i"
+%include "arrays_java.i"
+#endif
+
+/**
+ * Make all the swig pointers public, so that
+ * external libraries can refer to these, otherwise they default to
+ * protected...
+ */
+%typemap(javabody) SWIGTYPE %{
+ private long swigCPtr;
+ protected boolean swigCMemOwn;
+ public $javaclassname(long cPtr, boolean cMemoryOwn) {
+ swigCMemOwn = cMemoryOwn;
+ swigCPtr = cPtr;
+ }
+ public static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+%}
+
+%pragma(java) jniclasscode=%{
+ static {
+ try {
+ //load the library, make sure that libandroid-opencv.so is in your /libs/armeabi directory
+ //so that android sdk automatically installs it along with the app.
+ System.loadLibrary("android-opencv");
+ } catch (UnsatisfiedLinkError e) {
+ //badness
+ throw e;
+
+ }
+ }
+%}
+
+%include "cv.i"
+
+%include "glcamera.i"
+
+%include "image_pool.i"
+
+%include "Calibration.i"
diff --git a/android/android-jni/jni/buffers.i b/android/android-jni/jni/buffers.i
new file mode 100644
index 0000000000..d60112096c
--- /dev/null
+++ b/android/android-jni/jni/buffers.i
@@ -0,0 +1,165 @@
+/*
+ * These typemaps provide support for sharing data between JNI and JVM code
+ * using NIO direct buffers. It is the responsibility of the JVM code to
+ * allocate a direct buffer of the appropriate size.
+ *
+ * Example use:
+
+ * Wrapping:
+ * %include "buffers.i"
+ * %apply int* BUFF {int* buffer}
+ * int read_foo_int(int* buffer);
+ *
+ * Java:
+ * IntBuffer buffer = IntBuffer.allocateDirect(nInts*4).order(ByteOrder.nativeOrder()).asIntBuffer();
+ * Example.read_foo_int(buffer);
+ *
+
+ * The following typemaps are defined:
+ * void* BUFF <--> javax.nio.Buffer
+ * char* BUFF <--> javax.nio.ByteBuffer
+ * char* CBUFF <--> javax.nio.CharBuffer
+ * unsigned char* INBUFF/OUTBUFF <--> javax.nio.ShortBuffer
+ * short* BUFF <--> javax.nio.ShortBuffer
+ * unsigned short* INBUFF/OUTBUFF <--> javax.nio.IntBuffer
+ * int* BUFF <--> javax.nio.IntBuffer
+ * unsigned int* INBUFF/OUTBUFF <--> javax.nio.LongBuffer
+ * long* BUFF <--> javax.nio.IntBuffer
+ * unsigned long* INBUFF/OUTBUF <--> javax.nio.LongBuffer
+ * long long* BUFF <--> javax.nio.LongBuffer
+ * float* BUFF <--> javax.nio.FloatBuffer
+ * double* BUFF <--> javax.nio.DoubleBuffer
+ *
+ * Note the potential for data loss in the conversion from
+ * the C type 'unsigned long' to the signed Java long type.
+ * Hopefully, I can implement a workaround with BigNumber in the future.
+ *
+ * The use of ByteBuffer vs CharBuffer for the char* type should
+ * depend on the type of data. In general you'll probably
+ * want to use CharBuffer for actual text data.
+ */
+/*
+ * This macro is used to define the nio buffers for primitive types.
+ */
+%define NIO_BUFFER_TYPEMAP(CTYPE, LABEL, BUFFERTYPE)
+%typemap(jni) CTYPE* LABEL "jobject"
+%typemap(jtype) CTYPE* LABEL "BUFFERTYPE"
+%typemap(jstype) CTYPE* LABEL "BUFFERTYPE"
+%typemap(javain,
+ pre=" assert $javainput.isDirect() : \"Buffer must be allocated direct.\";") CTYPE* LABEL "$javainput"
+%typemap(javaout) CTYPE* LABEL {
+ return $jnicall;
+}
+%typemap(in) CTYPE* LABEL {
+ $1 = (*jenv)->GetDirectBufferAddress(jenv, $input);
+ if ($1 == NULL) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "Unable to get address of direct buffer. Buffer must be allocated direct.");
+ }
+}
+%typemap(memberin) CTYPE* LABEL {
+ if ($input) {
+ $1 = $input;
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(freearg) CTYPE* LABEL ""
+%enddef
+
+NIO_BUFFER_TYPEMAP(void, BUFF, java.nio.Buffer);
+NIO_BUFFER_TYPEMAP(char, BUFF, java.nio.ByteBuffer);
+NIO_BUFFER_TYPEMAP(char, CBUFF, java.nio.CharBuffer);
+/*NIO_BUFFER_TYPEMAP(unsigned char, BUFF, java.nio.ShortBuffer);*/
+NIO_BUFFER_TYPEMAP(short, BUFF, java.nio.ShortBuffer);
+NIO_BUFFER_TYPEMAP(unsigned short, BUFF, java.nio.IntBuffer);
+NIO_BUFFER_TYPEMAP(int, BUFF, java.nio.IntBuffer);
+NIO_BUFFER_TYPEMAP(unsigned int, BUFF, java.nio.LongBuffer);
+NIO_BUFFER_TYPEMAP(long, BUFF, java.nio.IntBuffer);
+NIO_BUFFER_TYPEMAP(unsigned long, BUFF, java.nio.LongBuffer);
+NIO_BUFFER_TYPEMAP(long long, BUFF, java.nio.LongBuffer);
+NIO_BUFFER_TYPEMAP(float, BUFF, java.nio.FloatBuffer);
+NIO_BUFFER_TYPEMAP(double, BUFF, java.nio.DoubleBuffer);
+#undef NIO_BUFFER_TYPEMAP
+
+
+%define UNSIGNED_NIO_BUFFER_TYPEMAP(CTYPE, BSIZE, BUFFERTYPE, PACKFCN, UNPACKFCN)
+%typemap(jni) CTYPE* INBUFF "jobject"
+%typemap(jtype) CTYPE* INBUFF "java.nio.ByteBuffer"
+%typemap(jstype) CTYPE* INBUFF "BUFFERTYPE"
+%typemap(javain,
+ pre=" java.nio.ByteBuffer tmp$javainput = PACKFCN($javainput, true);") CTYPE* INBUFF "tmp$javainput"
+%typemap(javaout) CTYPE* INBUFF {
+ return $jnicall;
+}
+%typemap(in) CTYPE* INBUFF {
+ $1 = (*jenv)->GetDirectBufferAddress(jenv, $input);
+ if ($1 == NULL) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "Unable to get address of direct buffer. Buffer must be allocated direct.");
+ }
+}
+%typemap(memberin) CTYPE* INBUFF {
+ if ($input) {
+ $1 = $input;
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(freearg) CTYPE* INBUFF ""
+
+%typemap(jni) CTYPE* OUTBUFF "jobject"
+%typemap(jtype) CTYPE* OUTBUFF "java.nio.ByteBuffer"
+%typemap(jstype) CTYPE* OUTBUFF "BUFFERTYPE"
+%typemap(javain,
+ pre=" java.nio.ByteBuffer tmp$javainput = java.nio.ByteBuffer.allocateDirect($javainput.capacity()*BSIZE).order($javainput.order());",
+ post=" UNPACKFCN(tmp$javainput, $javainput);") CTYPE* OUTBUFF "tmp$javainput"
+%typemap(javaout) CTYPE* OUTBUFF {
+ return $jnicall;
+}
+%typemap(in) CTYPE* OUTBUFF {
+ $1 = (*jenv)->GetDirectBufferAddress(jenv, $input);
+ if ($1 == NULL) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "Unable to get address of direct buffer. Buffer must be allocated direct.");
+ }
+}
+%typemap(memberin) CTYPE* OUTBUFF {
+ if ($input) {
+ $1 = $input;
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(freearg) CTYPE* OUTBUFF ""
+%enddef
+
+UNSIGNED_NIO_BUFFER_TYPEMAP(unsigned char, 1, java.nio.ShortBuffer, permafrost.hdf.libhdf.BufferUtils.packUChar, permafrost.hdf.libhdf.BufferUtils.unpackUChar);
+UNSIGNED_NIO_BUFFER_TYPEMAP(unsigned short, 2, java.nio.IntBuffer, permafrost.hdf.libhdf.BufferUtils.packUShort, permafrost.hdf.libhdf.BufferUtils.unpackUShort);
+UNSIGNED_NIO_BUFFER_TYPEMAP(unsigned int, 4, java.nio.LongBuffer, permafrost.hdf.libhdf.BufferUtils.packUInt, permafrost.hdf.libhdf.BufferUtils.unpackUInt);
+UNSIGNED_NIO_BUFFER_TYPEMAP(unsigned long, 4, java.nio.LongBuffer, permafrost.hdf.libhdf.BufferUtils.packUInt, permafrost.hdf.libhdf.BufferUtils.unpackUInt);
+
+/*
+%typemap(jni) unsigned char* BUFF "jobject"
+%typemap(jtype) unsigned char* BUFF "java.nio.ByteBuffer"
+%typemap(jstype) unsigned char* BUFF "java.nio.ShortBuffer"
+%typemap(javain,
+ pre=" java.nio.ByteBuffer tmp$javainput = permafrost.hdf.libhdf.BufferUtils.packUChar($javainput, true);",
+ post=" permafrost.hdf.libhdf.BufferUtils.unpackUChar(tmp$javainput, $javainput);") unsigned char* BUFF "tmp$javainput"
+%typemap(javaout) unsigned char* BUFF {
+ return $jnicall;
+}
+%typemap(in) unsigned char* BUFF {
+ $1 = (*jenv)->GetDirectBufferAddress(jenv, $input);
+ if ($1 == NULL) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "Unable to get address of direct buffer. Buffer must be allocated direct.");
+ }
+}
+%typemap(memberin) unsigned char* BUFF {
+ if ($input) {
+ $1 = $input;
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(freearg) unsigned char* BUFF ""
+*/
+
+#undef UNSIGNED_NIO_BUFFER_TYPEMAP
\ No newline at end of file
diff --git a/android/android-jni/jni/cv.i b/android/android-jni/jni/cv.i
new file mode 100644
index 0000000000..3c47d0a561
--- /dev/null
+++ b/android/android-jni/jni/cv.i
@@ -0,0 +1,59 @@
+%typemap(javaimports) Mat "
+/** Wrapper for the OpenCV Mat object. Good for passing around as a pointer to a Mat.
+*/"
+
+%typemap(javaimports) Size "
+/** Wrapper for the OpenCV Size object. Good for setting dimensions of cv::Mat...
+*/"
+
+class Mat {
+public:
+ %immutable;
+ int rows;
+ int cols;
+};
+
+class Size{
+public:
+ Size(int width,int height);
+ int width;
+ int height;
+
+};
+
+template class Ptr
+{
+public:
+ //! empty constructor
+ Ptr();
+ //! take ownership of the pointer. The associated reference counter is allocated and set to 1
+ Ptr(_Tp* _obj);
+ //! calls release()
+ ~Ptr();
+ //! copy constructor. Copies the members and calls addref()
+ Ptr(const Ptr& ptr);
+ //! copy operator. Calls ptr.addref() and release() before copying the members
+ // Ptr& operator = (const Ptr& ptr);
+ //! increments the reference counter
+ void addref();
+ //! decrements the reference counter. If it reaches 0, delete_obj() is called
+ void release();
+ //! deletes the object. Override if needed
+ void delete_obj();
+ //! returns true iff obj==NULL
+ bool empty() const;
+
+
+ //! helper operators making "Ptr ptr" use very similar to "T* ptr".
+ _Tp* operator -> ();
+ // const _Tp* operator -> () const;
+
+ // operator _Tp* ();
+ // operator const _Tp*() const;
+
+protected:
+ _Tp* obj; //< the object pointer.
+ int* refcount; //< the associated reference counter
+};
+
+%template(PtrMat) Ptr;
\ No newline at end of file
diff --git a/android/android-jni/jni/gl_code.cpp b/android/android-jni/jni/gl_code.cpp
new file mode 100644
index 0000000000..c13374f5d1
--- /dev/null
+++ b/android/android-jni/jni/gl_code.cpp
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// OpenGL ES 2.0 code
+
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "glcamera.h"
+#include "image_pool.h"
+using namespace cv;
+#define LOG_TAG "libandroid-opencv"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+
+static void printGLString(const char *name, GLenum s) {
+ const char *v = (const char *) glGetString(s);
+ LOGI("GL %s = %s\n", name, v);
+}
+
+static void checkGlError(const char* op) {
+ for (GLint error = glGetError(); error; error = glGetError()) {
+ LOGI("after %s() glError (0x%x)\n", op, error);
+ }
+}
+
+static const char gVertexShader[] = "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+static const char gFragmentShader[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
+ "} \n";
+
+const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f };
+GLubyte testpixels[4 * 3] = { 255, 0, 0, // Red
+ 0, 255, 0, // Green
+ 0, 0, 255, // Blue
+ 255, 255, 0 // Yellow
+ };
+
+GLuint glcamera::createSimpleTexture2D(GLuint _textureid, GLubyte* pixels,
+ int width, int height, int channels) {
+
+ // Bind the texture
+ glActiveTexture(GL_TEXTURE0);
+ checkGlError("glActiveTexture");
+ // Bind the texture object
+ glBindTexture(GL_TEXTURE_2D, _textureid);
+ checkGlError("glBindTexture");
+
+ GLenum format;
+ switch (channels) {
+ case 3:
+ format = GL_RGB;
+ break;
+ case 1:
+ format = GL_LUMINANCE;
+ break;
+ case 4:
+ format = GL_RGBA;
+ break;
+ }
+ // Load the texture
+ glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format,
+ GL_UNSIGNED_BYTE, pixels);
+
+ checkGlError("glTexImage2D");
+ // Set the filtering mode
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+
+ return _textureid;
+
+}
+
+GLuint glcamera::loadShader(GLenum shaderType, const char* pSource) {
+ GLuint shader = glCreateShader(shaderType);
+ if (shader) {
+ glShaderSource(shader, 1, &pSource, NULL);
+ glCompileShader(shader);
+ GLint compiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ GLint infoLen = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen) {
+ char* buf = (char*) malloc(infoLen);
+ if (buf) {
+ glGetShaderInfoLog(shader, infoLen, NULL, buf);
+ LOGE("Could not compile shader %d:\n%s\n",
+ shaderType, buf);
+ free(buf);
+ }
+ glDeleteShader(shader);
+ shader = 0;
+ }
+ }
+ }
+ return shader;
+}
+
+GLuint glcamera::createProgram(const char* pVertexSource,
+ const char* pFragmentSource) {
+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
+ if (!vertexShader) {
+ return 0;
+ }
+
+ GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
+ if (!pixelShader) {
+ return 0;
+ }
+
+ GLuint program = glCreateProgram();
+ if (program) {
+ glAttachShader(program, vertexShader);
+ checkGlError("glAttachShader");
+ glAttachShader(program, pixelShader);
+ checkGlError("glAttachShader");
+ glLinkProgram(program);
+ GLint linkStatus = GL_FALSE;
+ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+ if (linkStatus != GL_TRUE) {
+ GLint bufLength = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+ if (bufLength) {
+ char* buf = (char*) malloc(bufLength);
+ if (buf) {
+ glGetProgramInfoLog(program, bufLength, NULL, buf);
+ LOGE("Could not link program:\n%s\n", buf);
+ free(buf);
+ }
+ }
+ glDeleteProgram(program);
+ program = 0;
+ }
+ }
+ return program;
+}
+
+//GLuint textureID;
+
+bool glcamera::setupGraphics(int w, int h) {
+ printGLString("Version", GL_VERSION);
+ printGLString("Vendor", GL_VENDOR);
+ printGLString("Renderer", GL_RENDERER);
+ printGLString("Extensions", GL_EXTENSIONS);
+
+ LOGI("setupGraphics(%d, %d)", w, h);
+ gProgram = createProgram(gVertexShader, gFragmentShader);
+ if (!gProgram) {
+ LOGE("Could not create program.");
+ return false;
+ }
+ gvPositionHandle = glGetAttribLocation(gProgram, "a_position");
+ gvTexCoordHandle = glGetAttribLocation(gProgram, "a_texCoord");
+
+ gvSamplerHandle = glGetAttribLocation(gProgram, "s_texture");
+
+ // Use tightly packed data
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ // Generate a texture object
+ glGenTextures(1, &textureID);
+ textureID = createSimpleTexture2D(textureID, testpixels, 2, 2, 3);
+
+ checkGlError("glGetAttribLocation");
+ LOGI("glGetAttribLocation(\"vPosition\") = %d\n",
+ gvPositionHandle);
+
+ glViewport(0, 0, w, h);
+ checkGlError("glViewport");
+ return true;
+}
+
+void glcamera::renderFrame() {
+
+ GLfloat vVertices[] = { -1.0f, 1.0f, 0.0f, // Position 0
+ 0.0f, 0.0f, // TexCoord 0
+ -1.0f, -1.0f, 0.0f, // Position 1
+ 0.0f, 1.0f, // TexCoord 1
+ 1.0f, -1.0f, 0.0f, // Position 2
+ 1.0f, 1.0f, // TexCoord 2
+ 1.0f, 1.0f, 0.0f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+ GLsizei stride = 5 * sizeof(GLfloat); // 3 for position, 2 for texture
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ checkGlError("glClearColor");
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+ checkGlError("glClear");
+
+ glUseProgram(gProgram);
+ checkGlError("glUseProgram");
+
+ // Load the vertex position
+ glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, stride,
+ vVertices);
+ // Load the texture coordinate
+ glVertexAttribPointer(gvTexCoordHandle, 2, GL_FLOAT, GL_FALSE, stride,
+ &vVertices[3]);
+
+ glEnableVertexAttribArray(gvPositionHandle);
+ glEnableVertexAttribArray(gvTexCoordHandle);
+
+ // Bind the texture
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, textureID);
+
+ // Set the sampler texture unit to 0
+ glUniform1i(gvSamplerHandle, 0);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+ //checkGlError("glVertexAttribPointer");
+ //glEnableVertexAttribArray(gvPositionHandle);
+ //checkGlError("glEnableVertexAttribArray");
+ //glDrawArrays(GL_TRIANGLES, 0, 3);
+ //checkGlError("glDrawArrays");
+}
+
+void glcamera::init(int width, int height) {
+ newimage = false;
+ nimg = Mat();
+ setupGraphics(width, height);
+
+}
+
+void glcamera::step() {
+ if (newimage && !nimg.empty()) {
+
+ textureID = createSimpleTexture2D(textureID,
+ nimg.ptr (0), nimg.rows, nimg.cols,
+ nimg.channels());
+ newimage = false;
+ }
+ renderFrame();
+
+}
+
+void glcamera::setTextureImage(Ptr img) {
+
+ //int p2 = (int)(std::log(img->size().width)/0.69315);
+ int sz = 256;//std::pow(2,p2);
+ Size size(sz, sz);
+
+ resize(*img, nimg, size,cv::INTER_NEAREST);
+
+ newimage = true;
+
+}
+
+void glcamera::drawMatToGL(int idx, image_pool* pool) {
+
+ Ptr img = pool->getImage(idx);
+
+ if (img.empty())
+ return; //no image at input_idx!
+
+ setTextureImage(img);
+
+}
+
+glcamera::glcamera():newimage(false) {
+ LOGI("glcamera constructor");
+}
+glcamera::~glcamera() {
+ LOGI("glcamera destructor");
+}
+
+
diff --git a/android/android-jni/jni/glcamera.h b/android/android-jni/jni/glcamera.h
new file mode 100644
index 0000000000..e96041058c
--- /dev/null
+++ b/android/android-jni/jni/glcamera.h
@@ -0,0 +1,40 @@
+#ifndef GLCAMERA_H_
+#define GLCAMERA_H_
+#include
+
+#include
+#include
+
+#include "image_pool.h"
+class glcamera {
+ Mat nimg;
+ bool newimage;
+ GLuint textureID;
+
+ GLuint gProgram;
+ GLuint gvPositionHandle;
+
+ GLuint gvTexCoordHandle;
+ GLuint gvSamplerHandle;
+
+public:
+
+ glcamera();
+ ~glcamera();
+ void init(int width, int height);
+ void step();
+
+ void drawMatToGL(int idx, image_pool* pool);
+ void setTextureImage(Ptr img);
+
+private:
+ GLuint createSimpleTexture2D(GLuint _textureid, GLubyte* pixels, int width,
+ int height, int channels);
+ GLuint loadShader(GLenum shaderType, const char* pSource);
+ GLuint
+ createProgram(const char* pVertexSource,
+ const char* pFragmentSource);
+ bool setupGraphics(int w, int h);
+ void renderFrame();
+};
+#endif
diff --git a/android/android-jni/jni/glcamera.i b/android/android-jni/jni/glcamera.i
new file mode 100644
index 0000000000..0a4a05914b
--- /dev/null
+++ b/android/android-jni/jni/glcamera.i
@@ -0,0 +1,43 @@
+
+%typemap(javaimports) glcamera "
+/** a class for doing the native rendering of images
+this class renders using GL2 es, the native ndk version
+This class is used by the GL2CameraViewer to do the rendering,
+and is inspired by the gl2 example in the ndk samples
+*/"
+
+
+
+%javamethodmodifiers glcamera::init"
+ /** should be called onSurfaceChanged by the GLSurfaceView that is using this
+ * as the drawing engine
+ * @param width the width of the surface view that this will be drawing to
+ * @param width the height of the surface view that this will be drawing to
+ *
+ */
+ public";
+
+%javamethodmodifiers glcamera::step"
+ /** should be called by GLSurfaceView.Renderer in the onDrawFrame method, as it
+ handles the rendering of the opengl scene, and requires that the opengl context be
+ valid.
+
+ *
+ */
+ public";
+%javamethodmodifiers glcamera::drawMatToGL"
+ /** copies an image from a pool and queues it for drawing in opengl.
+ * this does transformation into power of two texture sizes
+ * @param idx the image index to copy
+ * @param pool the image_pool to look up the image from
+ *
+ */
+ public";
+
+class glcamera {
+public:
+ void init(int width, int height);
+ void step();
+ void drawMatToGL(int idx, image_pool* pool);
+};
+
diff --git a/android/android-jni/jni/image_pool.cpp b/android/android-jni/jni/image_pool.cpp
new file mode 100644
index 0000000000..863b4132d6
--- /dev/null
+++ b/android/android-jni/jni/image_pool.cpp
@@ -0,0 +1,86 @@
+#include "image_pool.h"
+
+#include "yuv420sp2rgb.h"
+
+#include
+#include
+
+
+JNIEXPORT void JNICALL Java_com_opencv_jni_opencvJNI_addYUVtoPool(JNIEnv * env,
+ jclass thiz, jlong ppool, jobject _jpool, jbyteArray jbuffer,
+ jint jidx, jint jwidth, jint jheight, jboolean jgrey) {
+ image_pool *pool = (image_pool *) ppool;
+
+ Ptr mat = pool->getYUV(jidx);
+
+ if (mat.empty() || mat->cols != jwidth || mat->rows != jheight * 2) {
+ //pool->deleteGrey(jidx);
+ mat = new Mat(jheight * 2, jwidth, CV_8UC1);
+ }
+
+ jsize sz = env->GetArrayLength(jbuffer);
+ uchar* buff = mat->ptr (0);
+
+ env->GetByteArrayRegion(jbuffer, 0, sz, (jbyte*) buff);
+
+ pool->addYUVMat(jidx, mat);
+ Ptr color = pool->getImage(jidx);
+ if (color.empty() || color->cols != jwidth || color->rows != jheight) {
+ //pool->deleteImage(jidx);
+ color = new Mat(jheight, jwidth, CV_8UC3);
+ }
+ if (!jgrey) {
+
+ //doesn't work unfortunately..
+ //cvtColor(*mat,*color, CV_YCrCb2RGB);
+ color_convert_common(buff, buff + jwidth * jheight, jwidth, jheight,
+ color->ptr (0), false);
+
+ }
+
+ if (jgrey) {
+ Mat grey;
+ pool->getGrey(jidx, grey);
+
+ cvtColor(grey, *color, CV_GRAY2RGB);
+
+ }
+
+ pool->addImage(jidx, color);
+
+}
+
+image_pool::image_pool() {
+
+}
+
+image_pool::~image_pool() {
+ __android_log_print(ANDROID_LOG_INFO, "image_pool", "destructor called");
+}
+
+cv::Ptr image_pool::getImage(int i) {
+ return imagesmap[i];
+}
+void image_pool::getGrey(int i, Mat & grey) {
+
+ cv::Ptr tm = yuvImagesMap[i];
+ if (tm.empty())
+ return;
+ grey = (*tm)(Range(0, tm->rows / 2), Range::all());
+}
+cv::Ptr image_pool::getYUV(int i) {
+
+ return yuvImagesMap[i];
+
+}
+void image_pool::addYUVMat(int i, cv::Ptr mat) {
+
+ yuvImagesMap[i] = mat;
+
+}
+void image_pool::addImage(int i, cv::Ptr mat) {
+
+ imagesmap[i] = mat;
+
+}
+
diff --git a/android/android-jni/jni/image_pool.h b/android/android-jni/jni/image_pool.h
new file mode 100644
index 0000000000..037f2a06a5
--- /dev/null
+++ b/android/android-jni/jni/image_pool.h
@@ -0,0 +1,62 @@
+#ifndef IMAGE_POOL_H
+#define IMAGE_POOL_H
+#include
+#include
+#include