adding samples to the android apps directory

This commit is contained in:
Ethan Rublee 2010-10-12 02:21:30 +00:00
parent c09254cf67
commit 2f859a8652
56 changed files with 2448 additions and 0 deletions

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.theveganrobot.cvcamera" android:versionCode="7" android:versionName="7.0"
>
<application android:debuggable="false" android:icon="@drawable/icon">
<activity android:name=".CVCamera" android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden|keyboard"
android:label="@string/app_name"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="7" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
</manifest>

View File

@ -0,0 +1,83 @@
# 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))
$(error Please setup the $(LOCAL_ENV_MK) - the default was just created')
endif
ANDROID_NDK_BASE = $(ANDROID_NDK_ROOT)
$(info OPENCV_CONFIG = $(OPENCV_CONFIG))
ifndef PROJECT_PATH
$(info PROJECT_PATH defaulting to this directory)
PROJECT_PATH=.
endif
# The name of the native library
LIBNAME = libcvcamera.so
# Find all the C++ sources in the native folder
SOURCES = $(wildcard jni/*.cpp)
HEADERS = $(wildcard jni/*.h)
ANDROID_MKS = $(wildcard jni/*.mk)
SWIG_IS = $(wildcard jni/*.i)
SWIG_MAIN = jni/cvcamera.i
SWIG_JAVA_DIR = src/com/theveganrobot/cvcamera/jni
SWIG_JAVA_OUT = $(wildcard $(SWIG_JAVA_DIR)/*.java)
SWIG_C_DIR = jni/gen
SWIG_C_OUT = $(SWIG_C_DIR)/cvcamera_swig.cpp
BUILD_DEFS=OPENCV_CONFIG=$(OPENCV_CONFIG) \
PROJECT_PATH=$(PROJECT_PATH) \
V=$(V) \
$(NDK_FLAGS)
# 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 $(BUILD_DEFS)
#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++ -I../../android-jni/jni -package "com.theveganrobot.cvcamera.jni" \
-outdir $(SWIG_JAVA_DIR) \
-o $(SWIG_C_OUT) $(SWIG_MAIN)
#clean targets
.PHONY: clean clean-swig cleanall
#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 clean $(BUILD_DEFS)

View File

@ -0,0 +1,2 @@
see http://code.google.com/p/android-opencv/wiki/CVCamera

View File

@ -0,0 +1 @@
make V=0

View File

@ -0,0 +1 @@
make OPENCV_ROOT=../../opencv V=0 clean

View File

@ -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.reference.1=../../android-jni
# Project target.
target=android-7

View File

@ -0,0 +1,21 @@
# 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) $(ANDROID_OPENCV_LIBS) -llog -lGLESv2
LOCAL_C_INCLUDES += $(OPENCV_INCLUDES) $(ANDROID_OPENCV_INCLUDES)
LOCAL_MODULE := cvcamera
LOCAL_SRC_FILES := Processor.cpp gen/cvcamera_swig.cpp
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,2 @@
# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi armeabi-v7a

View File

@ -0,0 +1,300 @@
/*
* Processor.cpp
*
* Created on: Jun 13, 2010
* Author: ethan
*/
#include "Processor.h"
#include <sys/stat.h>
using namespace cv;
Processor::Processor() :
stard(20/*max_size*/, 8/*response_threshold*/,
15/*line_threshold_projected*/,
8/*line_threshold_binarized*/, 5/*suppress_nonmax_size*/),
fastd(20/*threshold*/, true/*nonmax_suppression*/),
surfd(100./*hessian_threshold*/, 1/*octaves*/, 2/*octave_layers*/)
{
}
Processor::~Processor() {
// TODO Auto-generated destructor stub
}
void Processor::detectAndDrawFeatures(int input_idx, image_pool* pool,int feature_type) {
FeatureDetector* fd = 0;
switch (feature_type) {
case DETECT_SURF:
fd = &surfd;
break;
case DETECT_FAST:
fd = &fastd;
break;
case DETECT_STAR:
fd = &stard;
break;
}
Mat greyimage;
pool->getGrey(input_idx, greyimage);
//Mat* grayimage = pool->getYUV(input_idx);
Mat* img = pool->getImage(input_idx);
if (!img || greyimage.empty() || fd == 0)
return; //no image at input_idx!
keypoints.clear();
//if(grayimage->step1() > sizeof(uchar)) return;
//cvtColor(*img,*grayimage,CV_RGB2GRAY);
fd->detect(greyimage, keypoints);
for (vector<KeyPoint>::const_iterator it = keypoints.begin(); it
!= keypoints.end(); ++it) {
circle(*img, it->pt, 3, cvScalar(255, 0, 255, 0));
}
//pool->addImage(output_idx,outimage);
}
static double computeReprojectionErrors(
const vector<vector<Point3f> >& objectPoints, const vector<vector<
Point2f> >& imagePoints, const vector<Mat>& rvecs,
const vector<Mat>& tvecs, const Mat& cameraMatrix,
const Mat& distCoeffs, vector<float>& perViewErrors) {
vector<Point2f> 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;
}
static 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
*
*/
static bool runCalibration(vector<vector<Point2f> > imagePoints,
Size imageSize, Size boardSize, float squareSize, float aspectRatio,
int flags, Mat& cameraMatrix, Mat& distCoeffs, vector<Mat>& rvecs,
vector<Mat>& tvecs, vector<float>& reprojErrs, double& totalAvgErr) {
cameraMatrix = Mat::eye(3, 3, CV_64F);
if (flags & CV_CALIB_FIX_ASPECT_RATIO)
cameraMatrix.at<double> (0, 0) = aspectRatio;
distCoeffs = Mat::zeros(5, 1, CV_64F);
vector<vector<Point3f> > 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;
}
bool Processor::detectAndDrawChessboard(int idx,image_pool* pool) {
Mat grey;
pool->getGrey(idx, grey);
if (grey.empty())
return false;
vector<Point2f> corners;
IplImage iplgrey = grey;
if (!cvCheckChessboard(&iplgrey, Size(6, 8)))
return false;
bool patternfound = findChessboardCorners(grey, Size(6, 8), 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, Size(6, 8), Mat(corners), patternfound);
imgsize = grey.size();
return patternfound;
}
void Processor::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 saveCameraParams(const string& filename, Size imageSize, Size boardSize,
float squareSize, float aspectRatio, int flags,
const Mat& cameraMatrix, const Mat& distCoeffs,
const vector<Mat>& rvecs, const vector<Mat>& tvecs,
const vector<float>& reprojErrs,
const vector<vector<Point2f> >& 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;
}
}
void Processor::resetChess() {
imagepoints.clear();
}
void Processor::calibrate(const char* filename) {
vector<Mat> rvecs, tvecs;
vector<float> reprojErrs;
double totalAvgErr = 0;
int flags = 0;
bool writeExtrinsics = true;
bool writePoints = true;
bool ok = runCalibration(imagepoints, imgsize, Size(6, 8), 1.f, 1.f,
flags, K, distortion, rvecs, tvecs, reprojErrs, totalAvgErr);
if (ok){
saveCameraParams(filename, imgsize, Size(6, 8), 1.f,
1.f, flags, K, distortion, writeExtrinsics ? rvecs
: vector<Mat> (), writeExtrinsics ? tvecs
: vector<Mat> (), writeExtrinsics ? reprojErrs
: vector<float> (), writePoints ? imagepoints : vector<
vector<Point2f> > (), totalAvgErr);
}
}
int Processor::getNumberDetectedChessboards() {
return imagepoints.size();
}

View File

@ -0,0 +1,60 @@
/*
* Processor.h
*
* Created on: Jun 13, 2010
* Author: ethan
*/
#ifndef PROCESSOR_H_
#define PROCESSOR_H_
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <vector>
#include "image_pool.h"
#define DETECT_FAST 0
#define DETECT_STAR 1
#define DETECT_SURF 2
class Processor {
cv::StarFeatureDetector stard;
cv::FastFeatureDetector fastd;
cv::SurfFeatureDetector surfd;
std::vector<cv::KeyPoint> keypoints;
vector<vector<Point2f> > imagepoints;
cv::Mat K;
cv::Mat distortion;
cv::Size imgsize;
//image_pool pool;
public:
Processor();
virtual ~Processor();
void detectAndDrawFeatures(int idx, image_pool* pool, int feature_type);
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_ */

View File

@ -0,0 +1,51 @@
/*
* include the headers required by the generated cpp code
*/
%{
#include "Processor.h"
#include "image_pool.h"
using namespace cv;
%}
/**
* some constants, see Processor.h
*/
#define DETECT_FAST 0
#define DETECT_STAR 1
#define DETECT_SURF 2
//import the android-cv.i file so that swig is aware of all that has been previous defined
//notice that it is not an include....
%import "android-cv.i"
//make sure to import the image_pool as it is
//referenced by the Processor java generated
//class
%typemap(javaimports) Processor "
import com.opencv.jni.image_pool;// import the image_pool interface for playing nice with
// android-opencv
/** Processor - for processing images that are stored in an image pool
*/"
class Processor {
public:
Processor();
virtual ~Processor();
void detectAndDrawFeatures(int idx, image_pool* pool, int feature_type);
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);
};

View File

@ -0,0 +1,36 @@
/* File : android-cv.i */
%module cvcamera
/*
* the java import code muse be included for the opencv jni wrappers
* this means that the android project must reference opencv/android as a project
* see the default.properties for how this is done
*/
%pragma(java) jniclassimports=%{
import com.opencv.jni.*; //import the android-opencv jni wrappers
%}
%pragma(java) jniclasscode=%{
static {
try {
//load the cvcamera library, make sure that libcvcamera.so is in your <project>/libs/armeabi directory
//so that android sdk automatically installs it along with the app.
//the android-opencv lib must be loaded first inorder for the cvcamera
//lib to be found
//check the apk generated, by opening it in an archive manager, to verify that
//both these libraries are present
System.loadLibrary("android-opencv");
System.loadLibrary("cvcamera");
} catch (UnsatisfiedLinkError e) {
//badness
throw e;
}
}
%}
//include the Processor class swig interface file
%include "Processor.i"

View File

@ -0,0 +1,2 @@
android update project --name CVCamera \
--path .

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
</LinearLayout>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">CVCamera</string>
<string name="app_description">app to demo using android camera and passing data to opencv layer.</string>
<string name="Changes">Release 0.0.1 - first demo of using the OpenCV library with camera data</string>
</resources>

View File

@ -0,0 +1,4 @@
#location of android-opencv port of OpenCV to android
OPENCV_CONFIG=../../build/android-opencv.mk
ANDROID_NDK_ROOT=$(HOME)/android-ndk-r4-crystax

View File

@ -0,0 +1,498 @@
package com.theveganrobot.cvcamera;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.LinkedList;
import java.util.Scanner;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.widget.AnalogClock;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.opencv.camera.NativePreviewer;
import com.opencv.camera.NativeProcessor;
import com.opencv.camera.NativeProcessor.PoolCallback;
import com.opencv.jni.image_pool;
import com.opencv.opengl.GL2CameraViewer;
import com.theveganrobot.cvcamera.jni.Processor;
import com.theveganrobot.cvcamera.jni.cvcamera;
public class CVCamera extends Activity {
static final int DIALOG_CALIBRATING = 0;
static final int DIALOG_CALIBRATION_FILE = 1;
private static final int DIALOG_OPENING_TUTORIAL = 2;
private static final int DIALOG_TUTORIAL_FAST = 3;
private static final int DIALOG_TUTORIAL_SURF = 4;
private static final int DIALOG_TUTORIAL_STAR = 5;
private static final int DIALOG_TUTORIAL_CHESS = 6;
private boolean captureChess;
ProgressDialog makeCalibDialog() {
ProgressDialog progressDialog;
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Callibrating. Please wait...");
progressDialog.setCancelable(false);
return progressDialog;
}
void toasts(int id) {
switch (id) {
case DIALOG_OPENING_TUTORIAL:
Toast.makeText(this, "Try clicking the menu for CV options.",
Toast.LENGTH_LONG).show();
break;
case DIALOG_TUTORIAL_FAST:
Toast.makeText(this, "Detecting and Displaying FAST features",
Toast.LENGTH_LONG).show();
break;
case DIALOG_TUTORIAL_SURF:
Toast.makeText(this, "Detecting and Displaying SURF features",
Toast.LENGTH_LONG).show();
break;
case DIALOG_TUTORIAL_STAR:
Toast.makeText(this, "Detecting and Displaying STAR features",
Toast.LENGTH_LONG).show();
break;
case DIALOG_TUTORIAL_CHESS:
Toast
.makeText(
this,
"Calibration Mode, Point at a chessboard pattern and press the camera button, space,"
+ "or the DPAD to capture.",
Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
@Override
protected Dialog onCreateDialog(int id) {
Dialog dialog;
switch (id) {
case DIALOG_CALIBRATING:
dialog = makeCalibDialog();
break;
case DIALOG_CALIBRATION_FILE:
dialog = makeCalibFileAlert();
break;
default:
dialog = null;
}
return dialog;
}
private Dialog makeCalibFileAlert() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(calib_text).setTitle(
"camera.yml at " + calib_file_loc).setCancelable(false)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog alert = builder.create();
return alert;
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onKeyUp(int, android.view.KeyEvent)
*/
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_CAMERA:
case KeyEvent.KEYCODE_SPACE:
case KeyEvent.KEYCODE_DPAD_CENTER:
captureChess = true;
return true;
default:
return super.onKeyUp(keyCode, event);
}
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onKeyLongPress(int, android.view.KeyEvent)
*/
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
return super.onKeyLongPress(keyCode, event);
}
/**
* Avoid that the screen get's turned off by the system.
*/
public void disableScreenTurnOff() {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
/**
* Set's the orientation to landscape, as this is needed by AndAR.
*/
public void setOrientation() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
/**
* Maximize the application.
*/
public void setFullscreen() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
public void setNoTitle() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add("FAST");
menu.add("STAR");
menu.add("SURF");
menu.add("Chess");
return true;
}
private NativePreviewer mPreview;
private GL2CameraViewer glview;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
LinkedList<PoolCallback> defaultcallbackstack = new LinkedList<PoolCallback>();
defaultcallbackstack.addFirst(glview.getDrawCallback());
if (item.getTitle().equals("FAST")) {
defaultcallbackstack.addFirst(new FastProcessor());
toasts(DIALOG_TUTORIAL_FAST);
}
else if (item.getTitle().equals("Chess")) {
defaultcallbackstack.addFirst(new CalibrationProcessor());
toasts(DIALOG_TUTORIAL_CHESS);
}
else if (item.getTitle().equals("STAR")) {
defaultcallbackstack.addFirst(new STARProcessor());
toasts(DIALOG_TUTORIAL_STAR);
}
else if (item.getTitle().equals("SURF")) {
defaultcallbackstack.addFirst(new SURFProcessor());
toasts(DIALOG_TUTORIAL_SURF);
}
mPreview.addCallbackStack(defaultcallbackstack);
return true;
}
@Override
public void onOptionsMenuClosed(Menu menu) {
// TODO Auto-generated method stub
super.onOptionsMenuClosed(menu);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setFullscreen();
disableScreenTurnOff();
FrameLayout frame = new FrameLayout(this);
// Create our Preview view and set it as the content of our activity.
mPreview = new NativePreviewer(getApplication(), 640, 480);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.height = getWindowManager().getDefaultDisplay().getHeight();
params.width = (int) (params.height * 4.0 / 2.88);
LinearLayout vidlay = new LinearLayout(getApplication());
vidlay.setGravity(Gravity.CENTER);
vidlay.addView(mPreview, params);
frame.addView(vidlay);
// make the glview overlay ontop of video preview
mPreview.setZOrderMediaOverlay(false);
glview = new GL2CameraViewer(getApplication(), false, 0, 0);
glview.setZOrderMediaOverlay(true);
glview.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
ImageButton capture_button = new ImageButton(getApplicationContext());
capture_button.setImageDrawable(getResources().getDrawable(android.R.drawable.ic_menu_camera));
capture_button.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
capture_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
captureChess = true;
}
});
LinearLayout buttons = new LinearLayout(getApplicationContext());
buttons.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
buttons.addView(capture_button);
Button focus_button = new Button(getApplicationContext());
focus_button.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
focus_button.setText("Focus");
focus_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPreview.postautofocus(100);
}
});
buttons.addView(focus_button);
frame.addView(glview);
frame.addView(buttons);
setContentView(frame);
toasts(DIALOG_OPENING_TUTORIAL);
}
@Override
public boolean onTrackballEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
captureChess = true;
return true;
}
return super.onTrackballEvent(event);
}
@Override
protected void onPause() {
super.onPause();
//clears the callback stack
mPreview.onPause();
glview.onPause();
}
@Override
protected void onResume() {
super.onResume();
glview.onResume();
//add an initiall callback stack to the preview on resume...
//this one will just draw the frames to opengl
LinkedList<NativeProcessor.PoolCallback> cbstack = new LinkedList<PoolCallback>();
cbstack.add(glview.getDrawCallback());
mPreview.addCallbackStack(cbstack);
mPreview.onResume();
}
// final processor so taht these processor callbacks can access it
final Processor processor = new Processor();
class FastProcessor implements NativeProcessor.PoolCallback {
@Override
public void process(int idx, image_pool pool, long timestamp,
NativeProcessor nativeProcessor) {
processor.detectAndDrawFeatures(idx, pool, cvcamera.DETECT_FAST);
}
}
class STARProcessor implements NativeProcessor.PoolCallback {
@Override
public void process(int idx, image_pool pool, long timestamp,
NativeProcessor nativeProcessor) {
processor.detectAndDrawFeatures(idx, pool, cvcamera.DETECT_STAR);
}
}
class SURFProcessor implements NativeProcessor.PoolCallback {
@Override
public void process(int idx, image_pool pool, long timestamp,
NativeProcessor nativeProcessor) {
processor.detectAndDrawFeatures(idx, pool, cvcamera.DETECT_SURF);
}
}
String calib_text = null;
String calib_file_loc = null;
class CalibrationProcessor implements NativeProcessor.PoolCallback {
boolean calibrated = false;
@Override
public void process(int idx, image_pool pool, long timestamp,
NativeProcessor nativeProcessor) {
if (calibrated) {
processor.drawText(idx, pool, "Calibrated successfully");
return;
}
if (processor.getNumberDetectedChessboards() == 10) {
File opencvdir = new File(Environment
.getExternalStorageDirectory(), "opencv");
if (!opencvdir.exists()) {
opencvdir.mkdir();
}
File calibfile = new File(opencvdir, "camera.yml");
calib_file_loc = calibfile.getAbsolutePath();
processor.calibrate(calibfile.getAbsolutePath());
Log.i("chessboard", "calibrated");
calibrated = true;
processor.resetChess();
runOnUiThread(new Runnable() {
@Override
public void run() {
removeDialog(DIALOG_CALIBRATING);
}
});
try {
StringBuilder text = new StringBuilder();
String NL = System.getProperty("line.separator");
Scanner scanner = new Scanner(calibfile);
try {
while (scanner.hasNextLine()) {
text.append(scanner.nextLine() + NL);
}
} finally {
scanner.close();
}
calib_text = text.toString();
runOnUiThread(new Runnable() {
@Override
public void run() {
showDialog(DIALOG_CALIBRATION_FILE);
}
});
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if (captureChess
&& processor.detectAndDrawChessboard(idx, pool)) {
runOnUiThread(new Runnable() {
String numchess = String.valueOf(processor
.getNumberDetectedChessboards());
@Override
public void run() {
Toast.makeText(CVCamera.this,
"Detected " + numchess + " of 10 chessboards",
Toast.LENGTH_SHORT).show();
}
});
Log.i("cvcamera",
"detected a chessboard, n chess boards found: "
+ String.valueOf(processor
.getNumberDetectedChessboards()));
}
captureChess = false;
if (processor.getNumberDetectedChessboards() == 10) {
runOnUiThread(new Runnable() {
@Override
public void run() {
showDialog(DIALOG_CALIBRATING);
}
});
processor.drawText(idx, pool, "Calibrating, please wait.");
}
if (processor.getNumberDetectedChessboards() < 10) {
processor.drawText(idx, pool, "found "
+ processor.getNumberDetectedChessboards()
+ "/10 chessboards");
}
}
}
}

View File

@ -0,0 +1,3 @@
#!/bin/bash
echo uninstalling CVCamera from phone
adb uninstall com.theveganrobot.cvcamera

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.opencv.calibration" android:versionCode="1"
android:versionName="1.0">
<application android:debuggable="true" android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".Calibration" android:label="@string/app_name"
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden|keyboard">
<intent-filter>
<!-- <action android:name="android.intent.action.MAIN" /> -->
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ChessBoardChooser" android:label="@string/app_name"
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden|keyboard">
</activity>
<service android:name=".services.CalibrationService"></service>
</application>
<uses-sdk android:minSdkVersion="7" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
</manifest>

Binary file not shown.

View File

@ -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.reference.1=../../android-jni
# Project target.
target=android-7

View File

@ -0,0 +1,2 @@
android update project --name Calibration \
--path .

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/cameraback">
<!--<com.opencv.camera.NativePreviewer-->
<!-- <SurfaceView -->
<com.opencv.camera.NativePreviewer
android:id="@+id/nativepreviewer"
android:layout_width="400dip"
android:layout_height="300dip"
android:layout_alignParentLeft="true"
android:layout_margin="20dip"
android:gravity="center_horizontal|center_vertical"
android:layout_marginRight="20dip"
/>
<LinearLayout
android:id="@+id/glview_layout"
android:layout_width="400dip"
android:layout_height="300dip"
android:layout_alignParentLeft="true"
android:layout_margin="20dip"
android:gravity="center_horizontal|center_vertical"
android:layout_marginRight="20dip"
>
</LinearLayout>
<LinearLayout android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_margin="20dip"
android:gravity="center_horizontal|center_vertical"
android:layout_alignParentRight="true">
<ImageButton android:src="@android:drawable/ic_menu_camera"
android:id="@+id/capture" android:layout_width="60dip"
android:layout_height="60dip"></ImageButton>
<ImageButton android:src="@android:drawable/ic_menu_save"
android:id="@+id/calibrate" android:layout_width="60dip"
android:layout_height="60dip"></ImageButton>
<TextView android:id="@+id/numberpatterns"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dip"
android:background="@android:color/white"
android:text="0"/>
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center_vertical|center_horizontal">
<TextView android:text="@string/patterntext" android:autoLink="web" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:padding="20dip"/>
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Corners in width direction:"/>
<Spinner android:id="@+id/rows"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:saveEnabled="true"
android:prompt="@string/chesspromptx"
android:entries="@array/chesssizes">
</Spinner>
</LinearLayout>
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Corners in height direction:"/>
<Spinner android:id="@+id/cols"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:saveEnabled="true"
android:prompt="@string/chessprompty"
android:entries="@array/chesssizes">
</Spinner>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/patternsize" android:titleCondensed="Size"
android:title="@string/patternsize"
android:icon="@drawable/patternicon"
></item>
<item android:id="@+id/calibrate"
android:titleCondensed="Calib"
android:title="Calibrate"
></item>
<item android:id="@+id/help"
android:titleCondensed="Help"
android:title="Help"
android:icon="@android:drawable/ic_menu_help"
></item>
</menu>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="chesssizes">
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
<item>10</item>
<item>11</item>
<item>12</item>
<item>13</item>
</string-array>
<string name="chesspromptx">
Choose the width:</string>
<string name="chessprompty">
Choose the height:</string>
</resources>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="good_color">#00ff00</color>
<color name="bad_color">#FF0000</color>
</resources>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Calibration</string>
<string name="patternsize">Pattern Size</string>
<string name="patterntext">Please choose the width and height (number of inside corners) of the checker
board pattern you will be using for calibration. Default is 6 by 8 corners. You may find a checkerboard pattern at
http://opencv.willowgarage.com/pattern</string>
<string name="patternlink">http://opencv.willowgarage.com/pattern</string>
<string name="calibfile">/opencv/camera.yml</string>
<string name="sdcarddir">/opencv</string>
<string name="calibration_service_started">Calibration calculations have started...</string>
<string name="calibration_service_stopped">Calibration calculations has stopped.</string>
<string name="calibration_service_finished">Calibration finished, you camera is calibrated.</string>
<string name="calibration_service_label">Calibration</string>
<string name="calibration_not_enough">Please capture atleast 3 - preferably greater than 10 - images of the pattern!</string>
<string name="sdcard_error_msg"> Please make sure that you\'re sdcard is not mounted to you\'re computer, and that you have an sdcard that is writable on your device.</string>
</resources>

View File

@ -0,0 +1,311 @@
package com.opencv.calibration;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.opencv.calibration.Calibrator.CalibrationCallback;
import com.opencv.calibration.services.CalibrationService;
import com.opencv.camera.NativePreviewer;
import com.opencv.camera.NativeProcessor;
import com.opencv.misc.SDCardChecker;
import com.opencv.opengl.GL2CameraViewer;
public class Calibration extends Activity implements CalibrationCallback {
private NativePreviewer mPreview;
private GL2CameraViewer glview;
private Calibrator calibrator;
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_CAMERA:
case KeyEvent.KEYCODE_SPACE:
case KeyEvent.KEYCODE_DPAD_CENTER:
calibrator.queueChessCapture();
return true;
default:
return super.onKeyUp(keyCode, event);
}
}
@Override
public boolean onTrackballEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
calibrator.queueChessCapture();
return true;
}
return super.onTrackballEvent(event);
}
/**
* Avoid that the screen get's turned off by the system.
*/
public void disableScreenTurnOff() {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
/**
* Set's the orientation to landscape, as this is needed by AndAR.
*/
public void setOrientation() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
/**
* Maximize the application.
*/
public void setFullscreen() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
public void setNoTitle() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.calibrationmenu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.patternsize: {
Intent sizer = new Intent(getApplicationContext(),
ChessBoardChooser.class);
startActivity(sizer);
}
break;
case R.id.help:
help();
break;
case R.id.calibrate:
calibrate();
break;
}
return true;
}
private void help() {
// TODO Auto-generated method stub
}
@Override
public void onOptionsMenuClosed(Menu menu) {
// TODO Auto-generated method stub
super.onOptionsMenuClosed(menu);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
CalibrationService calibservice = ((CalibrationService.CalibrationServiceBinder) service)
.getService();
if (!SDCardChecker.CheckStorage(Calibration.this))
return;
SDCardChecker.MakeDataDir(Calibration.this);
File calibfile = SDCardChecker.getFile(calibservice,
R.string.calibfile);
try {
Calibrator tcalib = calibrator;
calibrator = new Calibrator(Calibration.this);
setCallbackStack();
calibservice.startCalibrating(tcalib, calibfile);
} catch (IOException e) {
e.printStackTrace();
}
// Tell the user about this for our demo.
Toast.makeText(Calibration.this,
"Starting calibration in the background.",
Toast.LENGTH_SHORT).show();
unbindService(this);
}
};
public static File getCalibrationFile(Context ctx) {
return SDCardChecker.getFile(ctx, R.string.calibfile);
}
void doBindCalibService() {
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
bindService(new Intent(Calibration.this, CalibrationService.class),
mConnection, Context.BIND_AUTO_CREATE);
}
void calibrate() {
if (calibrator.getNumberPatternsDetected() < 3) {
Toast.makeText(this, getText(R.string.calibration_not_enough),
Toast.LENGTH_LONG).show();
return;
}
Intent calibservice = new Intent(Calibration.this,
CalibrationService.class);
startService(calibservice);
doBindCalibService();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setFullscreen();
disableScreenTurnOff();
setContentView(R.layout.camera);
mPreview = (NativePreviewer) findViewById(R.id.nativepreviewer);
LinearLayout glview_layout = (LinearLayout) findViewById(R.id.glview_layout);
glview = new GL2CameraViewer(getApplication(), false, 0, 0);
glview_layout.addView(glview);
calibrator = new Calibrator(this);
ImageButton capturebutton = (ImageButton) findViewById(R.id.capture);
capturebutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
calibrator.queueChessCapture();
}
});
ImageButton calibbutton = (ImageButton) findViewById(R.id.calibrate);
calibbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
calibrate();
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
mPreview.onPause();
glview.onPause();
}
protected void setCallbackStack() {
calibrator.setPatternSize(ChessBoardChooser.getPatternSize(this));
LinkedList<NativeProcessor.PoolCallback> callbackstack = new LinkedList<NativeProcessor.PoolCallback>();
callbackstack.add(calibrator);
callbackstack.add(glview.getDrawCallback());
mPreview.addCallbackStack(callbackstack);
updateNumber(calibrator);
}
@Override
protected void onResume() {
super.onResume();
glview.onResume();
mPreview.onResume();
setCallbackStack();
}
void updateNumber(Calibrator calibrator) {
TextView numbertext = (TextView) findViewById(R.id.numberpatterns);
int numdetectd = calibrator.getNumberPatternsDetected();
if (numdetectd > 2) {
numbertext
.setTextColor(getResources().getColor(R.color.good_color));
} else
numbertext.setTextColor(getResources().getColor(R.color.bad_color));
numbertext.setText(String.valueOf(numdetectd));
}
@Override
public void onFoundChessboard(final Calibrator calibrator) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(Calibration.this,
"Captured a calibration pattern!", Toast.LENGTH_SHORT)
.show();
updateNumber(calibrator);
}
});
}
@Override
public void onDoneCalibration(Calibrator calibration, File calibfile) {
}
@Override
public void onFailedChessboard(final Calibrator calibrator) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(
Calibration.this,
"No pattern found. Make sure its the right dimensions, and close enough...",
Toast.LENGTH_LONG).show();
updateNumber(calibrator);
}
});
}
}

View File

@ -0,0 +1,74 @@
package com.opencv.calibration;
import com.opencv.jni.Size;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Spinner;
public class ChessBoardChooser extends Activity {
public static final String CHESS_SIZE = "chess_size";
public static final int DEFAULT_WIDTH = 6;
public static final int DEFAULT_HEIGHT = 8;
public static final int LOWEST = 3;
class DimChooser implements OnItemSelectedListener {
private String dim;
public DimChooser(String dim) {
this.dim = dim;
}
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int pos,
long arg3) {
SharedPreferences settings = getSharedPreferences(CHESS_SIZE, 0);
Editor editor = settings.edit();
editor.putInt(dim, pos + LOWEST);
editor.commit();
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.chesssizer);
// Restore preferences
SharedPreferences settings = getSharedPreferences(CHESS_SIZE, 0);
int width = settings.getInt("width", 6);
int height = settings.getInt("height", 8);
Spinner wspin, hspin;
wspin = (Spinner) findViewById(R.id.rows);
hspin = (Spinner) findViewById(R.id.cols);
wspin.setSelection(width - LOWEST);
hspin.setSelection(height - LOWEST);
wspin.setOnItemSelectedListener(new DimChooser("width"));
hspin.setOnItemSelectedListener(new DimChooser("height"));
}
public static Size getPatternSize(Context ctx) {
SharedPreferences settings = ctx.getSharedPreferences(CHESS_SIZE, 0);
int width = settings.getInt("width", 6);
int height = settings.getInt("height", 8);
return new Size(width, height);
}
}

View File

@ -0,0 +1,151 @@
package com.opencv.calibration.services;
import java.io.File;
import java.io.IOException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import com.opencv.calibration.Calibration;
import com.opencv.calibration.Calibrator;
import com.opencv.calibration.Calibrator.CalibrationCallback;
import com.opencv.calibration.R;
public class CalibrationService extends Service implements CalibrationCallback {
public void startCalibrating(Calibrator calibrator, File calibration_file)
throws IOException {
calibrator.setCallback(this);
calibrator.calibrate(calibration_file);
}
private NotificationManager mNM;
/**
* Class for clients to access. Because we know this service always runs in
* the same process as its clients, we don't need to deal with IPC.
*/
public class CalibrationServiceBinder extends Binder {
public CalibrationService getService() {
return CalibrationService.this;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_NOT_STICKY;
}
@Override
public void onCreate() {
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Display a notification about us starting. We put an icon in the
// status bar.
showNotification();
}
@Override
public void onDestroy() {
// Cancel the persistent notification.
// mNM.cancel(R.string.calibration_service_started);
// Tell the user we stopped.
Toast.makeText(this, R.string.calibration_service_finished,
Toast.LENGTH_SHORT).show();
}
private final IBinder mBinder = new CalibrationServiceBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Show a notification while this service is running.
*/
private void showNotification() {
// In this sample, we'll use the same text for the ticker and the
// expanded notification
CharSequence text = getText(R.string.calibration_service_started);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.icon, text,
System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this
// notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, Calibration.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this,
getText(R.string.calibration_service_label), text,
contentIntent);
notification.defaults |= Notification.DEFAULT_SOUND;
// Send the notification.
// We use a layout id because it is a unique number. We use it later to
// cancel.
mNM.notify(R.string.calibration_service_started, notification);
}
/**
* Show a notification while this service is running.
*/
private void doneNotification() {
// In this sample, we'll use the same text for the ticker and the
// expanded notification
CharSequence text = getText(R.string.calibration_service_finished);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.icon, text,
System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this
// notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, Calibration.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this,
getText(R.string.calibration_service_label), text,
contentIntent);
notification.defaults |= Notification.DEFAULT_SOUND;
// Send the notification.
// We use a layout id because it is a unique number. We use it later to
// cancel.
mNM.notify(R.string.calibration_service_started, notification);
}
@Override
public void onFoundChessboard(Calibrator calibrator) {
// TODO Auto-generated method stub
}
@Override
public void onDoneCalibration(Calibrator calibration, File calibfile) {
doneNotification();
stopSelf();
}
@Override
public void onFailedChessboard(Calibrator calibrator) {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,64 @@
package com.opencv.misc;
import java.io.File;
import android.content.Context;
import android.os.Environment;
import android.widget.Toast;
import com.opencv.calibration.R;
public class SDCardChecker {
public static File createThumb(Context ctx, File workingDir) {
return new File(workingDir, "thumb.jpg");
}
public static File getDir(Context ctx, String relativename) {
return new File(Environment.getExternalStorageDirectory()
+ relativename);
}
public static File getDir(Context ctx, int id) {
return new File(Environment.getExternalStorageDirectory()
+ ctx.getResources().getString(id));
}
public static File getFile(Context ctx, int id) {
return new File(Environment.getExternalStorageDirectory()
+ ctx.getResources().getString(id));
}
public static void MakeDataDir(Context ctx) {
File dir = getDir(ctx, R.string.sdcarddir);
dir.mkdirs();
}
public static boolean CheckStorage(Context ctx) {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but
// all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
boolean goodmount = mExternalStorageAvailable
&& mExternalStorageWriteable;
if (!goodmount) {
Toast.makeText(ctx, ctx.getString(R.string.sdcard_error_msg),
Toast.LENGTH_LONG).show();
}
return goodmount;
}
}

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.foo.bar" android:versionCode="1" android:versionName="1.0" >
<application android:debuggable="true" android:icon="@drawable/icon">
<activity android:name=".FooBar" android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden|keyboard"
android:label="@string/app_name"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
</manifest>

View File

@ -0,0 +1,98 @@
#Re-usable Makefile template for
#android-ndk + swig projects
#author: Ethan Rublee
#date: summer 2010
# The path to the NDK, requires crystax version r-4 for now, due to support
#for the standard library
ifndef ANDROID_NDK_BASE
ANDROID_NDK_BASE = $(HOME)/android-ndk-r4-crystax
$(info default ndk location set ANDROID_NDK_BASE = $(ANDROID_NDK_BASE))
endif
#define OPENCV_ROOT when calling this makefile
#OPENCV_ROOT = $(ANDROID_NDK_BASE)/apps/opencv
ifndef OPENCV_ROOT
$(error Please define OPENCV_ROOT with something like the command \
make OPENCV_ROOT=<opencv>)
endif
ifndef PROJECT_PATH
$(info PROJECT_PATH defaulting to this directory)
PROJECT_PATH=.
endif
$(info OPENCV_ROOT = $(OPENCV_ROOT))
# The name of the native library
LIBNAME = libfoobar.so
#define the main jni swig interface file
#the desired java package name
#and the desired java directory
#notice that the package and the java dir
#are related...
SWIG_MAIN = jni/foobar.i
SWIG_JAVA_PACKAGE = com.foo.bar.jni
SWIG_JAVA_DIR = src/com/foo/bar/jni
SWIG_BASE = foobar
#swig definitions - auto as long as all the
#swig interface files are in jni/*.i
SWIG_JAVA_OUT = $(wildcard $(SWIG_JAVA_DIR)/*.java)
SWIG_IS = $(wildcard jni/*.i)
#the directory where the jni sources are
C_DIR = jni
#directory where to put generated files
#relative to the C_DIR
GEN_DIR = gen
#the c swig is generated and put into the jni/gen folder
SWIG_C_DIR = $(C_DIR)/$(GEN_DIR)
#this file - jin/gen/foobar_swig.cpp must be included in the Android.mk
#for it to be built!
SWIG_C_OUT = $(SWIG_C_DIR)/$(SWIG_BASE)_swig.cpp
# The real native library stripped of symbols
LIB = libs/armeabi-v7a/$(LIBNAME) libs/armeabi/$(LIBNAME)
# Find all the C++ sources in the native folder
SOURCES = $(wildcard jni/*.cpp)
HEADERS = $(wildcard jni/*.h)
ANDROID_MKS = $(wildcard jni/*.mk)
#this gets called by the make command
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_ROOT=$(OPENCV_ROOT) \
OPENCV_LIBS_DIR=$(OPENCV_LIBS_DIR) PROJECT_PATH=$(PROJECT_PATH) SWIG_C_OUT=$(GEN_DIR)/$(SWIG_BASE)_swig.cpp V=$(V) $(NDK_FLAGS)
#this creates the swig wrappers
#-I$(OPENCV_ROOT)/android/jni is an additional swig include path
$(SWIG_C_OUT): $(SWIG_IS)
make clean-swig &&\
mkdir -p $(SWIG_C_DIR) &&\
mkdir -p $(SWIG_JAVA_DIR) &&\
swig -java -c++ -I$(OPENCV_ROOT)/android/jni -package "$(SWIG_JAVA_PACKAGE)" \
-outdir $(SWIG_JAVA_DIR) \
-o $(SWIG_C_OUT) $(SWIG_MAIN)
#clean targets
.PHONY: clean clean-swig cleanall
#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 clean V=$(V) $(NDK_FLAGS)

View File

@ -0,0 +1,2 @@
see http://code.google.com/p/android-opencv/wiki/camera_template

View File

@ -0,0 +1 @@
make OPENCV_ROOT=../../opencv V=0

View File

@ -0,0 +1 @@
make OPENCV_ROOT=../../opencv V=0 clean

View File

@ -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.reference.1=../../opencv/android/
# Project target.
target=android-7

View File

@ -0,0 +1,36 @@
# date: Summer, 2010
# author: Ethan Rublee
# contact: ethan.rublee@gmail.com
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#pass in OPENCV_ROOT or define it here
#OPENCV_ROOT := ~/android-opencv/opencv
ifndef OPENCV_ROOT
${error please define OPENCV_ROOT before this point!}
endif
#define OPENCV_INCLUDES
include $(OPENCV_ROOT)/includes.mk
#define OPENCV_LIBS
include $(OPENCV_ROOT)/libs.mk
LOCAL_LDLIBS += $(OPENCV_LIBS) $(ANDROID_OPENCV_LIBS) -llog -lGLESv2
LOCAL_C_INCLUDES += $(OPENCV_INCLUDES) $(ANDROID_OPENCV_INCLUDES)
LOCAL_MODULE := foobar
ifndef SWIG_C_OUT
${error please define SWIG_C_OUT before this point!}
endif
#make sure to pass in SWIG_C_OUT=gen/foobar_swig.cpp
#done in the makefile
LOCAL_SRC_FILES := ${SWIG_C_OUT} TestBar.cpp
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,2 @@
# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi armeabi-v7a

View File

@ -0,0 +1,5 @@
#include "TestBar.h"
void BarBar::crazy(){
}

View File

@ -0,0 +1,26 @@
/*
* TestBar.h
*
* Created on: Jul 17, 2010
* Author: ethan
*/
#ifndef TESTBAR_H_
#define TESTBAR_H_
#include "image_pool.h"
struct FooBarStruct {
int pool_image_count(image_pool* pool){
return pool->getCount();
}
};
class BarBar{
public:
void crazy();
};
#endif /* TESTBAR_H_ */

View File

@ -0,0 +1,68 @@
/* File : foobar.i */
%module foobar
/*
* the java import code muse be included for the opencv jni wrappers
* this means that the android project must reference opencv/android as a project
* see the default.properties for how this is done
*/
%pragma(java) jniclassimports=%{
import com.opencv.jni.*; //import the android-opencv jni wrappers
%}
%pragma(java) jniclasscode=%{
static {
try {
//load the cvcamera library, make sure that libcvcamera.so is in your <project>/libs/armeabi directory
//so that android sdk automatically installs it along with the app.
//the android-opencv lib must be loaded first inorder for the cvcamera
//lib to be found
//check the apk generated, by opening it in an archive manager, to verify that
//both these libraries are present
System.loadLibrary("android-opencv");
System.loadLibrary("foobar");
} catch (UnsatisfiedLinkError e) {
//badness
throw e;
}
}
%}
%{
#include "image_pool.h"
#include "TestBar.h"
using namespace cv;
%}
//import the android-cv.i file so that swig is aware of all that has been previous defined
//notice that it is not an include....
%import "android-cv.i"
//make sure to import the image_pool as it is
//referenced by the Processor java generated
//class
%typemap(javaimports) FooBarStruct "
import com.opencv.jni.image_pool;// import the image_pool interface for playing nice with
// android-opencv
/** FooBar - template
*/"
//sample inline class that needs to include image_pool
struct FooBarStruct {
int pool_image_count(image_pool* pool){
return pool->getCount();
}
};
//sample jni class
class BarBar{
public:
void crazy();
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">FooBar</string>
<string name="about_str">FooBar is a template app for the android-opencv project!\nVisit http://code.google.com/p/android-opencv for details.</string>
<string name="about_title">About FooBar</string>
<string name="about_menu">About</string>
<string name="ok">O.K.</string>
</resources>

View File

@ -0,0 +1,224 @@
package com.foo.bar;
import java.util.LinkedList;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
//make sure you have the OpenCV project open, so that the
//android-sdk can find it!
import com.foo.bar.jni.BarBar;
import com.foo.bar.jni.FooBarStruct;
import com.opencv.camera.NativePreviewer;
import com.opencv.camera.NativeProcessor;
import com.opencv.camera.NativeProcessor.PoolCallback;
import com.opencv.jni.image_pool;
import com.opencv.opengl.GL2CameraViewer;
public class FooBar extends Activity {
private final int FOOBARABOUT = 0;
@Override
protected Dialog onCreateDialog(int id) {
Dialog dialog;
switch (id) {
case FOOBARABOUT:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.about_title);
builder.setMessage(R.string.about_str);
builder.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dismissDialog(FOOBARABOUT);
}
});
dialog = builder.create();
default:
dialog = null;
}
return dialog;
}
/*
* Handle the capture button as follows...
*/
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_CAMERA:
case KeyEvent.KEYCODE_SPACE:
case KeyEvent.KEYCODE_DPAD_CENTER:
// capture button pressed here
return true;
default:
return super.onKeyUp(keyCode, event);
}
}
/*
* Handle the capture button as follows... On some phones there is no
* capture button, only trackball
*/
@Override
public boolean onTrackballEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
// capture button pressed
return true;
}
return super.onTrackballEvent(event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(R.string.about_menu);
return true;
}
private NativePreviewer mPreview;
private GL2CameraViewer glview;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// example menu
if (item.getTitle().equals(
getResources().getString(R.string.about_menu))) {
showDialog(FOOBARABOUT);
}
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
FrameLayout frame = new FrameLayout(this);
// Create our Preview view and set it as the content of our activity.
mPreview = new NativePreviewer(getApplication(), 300, 300);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.height = getWindowManager().getDefaultDisplay().getHeight();
params.width = (int) (params.height * 4.0 / 2.88);
LinearLayout vidlay = new LinearLayout(getApplication());
vidlay.setGravity(Gravity.CENTER);
vidlay.addView(mPreview, params);
frame.addView(vidlay);
// make the glview overlay ontop of video preview
mPreview.setZOrderMediaOverlay(false);
glview = new GL2CameraViewer(getApplication(), false, 0, 0);
glview.setZOrderMediaOverlay(true);
glview.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
frame.addView(glview);
setContentView(frame);
}
@Override
protected void onPause() {
super.onPause();
// IMPORTANT
// must tell the NativePreviewer of a pause
// and the glview - so that they can release resources and start back up
// properly
// failing to do this will cause the application to crash with no
// warning
// on restart
// clears the callback stack
mPreview.onPause();
glview.onPause();
}
@Override
protected void onResume() {
super.onResume();
// resume the opengl viewer first
glview.onResume();
// add an initial callback stack to the preview on resume...
// this one will just draw the frames to opengl
LinkedList<NativeProcessor.PoolCallback> cbstack = new LinkedList<PoolCallback>();
// SpamProcessor will be called first
cbstack.add(new SpamProcessor());
// then the same idx and pool will be passed to
// the glview callback -
// so operate on the image at idx, and modify, and then
// it will be drawn in the glview
// or remove this, and call glview manually in SpamProcessor
// cbstack.add(glview.getDrawCallback());
mPreview.addCallbackStack(cbstack);
mPreview.onResume();
}
class SpamProcessor implements NativeProcessor.PoolCallback {
FooBarStruct foo = new FooBarStruct();
BarBar barbar = new BarBar();
@Override
public void process(int idx, image_pool pool, long timestamp,
NativeProcessor nativeProcessor) {
// example of using the jni generated FoobarStruct;
int nImages = foo.pool_image_count(pool);
Log.i("foobar", "Number of images in pool: " + nImages);
// call a function - this function does absolutely nothing!
barbar.crazy();
// sample processor
// this gets called every frame in the order of the list
// first add to the callback stack linked list will be the
// first called
// the idx and pool may be used to get the cv::Mat
// that is the latest frame being passed.
// pool.getClass(idx)
// these are what the glview.getDrawCallback() calls
glview.drawMatToGL(idx, pool);
glview.requestRender();
}
}
}