Removed outdated android-opencv subproject
@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="com.opencv" android:versionCode="1" android:versionName="0.1">
|
|
||||||
|
|
||||||
<application android:debuggable="true">
|
|
||||||
<!-- The activity tag here is currently not used. The main project TicTacToeMain
|
|
||||||
must currently redefine the activities to be used from the libraries. However
|
|
||||||
later the tools will pick up the activities from here and merge them automatically,
|
|
||||||
so it's best to define your activities here like for any regular Android
|
|
||||||
project. -->
|
|
||||||
<activity android:name="com.opencv.OpenCV">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity android:name="com.opencv.calibration.ChessBoardChooser" />
|
|
||||||
<activity android:name="com.opencv.calibration.CameraConfig" />
|
|
||||||
<activity android:name="com.opencv.calibration.CalibrationViewer" />
|
|
||||||
<service android:name="com.opencv.calibration.services.CalibrationService" />
|
|
||||||
</application>
|
|
||||||
<uses-sdk android:minSdkVersion="7" />
|
|
||||||
|
|
||||||
<!-- set the opengl version -->
|
|
||||||
<uses-feature android:glEsVersion="0x00020000" />
|
|
||||||
<!-- set the opengl version -->
|
|
||||||
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
|
|
||||||
|
|
||||||
</manifest>
|
|
@ -1,44 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# The AndroidOpenCV CMake configuration file
|
|
||||||
#
|
|
||||||
# ** File generated automatically, do not modify **
|
|
||||||
#
|
|
||||||
# Usage from an external project:
|
|
||||||
# In your CMakeLists.txt, add these lines:
|
|
||||||
#
|
|
||||||
# FIND_PACKAGE(AndroidOpenCV REQUIRED )
|
|
||||||
# TARGET_LINK_LIBRARIES(MY_TARGET_NAME ${AndroidOpenCV_LIBS})
|
|
||||||
#
|
|
||||||
# This file will define the following variables:
|
|
||||||
# - AndroidOpenCV_LIBS : The list of libraries to links against.
|
|
||||||
# - AndroidOpenCV_LIB_DIR : The directory where lib files are.
|
|
||||||
# Calling LINK_DIRECTORIES with this path
|
|
||||||
# is NOT needed.
|
|
||||||
# - AndroidOpenCV_INCLUDE_DIRS : The AndroidOpenCV include directories.
|
|
||||||
# - AndroidOpenCV_SWIG_DIR : The swig path
|
|
||||||
#
|
|
||||||
# ===========================================================================
|
|
||||||
|
|
||||||
|
|
||||||
# ======================================================
|
|
||||||
# Include directories to add to the user project:
|
|
||||||
# ======================================================
|
|
||||||
|
|
||||||
# Provide the include directories to the caller
|
|
||||||
SET(AndroidOpenCV_INCLUDE_DIRS @CMAKE_INCLUDE_DIRS_CONFIGCMAKE@)
|
|
||||||
INCLUDE_DIRECTORIES(${AndroidOpenCV_INCLUDE_DIRS})
|
|
||||||
|
|
||||||
# ======================================================
|
|
||||||
# Link directories to add to the user project:
|
|
||||||
# ======================================================
|
|
||||||
|
|
||||||
# Provide the libs directory anyway, it may be needed in some cases.
|
|
||||||
SET(AndroidOpenCV_LIB_DIR @CMAKE_LIB_DIRS_CONFIGCMAKE@)
|
|
||||||
LINK_DIRECTORIES(${AndroidOpenCV_LIB_DIR})
|
|
||||||
|
|
||||||
# ======================================================
|
|
||||||
# Libraries to add to the user project:
|
|
||||||
# ======================================================
|
|
||||||
SET(AndroidOpenCV_LIBS @CMAKE_LIBS_CONFIGCMAKE@)
|
|
||||||
|
|
||||||
SET(AndroidOpenCV_SWIG_DIR @CMAKE_SWIG_DIR_CONFIGCMAKE@)
|
|
@ -1,5 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
|
||||||
|
|
||||||
project(android-jni)
|
|
||||||
|
|
||||||
add_subdirectory(jni)
|
|
@ -1,15 +0,0 @@
|
|||||||
=========================================
|
|
||||||
CMake Build
|
|
||||||
=========================================
|
|
||||||
#path to the android build of opencv
|
|
||||||
opencv_dir=`pwd`/../build
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake -DOpenCV_DIR=$opencv_dir -DCMAKE_TOOLCHAIN_FILE=$ANDTOOLCHAIN ..
|
|
||||||
|
|
||||||
=========================================
|
|
||||||
Android Build
|
|
||||||
=========================================
|
|
||||||
sh project_create.sh
|
|
||||||
ant compile
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
|||||||
@ECHO OFF
|
|
||||||
SETLOCAL
|
|
||||||
PUSHD %~dp0
|
|
||||||
SET PROJECT_NAME=android-opencv
|
|
||||||
CALL ..\scripts\build.cmd %*
|
|
||||||
POPD
|
|
||||||
ENDLOCAL
|
|
@ -1,9 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
cd `dirname $0`
|
|
||||||
|
|
||||||
opencv_build_dir=`pwd`/../build
|
|
||||||
mkdir -p build
|
|
||||||
cd build
|
|
||||||
|
|
||||||
cmake -DOpenCVDIR=$opencv_build_dir -DCMAKE_TOOLCHAIN_FILE=../../android.toolchain.cmake ..
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
cd `dirname $0`
|
|
||||||
|
|
||||||
opencv_build_dir=`pwd`/../build_neon
|
|
||||||
mkdir -p build_neon
|
|
||||||
cd build_neon
|
|
||||||
|
|
||||||
cmake -DOpenCVDIR=$opencv_build_dir -DARM_TARGET="armeabi-v7a with NEON" -DCMAKE_TOOLCHAIN_FILE=../../android.toolchain.cmake ..
|
|
@ -1,11 +0,0 @@
|
|||||||
# This file is automatically generated by Android Tools.
|
|
||||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
|
||||||
#
|
|
||||||
# This file must be checked in Version Control Systems.
|
|
||||||
#
|
|
||||||
# To customize properties used by the Ant build system use,
|
|
||||||
# "build.properties", and override values to adapt the script to your
|
|
||||||
# project structure.
|
|
||||||
|
|
||||||
# Project target.
|
|
||||||
target=android-7
|
|
@ -1,70 +0,0 @@
|
|||||||
#########################################################
|
|
||||||
# Find opencv and android-opencv
|
|
||||||
#########################################################
|
|
||||||
|
|
||||||
set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../build
|
|
||||||
CACHE PATH "The path where you built opencv for android")
|
|
||||||
find_package(OpenCV REQUIRED)
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
#c flags, included, and lib dependencies
|
|
||||||
#########################################################
|
|
||||||
#notice the "recycling" of CMAKE_C_FLAGS
|
|
||||||
#this is necessary to pick up android flags
|
|
||||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -fPIC" )
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
||||||
|
|
||||||
set( LIBRARY_DEPS ${OpenCV_LIBS} )
|
|
||||||
if(ANDROID)
|
|
||||||
set( LIBRARY_DEPS ${LIBRARY_DEPS} log dl GLESv2)
|
|
||||||
endif(ANDROID)
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
#SWIG STUFF
|
|
||||||
#########################################################
|
|
||||||
#the java package to place swig generated java files in
|
|
||||||
set(MY_PACKAGE com.opencv.jni)
|
|
||||||
|
|
||||||
if(NOT ANDROID)
|
|
||||||
#non android swig and jni
|
|
||||||
#jni is available by default on android
|
|
||||||
find_package(JNI REQUIRED)
|
|
||||||
include_directories(${JNI_INCLUDE_DIRS})
|
|
||||||
FIND_PACKAGE(SWIG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
INCLUDE(${SWIG_USE_FILE}) #on android this is found by the cmake toolchain
|
|
||||||
|
|
||||||
if(ANDROID)
|
|
||||||
#this will set the output path for the java package
|
|
||||||
#and properly create the package declarations in generated java sources
|
|
||||||
SET_SWIG_JAVA_PACKAGE( ${MY_PACKAGE} ) #defined in the android toolchain
|
|
||||||
endif(ANDROID)
|
|
||||||
|
|
||||||
SET_SOURCE_FILES_PROPERTIES(android-cv.i PROPERTIES CPLUSPLUS ON)
|
|
||||||
|
|
||||||
SWIG_ADD_MODULE(android-opencv java
|
|
||||||
android-cv.i
|
|
||||||
Calibration.cpp
|
|
||||||
gl_code.cpp
|
|
||||||
image_pool.cpp
|
|
||||||
yuv420sp2rgb.c
|
|
||||||
#yuv420rgb888c.c
|
|
||||||
#yuv420rgb888.s
|
|
||||||
yuv2rgb16tab.c
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(android-opencv ${LIBRARY_DEPS} )
|
|
||||||
|
|
||||||
###################################################################
|
|
||||||
# Setup the configure file for other's to link against.
|
|
||||||
###################################################################
|
|
||||||
set(CMAKE_INCLUDE_DIRS_CONFIGCMAKE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
||||||
set(CMAKE_LIB_DIRS_CONFIGCMAKE ${LIBRARY_OUTPUT_PATH})
|
|
||||||
set(CMAKE_LIBS_CONFIGCMAKE android-opencv)
|
|
||||||
set(CMAKE_SWIG_DIR_CONFIGCMAKE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
configure_file( "${CMAKE_SOURCE_DIR}/AndroidOpenCVConfig.cmake.in"
|
|
||||||
"${CMAKE_BINARY_DIR}/AndroidOpenCVConfig.cmake"
|
|
||||||
IMMEDIATE @ONLY)
|
|
@ -1,245 +0,0 @@
|
|||||||
/*
|
|
||||||
* Processor.cpp
|
|
||||||
*
|
|
||||||
* Created on: Jun 13, 2010
|
|
||||||
* Author: ethan
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Calibration.h"
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
using namespace cv;
|
|
||||||
|
|
||||||
Calibration::Calibration() :
|
|
||||||
patternsize(6, 8)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Calibration::~Calibration()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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<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(4, 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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}//anon namespace
|
|
||||||
bool Calibration::detectAndDrawChessboard(int idx, image_pool* pool)
|
|
||||||
{
|
|
||||||
|
|
||||||
bool patternfound = false;
|
|
||||||
Mat grey = pool->getGrey(idx);
|
|
||||||
if (grey.empty())
|
|
||||||
return false;
|
|
||||||
vector<Point2f> corners;
|
|
||||||
|
|
||||||
patternfound = findChessboardCorners(grey, patternsize, corners,CALIB_CB_FILTER_QUADS + CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE
|
|
||||||
+ CALIB_CB_FAST_CHECK);
|
|
||||||
Mat img = pool->getImage(idx);
|
|
||||||
|
|
||||||
if (corners.size() < 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (patternfound)
|
|
||||||
{
|
|
||||||
cornerSubPix(grey, corners, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
|
|
||||||
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<Mat> rvecs, tvecs;
|
|
||||||
vector<float> 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<
|
|
||||||
Mat> (), writeExtrinsics ? tvecs : vector<Mat> (), writeExtrinsics ? reprojErrs : vector<float> (), writePoints
|
|
||||||
? imagepoints : vector<vector<Point2f> > (), totalAvgErr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int Calibration::getNumberDetectedChessboards()
|
|
||||||
{
|
|
||||||
return imagepoints.size();
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
%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";
|
|
@ -1,58 +0,0 @@
|
|||||||
/* 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 <project>/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"
|
|
@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 = (CTYPE*)(jenv)->GetDirectBufferAddress( $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($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( $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 = (const char*)(jenv)->GetDirectBufferAddress( $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
|
|
@ -1,156 +0,0 @@
|
|||||||
%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 Size{
|
|
||||||
public:
|
|
||||||
Size();
|
|
||||||
Size(int width,int height);
|
|
||||||
~Size();
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CV_CN_MAX 512
|
|
||||||
#define CV_CN_SHIFT 3
|
|
||||||
#define CV_DEPTH_MAX (1 << CV_CN_SHIFT)
|
|
||||||
|
|
||||||
#define CV_8U 0
|
|
||||||
#define CV_8S 1
|
|
||||||
#define CV_16U 2
|
|
||||||
#define CV_16S 3
|
|
||||||
#define CV_32S 4
|
|
||||||
#define CV_32F 5
|
|
||||||
#define CV_64F 6
|
|
||||||
#define CV_USRTYPE1 7
|
|
||||||
|
|
||||||
#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1)
|
|
||||||
#define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK)
|
|
||||||
|
|
||||||
#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
|
|
||||||
#define CV_MAKE_TYPE CV_MAKETYPE
|
|
||||||
|
|
||||||
#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
|
|
||||||
#define CV_8UC2 CV_MAKETYPE(CV_8U,2)
|
|
||||||
#define CV_8UC3 CV_MAKETYPE(CV_8U,3)
|
|
||||||
#define CV_8UC4 CV_MAKETYPE(CV_8U,4)
|
|
||||||
#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n))
|
|
||||||
|
|
||||||
#define CV_8SC1 CV_MAKETYPE(CV_8S,1)
|
|
||||||
#define CV_8SC2 CV_MAKETYPE(CV_8S,2)
|
|
||||||
#define CV_8SC3 CV_MAKETYPE(CV_8S,3)
|
|
||||||
#define CV_8SC4 CV_MAKETYPE(CV_8S,4)
|
|
||||||
#define CV_8SC(n) CV_MAKETYPE(CV_8S,(n))
|
|
||||||
|
|
||||||
#define CV_16UC1 CV_MAKETYPE(CV_16U,1)
|
|
||||||
#define CV_16UC2 CV_MAKETYPE(CV_16U,2)
|
|
||||||
#define CV_16UC3 CV_MAKETYPE(CV_16U,3)
|
|
||||||
#define CV_16UC4 CV_MAKETYPE(CV_16U,4)
|
|
||||||
#define CV_16UC(n) CV_MAKETYPE(CV_16U,(n))
|
|
||||||
|
|
||||||
#define CV_16SC1 CV_MAKETYPE(CV_16S,1)
|
|
||||||
#define CV_16SC2 CV_MAKETYPE(CV_16S,2)
|
|
||||||
#define CV_16SC3 CV_MAKETYPE(CV_16S,3)
|
|
||||||
#define CV_16SC4 CV_MAKETYPE(CV_16S,4)
|
|
||||||
#define CV_16SC(n) CV_MAKETYPE(CV_16S,(n))
|
|
||||||
|
|
||||||
#define CV_32SC1 CV_MAKETYPE(CV_32S,1)
|
|
||||||
#define CV_32SC2 CV_MAKETYPE(CV_32S,2)
|
|
||||||
#define CV_32SC3 CV_MAKETYPE(CV_32S,3)
|
|
||||||
#define CV_32SC4 CV_MAKETYPE(CV_32S,4)
|
|
||||||
#define CV_32SC(n) CV_MAKETYPE(CV_32S,(n))
|
|
||||||
|
|
||||||
#define CV_32FC1 CV_MAKETYPE(CV_32F,1)
|
|
||||||
#define CV_32FC2 CV_MAKETYPE(CV_32F,2)
|
|
||||||
#define CV_32FC3 CV_MAKETYPE(CV_32F,3)
|
|
||||||
#define CV_32FC4 CV_MAKETYPE(CV_32F,4)
|
|
||||||
#define CV_32FC(n) CV_MAKETYPE(CV_32F,(n))
|
|
||||||
|
|
||||||
#define CV_64FC1 CV_MAKETYPE(CV_64F,1)
|
|
||||||
#define CV_64FC2 CV_MAKETYPE(CV_64F,2)
|
|
||||||
#define CV_64FC3 CV_MAKETYPE(CV_64F,3)
|
|
||||||
#define CV_64FC4 CV_MAKETYPE(CV_64F,4)
|
|
||||||
#define CV_64FC(n) CV_MAKETYPE(CV_64F,(n))
|
|
||||||
|
|
||||||
#define CV_AUTO_STEP 0x7fffffff
|
|
||||||
#define CV_WHOLE_ARR cvSlice( 0, 0x3fffffff )
|
|
||||||
|
|
||||||
#define CV_MAT_CN_MASK ((CV_CN_MAX - 1) << CV_CN_SHIFT)
|
|
||||||
#define CV_MAT_CN(flags) ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1)
|
|
||||||
#define CV_MAT_TYPE_MASK (CV_DEPTH_MAX*CV_CN_MAX - 1)
|
|
||||||
#define CV_MAT_TYPE(flags) ((flags) & CV_MAT_TYPE_MASK)
|
|
||||||
#define CV_MAT_CONT_FLAG_SHIFT 14
|
|
||||||
#define CV_MAT_CONT_FLAG (1 << CV_MAT_CONT_FLAG_SHIFT)
|
|
||||||
#define CV_IS_MAT_CONT(flags) ((flags) & CV_MAT_CONT_FLAG)
|
|
||||||
#define CV_IS_CONT_MAT CV_IS_MAT_CONT
|
|
||||||
#define CV_SUBMAT_FLAG_SHIFT 15
|
|
||||||
#define CV_SUBMAT_FLAG (1 << CV_SUBMAT_FLAG_SHIFT)
|
|
||||||
#define CV_IS_SUBMAT(flags) ((flags) & CV_MAT_SUBMAT_FLAG)
|
|
||||||
|
|
||||||
#define CV_MAGIC_MASK 0xFFFF0000
|
|
||||||
#define CV_MAT_MAGIC_VAL 0x42420000
|
|
||||||
#define CV_TYPE_NAME_MAT "opencv-matrix"
|
|
||||||
|
|
||||||
class Mat {
|
|
||||||
public:
|
|
||||||
Mat();
|
|
||||||
~Mat();
|
|
||||||
void create(Size size, int type);
|
|
||||||
int channels() const;
|
|
||||||
%immutable;
|
|
||||||
int rows;
|
|
||||||
int cols;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class _Tp> 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<T> 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<Mat>;
|
|
||||||
|
|
||||||
void imwrite(const char* image_name, const Mat& image);
|
|
||||||
Mat imread(const char* image_name);
|
|
||||||
|
|
||||||
%include "buffers.i"
|
|
||||||
%apply char* BUFF {const char* buffer}
|
|
||||||
%apply char* BUFF {char* buffer}
|
|
||||||
void copyMatToBuffer(char* buffer, const Mat& mat);
|
|
||||||
void copyBufferToMat(Mat& mat, const char* buffer);
|
|
@ -1,352 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <jni.h>
|
|
||||||
#if __ANDROID__
|
|
||||||
#include <GLES2/gl2.h>
|
|
||||||
#include <GLES2/gl2ext.h>
|
|
||||||
#else
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "android_logger.h"
|
|
||||||
|
|
||||||
#include <opencv2/core/core.hpp>
|
|
||||||
#include <opencv2/imgproc/imgproc.hpp>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "glcamera.h"
|
|
||||||
#include "image_pool.h"
|
|
||||||
using namespace cv;
|
|
||||||
|
|
||||||
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";
|
|
||||||
|
|
||||||
|
|
||||||
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:
|
|
||||||
#if ANDROID
|
|
||||||
format = GL_RGB;
|
|
||||||
#else
|
|
||||||
format = GL_BGR;
|
|
||||||
#endif
|
|
||||||
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");
|
|
||||||
#if ANDROID
|
|
||||||
// Set the filtering mode
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
#else
|
|
||||||
/* Linear Filtering */
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return _textureid;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint glcamera::loadShader(GLenum shaderType, const char* pSource)
|
|
||||||
{
|
|
||||||
GLuint shader = 0;
|
|
||||||
#if __ANDROID__
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint glcamera::createProgram(const char* pVertexSource, const char* pFragmentSource)
|
|
||||||
{
|
|
||||||
#if __ANDROID__
|
|
||||||
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;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
void glcamera::clear(){
|
|
||||||
nimg = Mat();
|
|
||||||
}
|
|
||||||
//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);
|
|
||||||
|
|
||||||
#if __ANDROID__
|
|
||||||
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);
|
|
||||||
|
|
||||||
glViewport(0, 0, w, h);
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcamera::renderFrame()
|
|
||||||
{
|
|
||||||
|
|
||||||
#if __ANDROID__
|
|
||||||
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, img_h, // TexCoord 1
|
|
||||||
1.0f, -1.0f, 0.0f, // Position 2
|
|
||||||
img_w, img_h, // TexCoord 2
|
|
||||||
1.0f, 1.0f, 0.0f, // Position 3
|
|
||||||
img_w, 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");
|
|
||||||
|
|
||||||
if(nimg.empty())return;
|
|
||||||
|
|
||||||
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);
|
|
||||||
#endif
|
|
||||||
//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<unsigned char> (0), nimg.cols, nimg.rows, nimg.channels());
|
|
||||||
newimage = false;
|
|
||||||
}
|
|
||||||
renderFrame();
|
|
||||||
|
|
||||||
}
|
|
||||||
#define NEAREST_POW2(x)( std::ceil(std::log(x)/0.69315) )
|
|
||||||
void glcamera::setTextureImage(const Mat& img)
|
|
||||||
{
|
|
||||||
int p = NEAREST_POW2(img.cols/2); //subsample by 2
|
|
||||||
//int sz = std::pow(2, p);
|
|
||||||
|
|
||||||
// Size size(sz, sz);
|
|
||||||
Size size(256, 256);
|
|
||||||
img_w = 1;
|
|
||||||
img_h = 1;
|
|
||||||
if (nimg.cols != size.width)
|
|
||||||
LOGI_STREAM( "using texture of size: (" << size.width << " , " << size.height << ") image size is: (" << img.cols << " , " << img.rows << ")");
|
|
||||||
nimg.create(size, img.type());
|
|
||||||
#if SUBREGION_NPO2
|
|
||||||
cv::Rect roi(0, 0, img.cols/2, img.rows/2);
|
|
||||||
cv::Mat nimg_sub = nimg(roi);
|
|
||||||
//img.copyTo(nimg_sub);
|
|
||||||
img_w = (img.cols/2)/float(sz);
|
|
||||||
img_h = (img.rows/2)/float(sz);
|
|
||||||
cv::resize(img,nimg_sub,nimg_sub.size(),0,0,CV_INTER_NN);
|
|
||||||
#else
|
|
||||||
cv::resize(img, nimg, nimg.size(), 0, 0, CV_INTER_NN);
|
|
||||||
#endif
|
|
||||||
newimage = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcamera::drawMatToGL(int idx, image_pool* pool)
|
|
||||||
{
|
|
||||||
|
|
||||||
Mat 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");
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
|||||||
|
|
||||||
%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);
|
|
||||||
void clear();
|
|
||||||
};
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
|||||||
#include "image_pool.h"
|
|
||||||
|
|
||||||
#include "yuv420sp2rgb.h"
|
|
||||||
|
|
||||||
#include "android_logger.h"
|
|
||||||
|
|
||||||
#include <opencv2/imgproc/imgproc.hpp>
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <jni.h>
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);
|
|
||||||
//
|
|
||||||
//JNIEXPORT jobject JNICALL Java_com_opencv_jni_opencvJNI_getBitmapBuffer(
|
|
||||||
// JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_);
|
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_com_opencv_jni_opencvJNI_addYUVtoPool(JNIEnv *, jclass, jlong, jobject, jbyteArray, jint,
|
|
||||||
jint, jint, jboolean);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace cv;
|
|
||||||
|
|
||||||
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
|
||||||
{
|
|
||||||
JNIEnv *env;
|
|
||||||
LOGI("JNI_OnLoad called for opencv");
|
|
||||||
return JNI_VERSION_1_4;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
int buff_height = jheight + (jheight / 2);
|
|
||||||
Size buff_size(jwidth, buff_height);
|
|
||||||
image_pool *pool = (image_pool *)ppool;
|
|
||||||
|
|
||||||
Mat mat = pool->getYUV(jidx);
|
|
||||||
//create is smart and only copies if the buffer size is different
|
|
||||||
mat.create(buff_size, CV_8UC1);
|
|
||||||
{
|
|
||||||
uchar* buff = mat.ptr<uchar> (0);
|
|
||||||
jsize sz = env->GetArrayLength(jbuffer);
|
|
||||||
//http://elliotth.blogspot.com/2007/03/optimizing-jni-array-access.html
|
|
||||||
env->GetByteArrayRegion(jbuffer, 0, sz, (jbyte*)buff);
|
|
||||||
}
|
|
||||||
pool->addYUVMat(jidx, mat);
|
|
||||||
|
|
||||||
Mat color;
|
|
||||||
if (jgrey)
|
|
||||||
{
|
|
||||||
Mat grey = pool->getGrey(jidx);
|
|
||||||
color = grey;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
color = pool->getImage(jidx);
|
|
||||||
pool->convertYUVtoColor(jidx, color);
|
|
||||||
}
|
|
||||||
pool->addImage(jidx, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
image_pool::image_pool()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
image_pool::~image_pool()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat image_pool::getImage(int i)
|
|
||||||
{
|
|
||||||
return imagesmap[i];
|
|
||||||
}
|
|
||||||
Mat image_pool::getGrey(int i)
|
|
||||||
{
|
|
||||||
Mat tm = yuvImagesMap[i];
|
|
||||||
if (tm.empty())
|
|
||||||
return tm;
|
|
||||||
return tm(Range(0, tm.rows * (2.0f / 3)), Range::all());
|
|
||||||
}
|
|
||||||
Mat image_pool::getYUV(int i)
|
|
||||||
{
|
|
||||||
return yuvImagesMap[i];
|
|
||||||
}
|
|
||||||
void image_pool::addYUVMat(int i, Mat mat)
|
|
||||||
{
|
|
||||||
yuvImagesMap[i] = mat;
|
|
||||||
}
|
|
||||||
void image_pool::addImage(int i, Mat mat)
|
|
||||||
{
|
|
||||||
imagesmap[i] = mat;
|
|
||||||
}
|
|
||||||
|
|
||||||
void image_pool::convertYUVtoColor(int i, cv::Mat& out)
|
|
||||||
{
|
|
||||||
Mat yuv = getYUV(i);
|
|
||||||
if (yuv.empty())
|
|
||||||
return;
|
|
||||||
int width = yuv.cols;
|
|
||||||
int height = yuv.rows * (2.0f / 3);
|
|
||||||
out.create(height, width, CV_8UC3);
|
|
||||||
const unsigned char* buff = yuv.ptr<unsigned char> (0);
|
|
||||||
unsigned char* out_buff = out.ptr<unsigned char> (0);
|
|
||||||
color_convert_common(buff, buff + width * height, width, height, out_buff, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyMatToBuffer(char* buffer, const cv::Mat& mat)
|
|
||||||
{
|
|
||||||
memcpy(buffer, mat.data, mat.rows * mat.cols * mat.step1());
|
|
||||||
}
|
|
||||||
void copyBufferToMat(cv::Mat& mat, const char* buffer)
|
|
||||||
{
|
|
||||||
memcpy(mat.data, buffer, mat.rows * mat.cols * mat.step1());
|
|
||||||
}
|
|
||||||
|
|
||||||
void RGB2BGR(const Mat& in, Mat& out)
|
|
||||||
{
|
|
||||||
cvtColor(in, out, CV_RGB2BGR);
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
%typemap(javaimports) image_pool "
|
|
||||||
/** image_pool is used for keeping track of a pool of native images. It stores images as cv::Mat's and
|
|
||||||
references them by an index. It allows one to get a pointer to an underlying mat, and handles memory deletion.*/"
|
|
||||||
|
|
||||||
|
|
||||||
%javamethodmodifiers image_pool::getImage"
|
|
||||||
/** gets a pointer to a stored image, by an index. If the index is new, returns a null pointer
|
|
||||||
* @param idx the index in the pool that is associated with a cv::Mat
|
|
||||||
* @return the pointer to a cv::Mat, null pointer if the given idx is novel
|
|
||||||
*/
|
|
||||||
public";
|
|
||||||
|
|
||||||
|
|
||||||
%javamethodmodifiers image_pool::deleteImage"
|
|
||||||
/** deletes the image from the pool
|
|
||||||
* @param idx the index in the pool that is associated with a cv::Mat
|
|
||||||
*/
|
|
||||||
public";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%javamethodmodifiers addYUVtoPool"
|
|
||||||
/** adds a yuv
|
|
||||||
* @param idx the index in the pool that is associated with a cv::Mat
|
|
||||||
*/
|
|
||||||
public";
|
|
||||||
|
|
||||||
%include "various.i"
|
|
||||||
|
|
||||||
|
|
||||||
%apply (char* BYTE) { (char *data)}; //byte[] to char*
|
|
||||||
|
|
||||||
|
|
||||||
%native (addYUVtoPool) void addYUVtoPool(image_pool* pool, char* data,int idx, int width, int height, bool grey);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%feature("director") image_pool;
|
|
||||||
class image_pool {
|
|
||||||
public:
|
|
||||||
Mat getGrey(int i);
|
|
||||||
Mat getImage(int i);
|
|
||||||
void addImage(int i, Mat mat);
|
|
||||||
void convertYUVtoColor(int i, Mat& out);
|
|
||||||
};
|
|
||||||
|
|
||||||
void RGB2BGR(const Mat& in, Mat& out);
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 Calibration
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
cv::Size patternsize;
|
|
||||||
private:
|
|
||||||
std::vector<cv::KeyPoint> keypoints;
|
|
||||||
|
|
||||||
std::vector<std::vector<cv::Point2f> > imagepoints;
|
|
||||||
|
|
||||||
cv::Mat K;
|
|
||||||
cv::Mat distortion;
|
|
||||||
cv::Size imgsize;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* PROCESSOR_H_ */
|
|
@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#define LOG_TAG "libopencv"
|
|
||||||
#if ANDROID
|
|
||||||
#include <android/log.h>
|
|
||||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
|
||||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#include <cstdio>
|
|
||||||
#define LOGI(...) printf("info:");printf("%s:",LOG_TAG); fprintf(stdout,__VA_ARGS__);printf("\n");
|
|
||||||
#define LOGE(...) printf("error:");printf("%s:",LOG_TAG); fprintf(stderr,__VA_ARGS__);printf("\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LOGI_STREAM
|
|
||||||
#define LOGI_STREAM(x) {std::stringstream ss; ss << x; LOGI("%s",ss.str().c_str());}
|
|
||||||
#endif
|
|
||||||
#define LOGE_STREAM(x) {std::stringstream ss; ss << x; LOGE("%s",ss.str().c_str());}
|
|
@ -1,48 +0,0 @@
|
|||||||
#ifndef GLCAMERA_H_
|
|
||||||
#define GLCAMERA_H_
|
|
||||||
#include <opencv2/core/core.hpp>
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
#include <GLES2/gl2.h>
|
|
||||||
#include <GLES2/gl2ext.h>
|
|
||||||
#else
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <GL/glu.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "image_pool.h"
|
|
||||||
|
|
||||||
class glcamera
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
glcamera();
|
|
||||||
~glcamera();
|
|
||||||
void init(int width, int height);
|
|
||||||
void step();
|
|
||||||
|
|
||||||
void drawMatToGL(int idx, image_pool* pool);
|
|
||||||
void drawMatToGL(const cv::Mat& img);
|
|
||||||
void setTextureImage(const cv::Mat& img);
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
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();
|
|
||||||
cv::Mat nimg;
|
|
||||||
bool newimage;
|
|
||||||
GLuint textureID;
|
|
||||||
|
|
||||||
GLuint gProgram;
|
|
||||||
GLuint gvPositionHandle;
|
|
||||||
|
|
||||||
GLuint gvTexCoordHandle;
|
|
||||||
GLuint gvSamplerHandle;
|
|
||||||
float img_w, img_h;
|
|
||||||
};
|
|
||||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||||||
#ifndef IMAGE_POOL_H_ANDROID_KDJFKJ
|
|
||||||
#define IMAGE_POOL_H_ANDROID_KDJFKJ
|
|
||||||
#include <opencv2/core/core.hpp>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class image_pool
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
image_pool();
|
|
||||||
~image_pool();
|
|
||||||
cv::Mat getImage(int i);
|
|
||||||
cv::Mat getGrey(int i);
|
|
||||||
cv::Mat getYUV(int i);
|
|
||||||
|
|
||||||
int getCount()
|
|
||||||
{
|
|
||||||
return imagesmap.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds a mat at the given index - will not do a deep copy, just images[i] = mat
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void addImage(int i, cv::Mat mat);
|
|
||||||
|
|
||||||
/** this function stores the given matrix in the the yuvImagesMap. Also,
|
|
||||||
* after this call getGrey will work, as the grey image is just the top
|
|
||||||
* half of the YUV mat.
|
|
||||||
*
|
|
||||||
* \param i index to store yuv image at
|
|
||||||
* \param mat the yuv matrix to store
|
|
||||||
*/
|
|
||||||
void addYUVMat(int i, cv::Mat mat);
|
|
||||||
|
|
||||||
void convertYUVtoColor(int i, cv::Mat& out);
|
|
||||||
|
|
||||||
// int addYUV(uchar* buffer, int size, int width, int height, bool grey,int idx);
|
|
||||||
//
|
|
||||||
// void getBitmap(int * outintarray, int size, int idx);
|
|
||||||
private:
|
|
||||||
std::map<int, cv::Mat> imagesmap;
|
|
||||||
std::map<int, cv::Mat> yuvImagesMap;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void copyMatToBuffer(char* buffer, const cv::Mat& mat);
|
|
||||||
void copyBufferToMat(cv::Mat& mat, const char* buffer);
|
|
||||||
void RGB2BGR(const cv::Mat& in, cv::Mat& out);
|
|
||||||
#endif
|
|
@ -1,147 +0,0 @@
|
|||||||
/* YUV-> RGB conversion code.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2008-9 Robin Watts (robin@wss.co.uk) for Pinknoise
|
|
||||||
* Productions Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU GPL. If you need it under another license, contact
|
|
||||||
* me and ask.
|
|
||||||
*
|
|
||||||
* This program is free software ; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation ; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program ; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef YUV2RGB_H
|
|
||||||
|
|
||||||
#define YUV2RGB_H
|
|
||||||
|
|
||||||
/* Define these to something appropriate in your build */
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
typedef signed int int32_t;
|
|
||||||
typedef unsigned short uint16_t;
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
|
|
||||||
extern const uint32_t yuv2rgb565_table[];
|
|
||||||
extern const uint32_t yuv2bgr565_table[];
|
|
||||||
|
|
||||||
void yuv420_2_rgb565(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither);
|
|
||||||
|
|
||||||
void yuv422_2_rgb565(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither);
|
|
||||||
|
|
||||||
void yuv444_2_rgb565(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither);
|
|
||||||
|
|
||||||
void yuv420_2_rgb888(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither);
|
|
||||||
|
|
||||||
void yuv422_2_rgb888(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither);
|
|
||||||
|
|
||||||
void yuv444_2_rgb888(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither);
|
|
||||||
|
|
||||||
void yuv420_2_rgb8888(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither);
|
|
||||||
|
|
||||||
void yuv422_2_rgb8888(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither);
|
|
||||||
|
|
||||||
void yuv444_2_rgb8888(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* YUV2RGB_H */
|
|
@ -1,17 +0,0 @@
|
|||||||
#ifndef YUV420SP2RGB_H
|
|
||||||
#define YUV420SP2RGB_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void color_convert_common(
|
|
||||||
const unsigned char *pY, const unsigned char *pUV,
|
|
||||||
int width, int height, unsigned char *buffer,
|
|
||||||
int grey);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* int *INTARRAY typemaps.
|
|
||||||
* These are input typemaps for mapping a Java int[] array to a C int array.
|
|
||||||
* Note that as a Java array is used and thus passeed by reference, the C routine
|
|
||||||
* can return data to Java via the parameter.
|
|
||||||
*
|
|
||||||
* Example usage wrapping:
|
|
||||||
* void foo((int *INTARRAY, int INTARRAYSIZE);
|
|
||||||
*
|
|
||||||
* Java usage:
|
|
||||||
* byte b[] = new byte[20];
|
|
||||||
* modulename.foo(b);
|
|
||||||
*/
|
|
||||||
|
|
||||||
%typemap(in) (int *INTARRAY, int INTARRAYSIZE) {
|
|
||||||
$1 = (int *) JCALL2(GetIntArrayElements, jenv, $input, 0);
|
|
||||||
jsize sz = JCALL1(GetArrayLength, jenv, $input);
|
|
||||||
$2 = (int)sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
%typemap(argout) (int *INTARRAY, int INTARRAYSIZE) {
|
|
||||||
JCALL3(ReleaseIntArrayElements, jenv, $input, (jint *) $1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Prevent default freearg typemap from being used */
|
|
||||||
%typemap(freearg) (int *INTARRAY, int INTARRAYSIZE) ""
|
|
||||||
|
|
||||||
%typemap(jni) (int *INTARRAY, int INTARRAYSIZE) "jintArray"
|
|
||||||
%typemap(jtype) (int *INTARRAY, int INTARRAYSIZE) "int[]"
|
|
||||||
%typemap(jstype) (int *INTARRAY, int INTARRAYSIZE) "int[]"
|
|
||||||
%typemap(javain) (int *INTARRAY, int INTARRAYSIZE) "$javainput"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,802 +0,0 @@
|
|||||||
/* YUV-> RGB conversion code.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2008-9 Robin Watts (robin@wss.co.uk) for Pinknoise
|
|
||||||
* Productions Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU GPL. If you need it under another license, contact
|
|
||||||
* me and ask.
|
|
||||||
*
|
|
||||||
* This program is free software ; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation ; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program ; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* For BREW or Symbian you might need to make this static const rather than
|
|
||||||
* just const, and introduce a function to get the address. */
|
|
||||||
|
|
||||||
#include "yuv2rgb.h"
|
|
||||||
|
|
||||||
const uint32_t yuv2rgb565_table[256*3] =
|
|
||||||
{
|
|
||||||
/* y_table */
|
|
||||||
0x7FFFFFEDU,
|
|
||||||
0x7FFFFFEFU,
|
|
||||||
0x7FFFFFF0U,
|
|
||||||
0x7FFFFFF1U,
|
|
||||||
0x7FFFFFF2U,
|
|
||||||
0x7FFFFFF3U,
|
|
||||||
0x7FFFFFF4U,
|
|
||||||
0x7FFFFFF6U,
|
|
||||||
0x7FFFFFF7U,
|
|
||||||
0x7FFFFFF8U,
|
|
||||||
0x7FFFFFF9U,
|
|
||||||
0x7FFFFFFAU,
|
|
||||||
0x7FFFFFFBU,
|
|
||||||
0x7FFFFFFDU,
|
|
||||||
0x7FFFFFFEU,
|
|
||||||
0x7FFFFFFFU,
|
|
||||||
0x80000000U,
|
|
||||||
0x80400801U,
|
|
||||||
0x80A01002U,
|
|
||||||
0x80E01803U,
|
|
||||||
0x81202805U,
|
|
||||||
0x81803006U,
|
|
||||||
0x81C03807U,
|
|
||||||
0x82004008U,
|
|
||||||
0x82604809U,
|
|
||||||
0x82A0500AU,
|
|
||||||
0x82E0600CU,
|
|
||||||
0x8340680DU,
|
|
||||||
0x8380700EU,
|
|
||||||
0x83C0780FU,
|
|
||||||
0x84208010U,
|
|
||||||
0x84608811U,
|
|
||||||
0x84A09813U,
|
|
||||||
0x8500A014U,
|
|
||||||
0x8540A815U,
|
|
||||||
0x8580B016U,
|
|
||||||
0x85E0B817U,
|
|
||||||
0x8620C018U,
|
|
||||||
0x8660D01AU,
|
|
||||||
0x86C0D81BU,
|
|
||||||
0x8700E01CU,
|
|
||||||
0x8740E81DU,
|
|
||||||
0x87A0F01EU,
|
|
||||||
0x87E0F81FU,
|
|
||||||
0x88210821U,
|
|
||||||
0x88811022U,
|
|
||||||
0x88C11823U,
|
|
||||||
0x89012024U,
|
|
||||||
0x89412825U,
|
|
||||||
0x89A13026U,
|
|
||||||
0x89E14028U,
|
|
||||||
0x8A214829U,
|
|
||||||
0x8A81502AU,
|
|
||||||
0x8AC1582BU,
|
|
||||||
0x8B01602CU,
|
|
||||||
0x8B61682DU,
|
|
||||||
0x8BA1782FU,
|
|
||||||
0x8BE18030U,
|
|
||||||
0x8C418831U,
|
|
||||||
0x8C819032U,
|
|
||||||
0x8CC19833U,
|
|
||||||
0x8D21A034U,
|
|
||||||
0x8D61B036U,
|
|
||||||
0x8DA1B837U,
|
|
||||||
0x8E01C038U,
|
|
||||||
0x8E41C839U,
|
|
||||||
0x8E81D03AU,
|
|
||||||
0x8EE1D83BU,
|
|
||||||
0x8F21E83DU,
|
|
||||||
0x8F61F03EU,
|
|
||||||
0x8FC1F83FU,
|
|
||||||
0x90020040U,
|
|
||||||
0x90420841U,
|
|
||||||
0x90A21042U,
|
|
||||||
0x90E22044U,
|
|
||||||
0x91222845U,
|
|
||||||
0x91823046U,
|
|
||||||
0x91C23847U,
|
|
||||||
0x92024048U,
|
|
||||||
0x92624849U,
|
|
||||||
0x92A2504AU,
|
|
||||||
0x92E2604CU,
|
|
||||||
0x9342684DU,
|
|
||||||
0x9382704EU,
|
|
||||||
0x93C2784FU,
|
|
||||||
0x94228050U,
|
|
||||||
0x94628851U,
|
|
||||||
0x94A29853U,
|
|
||||||
0x9502A054U,
|
|
||||||
0x9542A855U,
|
|
||||||
0x9582B056U,
|
|
||||||
0x95E2B857U,
|
|
||||||
0x9622C058U,
|
|
||||||
0x9662D05AU,
|
|
||||||
0x96C2D85BU,
|
|
||||||
0x9702E05CU,
|
|
||||||
0x9742E85DU,
|
|
||||||
0x97A2F05EU,
|
|
||||||
0x97E2F85FU,
|
|
||||||
0x98230861U,
|
|
||||||
0x98831062U,
|
|
||||||
0x98C31863U,
|
|
||||||
0x99032064U,
|
|
||||||
0x99632865U,
|
|
||||||
0x99A33066U,
|
|
||||||
0x99E34068U,
|
|
||||||
0x9A434869U,
|
|
||||||
0x9A83506AU,
|
|
||||||
0x9AC3586BU,
|
|
||||||
0x9B23606CU,
|
|
||||||
0x9B63686DU,
|
|
||||||
0x9BA3786FU,
|
|
||||||
0x9BE38070U,
|
|
||||||
0x9C438871U,
|
|
||||||
0x9C839072U,
|
|
||||||
0x9CC39873U,
|
|
||||||
0x9D23A074U,
|
|
||||||
0x9D63B076U,
|
|
||||||
0x9DA3B877U,
|
|
||||||
0x9E03C078U,
|
|
||||||
0x9E43C879U,
|
|
||||||
0x9E83D07AU,
|
|
||||||
0x9EE3D87BU,
|
|
||||||
0x9F23E87DU,
|
|
||||||
0x9F63F07EU,
|
|
||||||
0x9FC3F87FU,
|
|
||||||
0xA0040080U,
|
|
||||||
0xA0440881U,
|
|
||||||
0xA0A41082U,
|
|
||||||
0xA0E42084U,
|
|
||||||
0xA1242885U,
|
|
||||||
0xA1843086U,
|
|
||||||
0xA1C43887U,
|
|
||||||
0xA2044088U,
|
|
||||||
0xA2644889U,
|
|
||||||
0xA2A4588BU,
|
|
||||||
0xA2E4608CU,
|
|
||||||
0xA344688DU,
|
|
||||||
0xA384708EU,
|
|
||||||
0xA3C4788FU,
|
|
||||||
0xA4248090U,
|
|
||||||
0xA4649092U,
|
|
||||||
0xA4A49893U,
|
|
||||||
0xA504A094U,
|
|
||||||
0xA544A895U,
|
|
||||||
0xA584B096U,
|
|
||||||
0xA5E4B897U,
|
|
||||||
0xA624C098U,
|
|
||||||
0xA664D09AU,
|
|
||||||
0xA6C4D89BU,
|
|
||||||
0xA704E09CU,
|
|
||||||
0xA744E89DU,
|
|
||||||
0xA7A4F09EU,
|
|
||||||
0xA7E4F89FU,
|
|
||||||
0xA82508A1U,
|
|
||||||
0xA88510A2U,
|
|
||||||
0xA8C518A3U,
|
|
||||||
0xA90520A4U,
|
|
||||||
0xA96528A5U,
|
|
||||||
0xA9A530A6U,
|
|
||||||
0xA9E540A8U,
|
|
||||||
0xAA4548A9U,
|
|
||||||
0xAA8550AAU,
|
|
||||||
0xAAC558ABU,
|
|
||||||
0xAB2560ACU,
|
|
||||||
0xAB6568ADU,
|
|
||||||
0xABA578AFU,
|
|
||||||
0xAC0580B0U,
|
|
||||||
0xAC4588B1U,
|
|
||||||
0xAC8590B2U,
|
|
||||||
0xACE598B3U,
|
|
||||||
0xAD25A0B4U,
|
|
||||||
0xAD65B0B6U,
|
|
||||||
0xADA5B8B7U,
|
|
||||||
0xAE05C0B8U,
|
|
||||||
0xAE45C8B9U,
|
|
||||||
0xAE85D0BAU,
|
|
||||||
0xAEE5D8BBU,
|
|
||||||
0xAF25E8BDU,
|
|
||||||
0xAF65F0BEU,
|
|
||||||
0xAFC5F8BFU,
|
|
||||||
0xB00600C0U,
|
|
||||||
0xB04608C1U,
|
|
||||||
0xB0A610C2U,
|
|
||||||
0xB0E620C4U,
|
|
||||||
0xB12628C5U,
|
|
||||||
0xB18630C6U,
|
|
||||||
0xB1C638C7U,
|
|
||||||
0xB20640C8U,
|
|
||||||
0xB26648C9U,
|
|
||||||
0xB2A658CBU,
|
|
||||||
0xB2E660CCU,
|
|
||||||
0xB34668CDU,
|
|
||||||
0xB38670CEU,
|
|
||||||
0xB3C678CFU,
|
|
||||||
0xB42680D0U,
|
|
||||||
0xB46690D2U,
|
|
||||||
0xB4A698D3U,
|
|
||||||
0xB506A0D4U,
|
|
||||||
0xB546A8D5U,
|
|
||||||
0xB586B0D6U,
|
|
||||||
0xB5E6B8D7U,
|
|
||||||
0xB626C8D9U,
|
|
||||||
0xB666D0DAU,
|
|
||||||
0xB6C6D8DBU,
|
|
||||||
0xB706E0DCU,
|
|
||||||
0xB746E8DDU,
|
|
||||||
0xB7A6F0DEU,
|
|
||||||
0xB7E6F8DFU,
|
|
||||||
0xB82708E1U,
|
|
||||||
0xB88710E2U,
|
|
||||||
0xB8C718E3U,
|
|
||||||
0xB90720E4U,
|
|
||||||
0xB96728E5U,
|
|
||||||
0xB9A730E6U,
|
|
||||||
0xB9E740E8U,
|
|
||||||
0xBA4748E9U,
|
|
||||||
0xBA8750EAU,
|
|
||||||
0xBAC758EBU,
|
|
||||||
0xBB2760ECU,
|
|
||||||
0xBB6768EDU,
|
|
||||||
0xBBA778EFU,
|
|
||||||
0xBC0780F0U,
|
|
||||||
0xBC4788F1U,
|
|
||||||
0xBC8790F2U,
|
|
||||||
0xBCE798F3U,
|
|
||||||
0xBD27A0F4U,
|
|
||||||
0xBD67B0F6U,
|
|
||||||
0xBDC7B8F7U,
|
|
||||||
0xBE07C0F8U,
|
|
||||||
0xBE47C8F9U,
|
|
||||||
0xBEA7D0FAU,
|
|
||||||
0xBEE7D8FBU,
|
|
||||||
0xBF27E8FDU,
|
|
||||||
0xBF87F0FEU,
|
|
||||||
0xBFC7F8FFU,
|
|
||||||
0xC0080100U,
|
|
||||||
0xC0480901U,
|
|
||||||
0xC0A81102U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
0xC0E82104U,
|
|
||||||
/* u_table */
|
|
||||||
0x0C400103U,
|
|
||||||
0x0C200105U,
|
|
||||||
0x0C200107U,
|
|
||||||
0x0C000109U,
|
|
||||||
0x0BE0010BU,
|
|
||||||
0x0BC0010DU,
|
|
||||||
0x0BA0010FU,
|
|
||||||
0x0BA00111U,
|
|
||||||
0x0B800113U,
|
|
||||||
0x0B600115U,
|
|
||||||
0x0B400117U,
|
|
||||||
0x0B400119U,
|
|
||||||
0x0B20011BU,
|
|
||||||
0x0B00011DU,
|
|
||||||
0x0AE0011FU,
|
|
||||||
0x0AE00121U,
|
|
||||||
0x0AC00123U,
|
|
||||||
0x0AA00125U,
|
|
||||||
0x0A800127U,
|
|
||||||
0x0A600129U,
|
|
||||||
0x0A60012BU,
|
|
||||||
0x0A40012DU,
|
|
||||||
0x0A20012FU,
|
|
||||||
0x0A000131U,
|
|
||||||
0x0A000132U,
|
|
||||||
0x09E00134U,
|
|
||||||
0x09C00136U,
|
|
||||||
0x09A00138U,
|
|
||||||
0x09A0013AU,
|
|
||||||
0x0980013CU,
|
|
||||||
0x0960013EU,
|
|
||||||
0x09400140U,
|
|
||||||
0x09400142U,
|
|
||||||
0x09200144U,
|
|
||||||
0x09000146U,
|
|
||||||
0x08E00148U,
|
|
||||||
0x08C0014AU,
|
|
||||||
0x08C0014CU,
|
|
||||||
0x08A0014EU,
|
|
||||||
0x08800150U,
|
|
||||||
0x08600152U,
|
|
||||||
0x08600154U,
|
|
||||||
0x08400156U,
|
|
||||||
0x08200158U,
|
|
||||||
0x0800015AU,
|
|
||||||
0x0800015CU,
|
|
||||||
0x07E0015EU,
|
|
||||||
0x07C00160U,
|
|
||||||
0x07A00162U,
|
|
||||||
0x07A00164U,
|
|
||||||
0x07800166U,
|
|
||||||
0x07600168U,
|
|
||||||
0x0740016AU,
|
|
||||||
0x0720016CU,
|
|
||||||
0x0720016EU,
|
|
||||||
0x07000170U,
|
|
||||||
0x06E00172U,
|
|
||||||
0x06C00174U,
|
|
||||||
0x06C00176U,
|
|
||||||
0x06A00178U,
|
|
||||||
0x0680017AU,
|
|
||||||
0x0660017CU,
|
|
||||||
0x0660017EU,
|
|
||||||
0x06400180U,
|
|
||||||
0x06200182U,
|
|
||||||
0x06000184U,
|
|
||||||
0x05E00185U,
|
|
||||||
0x05E00187U,
|
|
||||||
0x05C00189U,
|
|
||||||
0x05A0018BU,
|
|
||||||
0x0580018DU,
|
|
||||||
0x0580018FU,
|
|
||||||
0x05600191U,
|
|
||||||
0x05400193U,
|
|
||||||
0x05200195U,
|
|
||||||
0x05200197U,
|
|
||||||
0x05000199U,
|
|
||||||
0x04E0019BU,
|
|
||||||
0x04C0019DU,
|
|
||||||
0x04C0019FU,
|
|
||||||
0x04A001A1U,
|
|
||||||
0x048001A3U,
|
|
||||||
0x046001A5U,
|
|
||||||
0x044001A7U,
|
|
||||||
0x044001A9U,
|
|
||||||
0x042001ABU,
|
|
||||||
0x040001ADU,
|
|
||||||
0x03E001AFU,
|
|
||||||
0x03E001B1U,
|
|
||||||
0x03C001B3U,
|
|
||||||
0x03A001B5U,
|
|
||||||
0x038001B7U,
|
|
||||||
0x038001B9U,
|
|
||||||
0x036001BBU,
|
|
||||||
0x034001BDU,
|
|
||||||
0x032001BFU,
|
|
||||||
0x032001C1U,
|
|
||||||
0x030001C3U,
|
|
||||||
0x02E001C5U,
|
|
||||||
0x02C001C7U,
|
|
||||||
0x02A001C9U,
|
|
||||||
0x02A001CBU,
|
|
||||||
0x028001CDU,
|
|
||||||
0x026001CFU,
|
|
||||||
0x024001D1U,
|
|
||||||
0x024001D3U,
|
|
||||||
0x022001D5U,
|
|
||||||
0x020001D7U,
|
|
||||||
0x01E001D8U,
|
|
||||||
0x01E001DAU,
|
|
||||||
0x01C001DCU,
|
|
||||||
0x01A001DEU,
|
|
||||||
0x018001E0U,
|
|
||||||
0x016001E2U,
|
|
||||||
0x016001E4U,
|
|
||||||
0x014001E6U,
|
|
||||||
0x012001E8U,
|
|
||||||
0x010001EAU,
|
|
||||||
0x010001ECU,
|
|
||||||
0x00E001EEU,
|
|
||||||
0x00C001F0U,
|
|
||||||
0x00A001F2U,
|
|
||||||
0x00A001F4U,
|
|
||||||
0x008001F6U,
|
|
||||||
0x006001F8U,
|
|
||||||
0x004001FAU,
|
|
||||||
0x004001FCU,
|
|
||||||
0x002001FEU,
|
|
||||||
0x00000200U,
|
|
||||||
0xFFE00202U,
|
|
||||||
0xFFC00204U,
|
|
||||||
0xFFC00206U,
|
|
||||||
0xFFA00208U,
|
|
||||||
0xFF80020AU,
|
|
||||||
0xFF60020CU,
|
|
||||||
0xFF60020EU,
|
|
||||||
0xFF400210U,
|
|
||||||
0xFF200212U,
|
|
||||||
0xFF000214U,
|
|
||||||
0xFF000216U,
|
|
||||||
0xFEE00218U,
|
|
||||||
0xFEC0021AU,
|
|
||||||
0xFEA0021CU,
|
|
||||||
0xFEA0021EU,
|
|
||||||
0xFE800220U,
|
|
||||||
0xFE600222U,
|
|
||||||
0xFE400224U,
|
|
||||||
0xFE200226U,
|
|
||||||
0xFE200228U,
|
|
||||||
0xFE000229U,
|
|
||||||
0xFDE0022BU,
|
|
||||||
0xFDC0022DU,
|
|
||||||
0xFDC0022FU,
|
|
||||||
0xFDA00231U,
|
|
||||||
0xFD800233U,
|
|
||||||
0xFD600235U,
|
|
||||||
0xFD600237U,
|
|
||||||
0xFD400239U,
|
|
||||||
0xFD20023BU,
|
|
||||||
0xFD00023DU,
|
|
||||||
0xFCE0023FU,
|
|
||||||
0xFCE00241U,
|
|
||||||
0xFCC00243U,
|
|
||||||
0xFCA00245U,
|
|
||||||
0xFC800247U,
|
|
||||||
0xFC800249U,
|
|
||||||
0xFC60024BU,
|
|
||||||
0xFC40024DU,
|
|
||||||
0xFC20024FU,
|
|
||||||
0xFC200251U,
|
|
||||||
0xFC000253U,
|
|
||||||
0xFBE00255U,
|
|
||||||
0xFBC00257U,
|
|
||||||
0xFBC00259U,
|
|
||||||
0xFBA0025BU,
|
|
||||||
0xFB80025DU,
|
|
||||||
0xFB60025FU,
|
|
||||||
0xFB400261U,
|
|
||||||
0xFB400263U,
|
|
||||||
0xFB200265U,
|
|
||||||
0xFB000267U,
|
|
||||||
0xFAE00269U,
|
|
||||||
0xFAE0026BU,
|
|
||||||
0xFAC0026DU,
|
|
||||||
0xFAA0026FU,
|
|
||||||
0xFA800271U,
|
|
||||||
0xFA800273U,
|
|
||||||
0xFA600275U,
|
|
||||||
0xFA400277U,
|
|
||||||
0xFA200279U,
|
|
||||||
0xFA20027BU,
|
|
||||||
0xFA00027CU,
|
|
||||||
0xF9E0027EU,
|
|
||||||
0xF9C00280U,
|
|
||||||
0xF9A00282U,
|
|
||||||
0xF9A00284U,
|
|
||||||
0xF9800286U,
|
|
||||||
0xF9600288U,
|
|
||||||
0xF940028AU,
|
|
||||||
0xF940028CU,
|
|
||||||
0xF920028EU,
|
|
||||||
0xF9000290U,
|
|
||||||
0xF8E00292U,
|
|
||||||
0xF8E00294U,
|
|
||||||
0xF8C00296U,
|
|
||||||
0xF8A00298U,
|
|
||||||
0xF880029AU,
|
|
||||||
0xF860029CU,
|
|
||||||
0xF860029EU,
|
|
||||||
0xF84002A0U,
|
|
||||||
0xF82002A2U,
|
|
||||||
0xF80002A4U,
|
|
||||||
0xF80002A6U,
|
|
||||||
0xF7E002A8U,
|
|
||||||
0xF7C002AAU,
|
|
||||||
0xF7A002ACU,
|
|
||||||
0xF7A002AEU,
|
|
||||||
0xF78002B0U,
|
|
||||||
0xF76002B2U,
|
|
||||||
0xF74002B4U,
|
|
||||||
0xF74002B6U,
|
|
||||||
0xF72002B8U,
|
|
||||||
0xF70002BAU,
|
|
||||||
0xF6E002BCU,
|
|
||||||
0xF6C002BEU,
|
|
||||||
0xF6C002C0U,
|
|
||||||
0xF6A002C2U,
|
|
||||||
0xF68002C4U,
|
|
||||||
0xF66002C6U,
|
|
||||||
0xF66002C8U,
|
|
||||||
0xF64002CAU,
|
|
||||||
0xF62002CCU,
|
|
||||||
0xF60002CEU,
|
|
||||||
0xF60002CFU,
|
|
||||||
0xF5E002D1U,
|
|
||||||
0xF5C002D3U,
|
|
||||||
0xF5A002D5U,
|
|
||||||
0xF5A002D7U,
|
|
||||||
0xF58002D9U,
|
|
||||||
0xF56002DBU,
|
|
||||||
0xF54002DDU,
|
|
||||||
0xF52002DFU,
|
|
||||||
0xF52002E1U,
|
|
||||||
0xF50002E3U,
|
|
||||||
0xF4E002E5U,
|
|
||||||
0xF4C002E7U,
|
|
||||||
0xF4C002E9U,
|
|
||||||
0xF4A002EBU,
|
|
||||||
0xF48002EDU,
|
|
||||||
0xF46002EFU,
|
|
||||||
0xF46002F1U,
|
|
||||||
0xF44002F3U,
|
|
||||||
0xF42002F5U,
|
|
||||||
0xF40002F7U,
|
|
||||||
0xF3E002F9U,
|
|
||||||
0xF3E002FBU,
|
|
||||||
/* v_table */
|
|
||||||
0x1A09A000U,
|
|
||||||
0x19E9A800U,
|
|
||||||
0x19A9B800U,
|
|
||||||
0x1969C800U,
|
|
||||||
0x1949D000U,
|
|
||||||
0x1909E000U,
|
|
||||||
0x18C9E800U,
|
|
||||||
0x18A9F800U,
|
|
||||||
0x186A0000U,
|
|
||||||
0x182A1000U,
|
|
||||||
0x180A2000U,
|
|
||||||
0x17CA2800U,
|
|
||||||
0x17AA3800U,
|
|
||||||
0x176A4000U,
|
|
||||||
0x172A5000U,
|
|
||||||
0x170A6000U,
|
|
||||||
0x16CA6800U,
|
|
||||||
0x168A7800U,
|
|
||||||
0x166A8000U,
|
|
||||||
0x162A9000U,
|
|
||||||
0x160AA000U,
|
|
||||||
0x15CAA800U,
|
|
||||||
0x158AB800U,
|
|
||||||
0x156AC000U,
|
|
||||||
0x152AD000U,
|
|
||||||
0x14EAE000U,
|
|
||||||
0x14CAE800U,
|
|
||||||
0x148AF800U,
|
|
||||||
0x146B0000U,
|
|
||||||
0x142B1000U,
|
|
||||||
0x13EB2000U,
|
|
||||||
0x13CB2800U,
|
|
||||||
0x138B3800U,
|
|
||||||
0x134B4000U,
|
|
||||||
0x132B5000U,
|
|
||||||
0x12EB6000U,
|
|
||||||
0x12CB6800U,
|
|
||||||
0x128B7800U,
|
|
||||||
0x124B8000U,
|
|
||||||
0x122B9000U,
|
|
||||||
0x11EBA000U,
|
|
||||||
0x11ABA800U,
|
|
||||||
0x118BB800U,
|
|
||||||
0x114BC000U,
|
|
||||||
0x112BD000U,
|
|
||||||
0x10EBE000U,
|
|
||||||
0x10ABE800U,
|
|
||||||
0x108BF800U,
|
|
||||||
0x104C0000U,
|
|
||||||
0x100C1000U,
|
|
||||||
0x0FEC2000U,
|
|
||||||
0x0FAC2800U,
|
|
||||||
0x0F8C3800U,
|
|
||||||
0x0F4C4000U,
|
|
||||||
0x0F0C5000U,
|
|
||||||
0x0EEC5800U,
|
|
||||||
0x0EAC6800U,
|
|
||||||
0x0E6C7800U,
|
|
||||||
0x0E4C8000U,
|
|
||||||
0x0E0C9000U,
|
|
||||||
0x0DEC9800U,
|
|
||||||
0x0DACA800U,
|
|
||||||
0x0D6CB800U,
|
|
||||||
0x0D4CC000U,
|
|
||||||
0x0D0CD000U,
|
|
||||||
0x0CCCD800U,
|
|
||||||
0x0CACE800U,
|
|
||||||
0x0C6CF800U,
|
|
||||||
0x0C4D0000U,
|
|
||||||
0x0C0D1000U,
|
|
||||||
0x0BCD1800U,
|
|
||||||
0x0BAD2800U,
|
|
||||||
0x0B6D3800U,
|
|
||||||
0x0B2D4000U,
|
|
||||||
0x0B0D5000U,
|
|
||||||
0x0ACD5800U,
|
|
||||||
0x0AAD6800U,
|
|
||||||
0x0A6D7800U,
|
|
||||||
0x0A2D8000U,
|
|
||||||
0x0A0D9000U,
|
|
||||||
0x09CD9800U,
|
|
||||||
0x098DA800U,
|
|
||||||
0x096DB800U,
|
|
||||||
0x092DC000U,
|
|
||||||
0x090DD000U,
|
|
||||||
0x08CDD800U,
|
|
||||||
0x088DE800U,
|
|
||||||
0x086DF800U,
|
|
||||||
0x082E0000U,
|
|
||||||
0x07EE1000U,
|
|
||||||
0x07CE1800U,
|
|
||||||
0x078E2800U,
|
|
||||||
0x076E3800U,
|
|
||||||
0x072E4000U,
|
|
||||||
0x06EE5000U,
|
|
||||||
0x06CE5800U,
|
|
||||||
0x068E6800U,
|
|
||||||
0x064E7800U,
|
|
||||||
0x062E8000U,
|
|
||||||
0x05EE9000U,
|
|
||||||
0x05CE9800U,
|
|
||||||
0x058EA800U,
|
|
||||||
0x054EB800U,
|
|
||||||
0x052EC000U,
|
|
||||||
0x04EED000U,
|
|
||||||
0x04AED800U,
|
|
||||||
0x048EE800U,
|
|
||||||
0x044EF000U,
|
|
||||||
0x042F0000U,
|
|
||||||
0x03EF1000U,
|
|
||||||
0x03AF1800U,
|
|
||||||
0x038F2800U,
|
|
||||||
0x034F3000U,
|
|
||||||
0x030F4000U,
|
|
||||||
0x02EF5000U,
|
|
||||||
0x02AF5800U,
|
|
||||||
0x028F6800U,
|
|
||||||
0x024F7000U,
|
|
||||||
0x020F8000U,
|
|
||||||
0x01EF9000U,
|
|
||||||
0x01AF9800U,
|
|
||||||
0x016FA800U,
|
|
||||||
0x014FB000U,
|
|
||||||
0x010FC000U,
|
|
||||||
0x00EFD000U,
|
|
||||||
0x00AFD800U,
|
|
||||||
0x006FE800U,
|
|
||||||
0x004FF000U,
|
|
||||||
0x00100000U,
|
|
||||||
0xFFD01000U,
|
|
||||||
0xFFB01800U,
|
|
||||||
0xFF702800U,
|
|
||||||
0xFF303000U,
|
|
||||||
0xFF104000U,
|
|
||||||
0xFED05000U,
|
|
||||||
0xFEB05800U,
|
|
||||||
0xFE706800U,
|
|
||||||
0xFE307000U,
|
|
||||||
0xFE108000U,
|
|
||||||
0xFDD09000U,
|
|
||||||
0xFD909800U,
|
|
||||||
0xFD70A800U,
|
|
||||||
0xFD30B000U,
|
|
||||||
0xFD10C000U,
|
|
||||||
0xFCD0D000U,
|
|
||||||
0xFC90D800U,
|
|
||||||
0xFC70E800U,
|
|
||||||
0xFC30F000U,
|
|
||||||
0xFBF10000U,
|
|
||||||
0xFBD11000U,
|
|
||||||
0xFB911800U,
|
|
||||||
0xFB712800U,
|
|
||||||
0xFB313000U,
|
|
||||||
0xFAF14000U,
|
|
||||||
0xFAD14800U,
|
|
||||||
0xFA915800U,
|
|
||||||
0xFA516800U,
|
|
||||||
0xFA317000U,
|
|
||||||
0xF9F18000U,
|
|
||||||
0xF9D18800U,
|
|
||||||
0xF9919800U,
|
|
||||||
0xF951A800U,
|
|
||||||
0xF931B000U,
|
|
||||||
0xF8F1C000U,
|
|
||||||
0xF8B1C800U,
|
|
||||||
0xF891D800U,
|
|
||||||
0xF851E800U,
|
|
||||||
0xF831F000U,
|
|
||||||
0xF7F20000U,
|
|
||||||
0xF7B20800U,
|
|
||||||
0xF7921800U,
|
|
||||||
0xF7522800U,
|
|
||||||
0xF7123000U,
|
|
||||||
0xF6F24000U,
|
|
||||||
0xF6B24800U,
|
|
||||||
0xF6925800U,
|
|
||||||
0xF6526800U,
|
|
||||||
0xF6127000U,
|
|
||||||
0xF5F28000U,
|
|
||||||
0xF5B28800U,
|
|
||||||
0xF5729800U,
|
|
||||||
0xF552A800U,
|
|
||||||
0xF512B000U,
|
|
||||||
0xF4F2C000U,
|
|
||||||
0xF4B2C800U,
|
|
||||||
0xF472D800U,
|
|
||||||
0xF452E800U,
|
|
||||||
0xF412F000U,
|
|
||||||
0xF3D30000U,
|
|
||||||
0xF3B30800U,
|
|
||||||
0xF3731800U,
|
|
||||||
0xF3532800U,
|
|
||||||
0xF3133000U,
|
|
||||||
0xF2D34000U,
|
|
||||||
0xF2B34800U,
|
|
||||||
0xF2735800U,
|
|
||||||
0xF2336800U,
|
|
||||||
0xF2137000U,
|
|
||||||
0xF1D38000U,
|
|
||||||
0xF1B38800U,
|
|
||||||
0xF1739800U,
|
|
||||||
0xF133A800U,
|
|
||||||
0xF113B000U,
|
|
||||||
0xF0D3C000U,
|
|
||||||
0xF093C800U,
|
|
||||||
0xF073D800U,
|
|
||||||
0xF033E000U,
|
|
||||||
0xF013F000U,
|
|
||||||
0xEFD40000U,
|
|
||||||
0xEF940800U,
|
|
||||||
0xEF741800U,
|
|
||||||
0xEF342000U,
|
|
||||||
0xEEF43000U,
|
|
||||||
0xEED44000U,
|
|
||||||
0xEE944800U,
|
|
||||||
0xEE745800U,
|
|
||||||
0xEE346000U,
|
|
||||||
0xEDF47000U,
|
|
||||||
0xEDD48000U,
|
|
||||||
0xED948800U,
|
|
||||||
0xED549800U,
|
|
||||||
0xED34A000U,
|
|
||||||
0xECF4B000U,
|
|
||||||
0xECD4C000U,
|
|
||||||
0xEC94C800U,
|
|
||||||
0xEC54D800U,
|
|
||||||
0xEC34E000U,
|
|
||||||
0xEBF4F000U,
|
|
||||||
0xEBB50000U,
|
|
||||||
0xEB950800U,
|
|
||||||
0xEB551800U,
|
|
||||||
0xEB352000U,
|
|
||||||
0xEAF53000U,
|
|
||||||
0xEAB54000U,
|
|
||||||
0xEA954800U,
|
|
||||||
0xEA555800U,
|
|
||||||
0xEA156000U,
|
|
||||||
0xE9F57000U,
|
|
||||||
0xE9B58000U,
|
|
||||||
0xE9958800U,
|
|
||||||
0xE9559800U,
|
|
||||||
0xE915A000U,
|
|
||||||
0xE8F5B000U,
|
|
||||||
0xE8B5C000U,
|
|
||||||
0xE875C800U,
|
|
||||||
0xE855D800U,
|
|
||||||
0xE815E000U,
|
|
||||||
0xE7F5F000U,
|
|
||||||
0xE7B60000U,
|
|
||||||
0xE7760800U,
|
|
||||||
0xE7561800U,
|
|
||||||
0xE7162000U,
|
|
||||||
0xE6D63000U,
|
|
||||||
0xE6B64000U,
|
|
||||||
0xE6764800U,
|
|
||||||
0xE6365800U
|
|
||||||
};
|
|
@ -1,201 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include "yuv420sp2rgb.h"
|
|
||||||
#include <arm_neon.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* this source file should only be compiled by Android.mk when targeting
|
|
||||||
* the armeabi-v7a ABI, and should be built in NEON mode
|
|
||||||
*/
|
|
||||||
void fir_filter_neon_intrinsics(short *output, const short* input, const short* kernel, int width, int kernelSize)
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
int nn, offset = -kernelSize / 2;
|
|
||||||
|
|
||||||
for (nn = 0; nn < width; nn++)
|
|
||||||
{
|
|
||||||
int mm, sum = 0;
|
|
||||||
int32x4_t sum_vec = vdupq_n_s32(0);
|
|
||||||
for (mm = 0; mm < kernelSize / 4; mm++)
|
|
||||||
{
|
|
||||||
int16x4_t kernel_vec = vld1_s16(kernel + mm * 4);
|
|
||||||
int16x4_t input_vec = vld1_s16(input + (nn + offset + mm * 4));
|
|
||||||
sum_vec = vmlal_s16(sum_vec, kernel_vec, input_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
sum += vgetq_lane_s32(sum_vec, 0);
|
|
||||||
sum += vgetq_lane_s32(sum_vec, 1);
|
|
||||||
sum += vgetq_lane_s32(sum_vec, 2);
|
|
||||||
sum += vgetq_lane_s32(sum_vec, 3);
|
|
||||||
|
|
||||||
if (kernelSize & 3)
|
|
||||||
{
|
|
||||||
for (mm = kernelSize - (kernelSize & 3); mm < kernelSize; mm++)
|
|
||||||
sum += kernel[mm] * input[nn + offset + mm];
|
|
||||||
}
|
|
||||||
|
|
||||||
output[nn] = (short)((sum + 0x8000) >> 16);
|
|
||||||
}
|
|
||||||
#else /* for comparison purposes only */
|
|
||||||
int nn, offset = -kernelSize/2;
|
|
||||||
for (nn = 0; nn < width; nn++)
|
|
||||||
{
|
|
||||||
int sum = 0;
|
|
||||||
int mm;
|
|
||||||
for (mm = 0; mm < kernelSize; mm++)
|
|
||||||
{
|
|
||||||
sum += kernel[mm]*input[nn+offset+mm];
|
|
||||||
}
|
|
||||||
output[n] = (short)((sum + 0x8000) >> 16);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved
|
|
||||||
U/V plane containing 8 bit 2x2 subsampled chroma samples.
|
|
||||||
except the interleave order of U and V is reversed.
|
|
||||||
|
|
||||||
H V
|
|
||||||
Y Sample Period 1 1
|
|
||||||
U (Cb) Sample Period 2 2
|
|
||||||
V (Cr) Sample Period 2 2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
size of a char:
|
|
||||||
find . -name limits.h -exec grep CHAR_BIT {} \;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef max
|
|
||||||
#define max(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; })
|
|
||||||
#define min(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; })
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define bytes_per_pixel 2
|
|
||||||
#define LOAD_Y(i,j) (pY + i * width + j)
|
|
||||||
#define LOAD_V(i,j) (pUV + (i / 2) * width + bytes_per_pixel * (j / 2))
|
|
||||||
#define LOAD_U(i,j) (pUV + (i / 2) * width + bytes_per_pixel * (j / 2)+1)
|
|
||||||
|
|
||||||
const uint8_t ZEROS[8] = {220,220, 220, 220, 220, 220, 220, 220};
|
|
||||||
const uint8_t Y_SUBS[8] = {16, 16, 16, 16, 16, 16, 16, 16};
|
|
||||||
const uint8_t UV_SUBS[8] = {128, 128, 128, 128, 128, 128, 128, 128};
|
|
||||||
|
|
||||||
const uint32_t UV_MULS[] = {833, 400, 833, 400};
|
|
||||||
|
|
||||||
void color_convert_common(unsigned char *pY, unsigned char *pUV, int width, int height, unsigned char *buffer, int grey)
|
|
||||||
{
|
|
||||||
|
|
||||||
int i, j;
|
|
||||||
int nR, nG, nB;
|
|
||||||
int nY, nU, nV;
|
|
||||||
unsigned char *out = buffer;
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
uint8x8_t Y_SUBvec = vld1_u8(Y_SUBS);
|
|
||||||
uint8x8_t UV_SUBvec = vld1_u8(UV_SUBS); // v,u,v,u v,u,v,u
|
|
||||||
uint32x4_t UV_MULSvec = vld1q_u32(UV_MULS);
|
|
||||||
uint8x8_t ZEROSvec =vld1_u8(ZEROS);
|
|
||||||
|
|
||||||
uint32_t UVvec_int[8];
|
|
||||||
if (grey)
|
|
||||||
{
|
|
||||||
memcpy(out, pY, width * height * sizeof(unsigned char));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// YUV 4:2:0
|
|
||||||
for (i = 0; i < height; i++)
|
|
||||||
{
|
|
||||||
for (j = 0; j < width; j += 8)
|
|
||||||
{
|
|
||||||
// nY = *(pY + i * width + j);
|
|
||||||
// nV = *(pUV + (i / 2) * width + bytes_per_pixel * (j / 2));
|
|
||||||
// nU = *(pUV + (i / 2) * width + bytes_per_pixel * (j / 2) + 1);
|
|
||||||
|
|
||||||
uint8x8_t nYvec = vld1_u8(LOAD_Y(i,j));
|
|
||||||
uint8x8_t nUVvec = vld1_u8(LOAD_V(i,j)); // v,u,v,u v,u,v,u
|
|
||||||
|
|
||||||
nYvec = vmul_u8(nYvec, vcle_u8(nYvec,ZEROSvec));
|
|
||||||
|
|
||||||
// Yuv Convert
|
|
||||||
// nY -= 16;
|
|
||||||
// nU -= 128;
|
|
||||||
// nV -= 128;
|
|
||||||
|
|
||||||
// nYvec = vsub_u8(nYvec, Y_SUBvec);
|
|
||||||
// nUVvec = vsub_u8(nYvec, UV_SUBvec);
|
|
||||||
|
|
||||||
uint16x8_t nYvec16 = vmovl_u8(vsub_u8(nYvec, Y_SUBvec));
|
|
||||||
uint16x8_t nUVvec16 = vmovl_u8(vsub_u8(nYvec, UV_SUBvec));
|
|
||||||
|
|
||||||
uint16x4_t Y_low4 = vget_low_u16(nYvec16);
|
|
||||||
uint16x4_t Y_high4 = vget_high_u16(nYvec16);
|
|
||||||
uint16x4_t UV_low4 = vget_low_u16(nUVvec16);
|
|
||||||
uint16x4_t UV_high4 = vget_high_u16(nUVvec16);
|
|
||||||
|
|
||||||
uint32x4_t UV_low4_int = vmovl_u16(UV_low4);
|
|
||||||
uint32x4_t UV_high4_int = vmovl_u16(UV_high4);
|
|
||||||
|
|
||||||
uint32x4_t Y_low4_int = vmull_n_u16(Y_low4, 1192);
|
|
||||||
uint32x4_t Y_high4_int = vmull_n_u16(Y_high4, 1192);
|
|
||||||
|
|
||||||
uint32x4x2_t UV_uzp = vuzpq_u32(UV_low4_int, UV_high4_int);
|
|
||||||
|
|
||||||
uint32x2_t Vl = vget_low_u32(UV_uzp.val[0]);// vld1_u32(UVvec_int);
|
|
||||||
uint32x2_t Vh = vget_high_u32(UV_uzp.val[0]);//vld1_u32(UVvec_int + 2);
|
|
||||||
|
|
||||||
uint32x2x2_t Vll_ = vzip_u32(Vl, Vl);
|
|
||||||
uint32x4_t* Vll = (uint32x4_t*)(&Vll_);
|
|
||||||
|
|
||||||
uint32x2x2_t Vhh_ = vzip_u32(Vh, Vh);
|
|
||||||
uint32x4_t* Vhh = (uint32x4_t*)(&Vhh_);
|
|
||||||
|
|
||||||
uint32x2_t Ul = vget_low_u32(UV_uzp.val[1]);
|
|
||||||
uint32x2_t Uh = vget_high_u32(UV_uzp.val[1]);
|
|
||||||
|
|
||||||
uint32x2x2_t Ull_ = vzip_u32(Ul, Ul);
|
|
||||||
uint32x4_t* Ull = (uint32x4_t*)(&Ull_);
|
|
||||||
|
|
||||||
uint32x2x2_t Uhh_ = vzip_u32(Uh, Uh);
|
|
||||||
uint32x4_t* Uhh = (uint32x4_t*)(&Uhh_);
|
|
||||||
|
|
||||||
uint32x4_t B_int_low = vmlaq_n_u32(Y_low4_int, *Ull, 2066); //multiply by scalar accum
|
|
||||||
uint32x4_t B_int_high = vmlaq_n_u32(Y_high4_int, *Uhh, 2066); //multiply by scalar accum
|
|
||||||
uint32x4_t G_int_low = vsubq_u32(Y_low4_int, vmlaq_n_u32(vmulq_n_u32(*Vll, 833), *Ull, 400));
|
|
||||||
uint32x4_t G_int_high = vsubq_u32(Y_high4_int, vmlaq_n_u32(vmulq_n_u32(*Vhh, 833), *Uhh, 400));
|
|
||||||
uint32x4_t R_int_low = vmlaq_n_u32(Y_low4_int, *Vll, 1634); //multiply by scalar accum
|
|
||||||
uint32x4_t R_int_high = vmlaq_n_u32(Y_high4_int, *Vhh, 1634); //multiply by scalar accum
|
|
||||||
|
|
||||||
B_int_low = vshrq_n_u32 (B_int_low, 10);
|
|
||||||
B_int_high = vshrq_n_u32 (B_int_high, 10);
|
|
||||||
G_int_low = vshrq_n_u32 (G_int_low, 10);
|
|
||||||
G_int_high = vshrq_n_u32 (G_int_high, 10);
|
|
||||||
R_int_low = vshrq_n_u32 (R_int_low, 10);
|
|
||||||
R_int_high = vshrq_n_u32 (R_int_high, 10);
|
|
||||||
|
|
||||||
|
|
||||||
uint8x8x3_t RGB;
|
|
||||||
RGB.val[0] = vmovn_u16(vcombine_u16(vqmovn_u32 (R_int_low),vqmovn_u32 (R_int_high)));
|
|
||||||
RGB.val[1] = vmovn_u16(vcombine_u16(vqmovn_u32 (G_int_low),vqmovn_u32 (G_int_high)));
|
|
||||||
RGB.val[2] = vmovn_u16(vcombine_u16(vqmovn_u32 (B_int_low),vqmovn_u32 (B_int_high)));
|
|
||||||
|
|
||||||
vst3_u8 (out+i*width*3 + j*3, RGB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,379 +0,0 @@
|
|||||||
; YUV-> RGB conversion code Copyright (C) 2008 Robin Watts (robin;wss.co.uk).
|
|
||||||
;
|
|
||||||
; Licensed under the GPL. If you need it under another license, contact me
|
|
||||||
; and ask.
|
|
||||||
;
|
|
||||||
; This program is free software ; you can redistribute it and/or modify
|
|
||||||
; it under the terms of the GNU General Public License as published by
|
|
||||||
; the Free Software Foundation ; either version 2 of the License, or
|
|
||||||
; (at your option) any later version.
|
|
||||||
;
|
|
||||||
; This program is distributed in the hope that it will be useful,
|
|
||||||
; but WITHOUT ANY WARRANTY ; without even the implied warranty of
|
|
||||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
; GNU General Public License for more details.
|
|
||||||
;
|
|
||||||
; You should have received a copy of the GNU General Public License
|
|
||||||
; along with this program ; if not, write to the Free Software
|
|
||||||
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; The algorithm used here is based heavily on one created by Sophie Wilson
|
|
||||||
; of Acorn/e-14/Broadcomm. Many thanks.
|
|
||||||
;
|
|
||||||
; Additional tweaks (in the fast fixup code) are from Paul Gardiner.
|
|
||||||
;
|
|
||||||
; The old implementation of YUV -> RGB did:
|
|
||||||
;
|
|
||||||
; R = CLAMP((Y-16)*1.164 + 1.596*V)
|
|
||||||
; G = CLAMP((Y-16)*1.164 - 0.391*U - 0.813*V)
|
|
||||||
; B = CLAMP((Y-16)*1.164 + 2.018*U )
|
|
||||||
;
|
|
||||||
; We're going to bend that here as follows:
|
|
||||||
;
|
|
||||||
; R = CLAMP(y + 1.596*V)
|
|
||||||
; G = CLAMP(y - 0.383*U - 0.813*V)
|
|
||||||
; B = CLAMP(y + 1.976*U )
|
|
||||||
;
|
|
||||||
; where y = 0 for Y <= 16,
|
|
||||||
; y = ( Y-16)*1.164, for 16 < Y <= 239,
|
|
||||||
; y = (239-16)*1.164, for 239 < Y
|
|
||||||
;
|
|
||||||
; i.e. We clamp Y to the 16 to 239 range (which it is supposed to be in
|
|
||||||
; anyway). We then pick the B_U factor so that B never exceeds 511. We then
|
|
||||||
; shrink the G_U factor in line with that to avoid a colour shift as much as
|
|
||||||
; possible.
|
|
||||||
;
|
|
||||||
; We're going to use tables to do it faster, but rather than doing it using
|
|
||||||
; 5 tables as as the above suggests, we're going to do it using just 3.
|
|
||||||
;
|
|
||||||
; We do this by working in parallel within a 32 bit word, and using one
|
|
||||||
; table each for Y U and V.
|
|
||||||
;
|
|
||||||
; Source Y values are 0 to 255, so 0.. 260 after scaling
|
|
||||||
; Source U values are -128 to 127, so -49.. 49(G), -253..251(B) after
|
|
||||||
; Source V values are -128 to 127, so -204..203(R), -104..103(G) after
|
|
||||||
;
|
|
||||||
; So total summed values:
|
|
||||||
; -223 <= R <= 481, -173 <= G <= 431, -253 <= B < 511
|
|
||||||
;
|
|
||||||
; We need to pack R G and B into a 32 bit word, and because of Bs range we
|
|
||||||
; need 2 bits above the valid range of B to detect overflow, and another one
|
|
||||||
; to detect the sense of the overflow. We therefore adopt the following
|
|
||||||
; representation:
|
|
||||||
;
|
|
||||||
; osGGGGGgggggosBBBBBbbbosRRRRRrrr
|
|
||||||
;
|
|
||||||
; Each such word breaks down into 3 ranges.
|
|
||||||
;
|
|
||||||
; osGGGGGggggg osBBBBBbbb osRRRRRrrr
|
|
||||||
;
|
|
||||||
; Thus we have 8 bits for each B and R table entry, and 10 bits for G (good
|
|
||||||
; as G is the most noticable one). The s bit for each represents the sign,
|
|
||||||
; and o represents the overflow.
|
|
||||||
;
|
|
||||||
; For R and B we pack the table by taking the 11 bit representation of their
|
|
||||||
; values, and toggling bit 10 in the U and V tables.
|
|
||||||
;
|
|
||||||
; For the green case we calculate 4*G (thus effectively using 10 bits for the
|
|
||||||
; valid range) truncate to 12 bits. We toggle bit 11 in the Y table.
|
|
||||||
|
|
||||||
; Theorarm library
|
|
||||||
; Copyright (C) 2009 Robin Watts for Pinknoise Productions Ltd
|
|
||||||
|
|
||||||
AREA |.text|, CODE, READONLY
|
|
||||||
|
|
||||||
EXPORT yuv420_2_rgb888
|
|
||||||
EXPORT yuv420_2_rgb888_PROFILE
|
|
||||||
|
|
||||||
; void yuv420_2_rgb565
|
|
||||||
; uint8_t *dst_ptr
|
|
||||||
; uint8_t *y_ptr
|
|
||||||
; uint8_t *u_ptr
|
|
||||||
; uint8_t *v_ptr
|
|
||||||
; int width
|
|
||||||
; int height
|
|
||||||
; int y_span
|
|
||||||
; int uv_span
|
|
||||||
; int dst_span
|
|
||||||
; int *tables
|
|
||||||
; int dither
|
|
||||||
|
|
||||||
CONST_flags
|
|
||||||
DCD 0x40080100
|
|
||||||
yuv420_2_rgb888
|
|
||||||
; r0 = dst_ptr
|
|
||||||
; r1 = y_ptr
|
|
||||||
; r2 = u_ptr
|
|
||||||
; r3 = v_ptr
|
|
||||||
; <> = width
|
|
||||||
; <> = height
|
|
||||||
; <> = y_span
|
|
||||||
; <> = uv_span
|
|
||||||
; <> = dst_span
|
|
||||||
; <> = y_table
|
|
||||||
; <> = dither
|
|
||||||
STMFD r13!,{r4-r11,r14}
|
|
||||||
|
|
||||||
LDR r8, [r13,#10*4] ; r8 = height
|
|
||||||
LDR r10,[r13,#11*4] ; r10= y_span
|
|
||||||
LDR r9, [r13,#13*4] ; r9 = dst_span
|
|
||||||
LDR r14,[r13,#14*4] ; r14= y_table
|
|
||||||
LDR r5, CONST_flags
|
|
||||||
LDR r11,[r13,#9*4] ; r11= width
|
|
||||||
ADD r4, r14, #256*4
|
|
||||||
SUBS r8, r8, #1
|
|
||||||
BLT end
|
|
||||||
BEQ trail_row1
|
|
||||||
yloop1
|
|
||||||
SUB r8, r8, r11,LSL #16 ; r8 = height-(width<<16)
|
|
||||||
ADDS r8, r8, #1<<16 ; if (width == 1)
|
|
||||||
BGE trail_pair1 ; just do 1 column
|
|
||||||
xloop1
|
|
||||||
LDRB r11,[r2], #1 ; r11 = u = *u_ptr++
|
|
||||||
LDRB r12,[r3], #1 ; r12 = v = *v_ptr++
|
|
||||||
LDRB r7, [r1, r10] ; r7 = y2 = y_ptr[stride]
|
|
||||||
LDRB r6, [r1], #1 ; r6 = y0 = *y_ptr++
|
|
||||||
ADD r12,r12,#512
|
|
||||||
LDR r11,[r4, r11,LSL #2] ; r11 = u = u_table[u]
|
|
||||||
LDR r12,[r14,r12,LSL #2] ; r12 = v = v_table[v]
|
|
||||||
LDR r7, [r14,r7, LSL #2] ; r7 = y2 = y_table[y2]
|
|
||||||
LDR r6, [r14,r6, LSL #2] ; r6 = y0 = y_table[y0]
|
|
||||||
ADD r11,r11,r12 ; r11 = uv = u+v
|
|
||||||
|
|
||||||
ADD r7, r7, r11 ; r7 = y2 + uv
|
|
||||||
ADD r6, r6, r11 ; r6 = y0 + uv
|
|
||||||
ANDS r12,r7, r5
|
|
||||||
TSTEQ r6, r5
|
|
||||||
BNE fix101
|
|
||||||
return101
|
|
||||||
; Store the bottom one first
|
|
||||||
ADD r12,r0, r9
|
|
||||||
STRB r7,[r12],#1 ; Store R
|
|
||||||
MOV r7, r7, ROR #22
|
|
||||||
STRB r7,[r12],#1 ; Store G
|
|
||||||
MOV r7, r7, ROR #21
|
|
||||||
STRB r7,[r12],#1 ; Store B
|
|
||||||
|
|
||||||
; Then store the top one
|
|
||||||
STRB r6,[r0], #1 ; Store R
|
|
||||||
MOV r6, r6, ROR #22
|
|
||||||
STRB r6,[r0], #1 ; Store G
|
|
||||||
|
|
||||||
LDRB r7, [r1, r10] ; r7 = y3 = y_ptr[stride]
|
|
||||||
LDRB r12,[r1], #1 ; r12= y1 = *y_ptr++
|
|
||||||
MOV r6, r6, ROR #21
|
|
||||||
LDR r7, [r14, r7, LSL #2] ; r7 = y3 = y_table[y2]
|
|
||||||
LDR r12,[r14, r12,LSL #2] ; r12= y1 = y_table[y0]
|
|
||||||
STRB r6,[r0], #1 ; Store B
|
|
||||||
|
|
||||||
ADD r7, r7, r11 ; r7 = y3 + uv
|
|
||||||
ADD r6, r12,r11 ; r6 = y1 + uv
|
|
||||||
ANDS r12,r7, r5
|
|
||||||
TSTEQ r6, r5
|
|
||||||
BNE fix102
|
|
||||||
return102
|
|
||||||
; Store the bottom one first
|
|
||||||
ADD r12,r0, r9
|
|
||||||
STRB r7,[r12],#1 ; Store R
|
|
||||||
MOV r7, r7, ROR #22
|
|
||||||
STRB r7,[r12],#1 ; Store G
|
|
||||||
MOV r7, r7, ROR #21
|
|
||||||
STRB r7,[r12],#1 ; Store B
|
|
||||||
|
|
||||||
; Then store the top one
|
|
||||||
STRB r6,[r0], #1 ; Store R
|
|
||||||
MOV r6, r6, ROR #22
|
|
||||||
STRB r6,[r0], #1 ; Store G
|
|
||||||
MOV r6, r6, ROR #21
|
|
||||||
STRB r6,[r0], #1 ; Store B
|
|
||||||
|
|
||||||
ADDS r8, r8, #2<<16
|
|
||||||
BLT xloop1
|
|
||||||
MOVS r8, r8, LSL #16 ; Clear the top 16 bits of r8
|
|
||||||
MOV r8, r8, LSR #16 ; If the C bit is clear we still have
|
|
||||||
BCC trail_pair1 ; 1 more pixel pair to do
|
|
||||||
end_xloop1
|
|
||||||
LDR r11,[r13,#9*4] ; r11= width
|
|
||||||
LDR r12,[r13,#12*4] ; r12= uv_stride
|
|
||||||
ADD r0, r0, r9, LSL #1
|
|
||||||
SUB r0, r0, r11,LSL #1
|
|
||||||
SUB r0, r0, r11
|
|
||||||
ADD r1, r1, r10,LSL #1
|
|
||||||
SUB r1, r1, r11
|
|
||||||
SUB r2, r2, r11,LSR #1
|
|
||||||
SUB r3, r3, r11,LSR #1
|
|
||||||
ADD r2, r2, r12
|
|
||||||
ADD r3, r3, r12
|
|
||||||
|
|
||||||
SUBS r8, r8, #2
|
|
||||||
BGT yloop1
|
|
||||||
|
|
||||||
LDMLTFD r13!,{r4-r11,pc}
|
|
||||||
trail_row1
|
|
||||||
; We have a row of pixels left to do
|
|
||||||
SUB r8, r8, r11,LSL #16 ; r8 = height-(width<<16)
|
|
||||||
ADDS r8, r8, #1<<16 ; if (width == 1)
|
|
||||||
BGE trail_pix1 ; just do 1 pixel
|
|
||||||
xloop12
|
|
||||||
LDRB r11,[r2], #1 ; r11 = u = *u_ptr++
|
|
||||||
LDRB r12,[r3], #1 ; r12 = v = *v_ptr++
|
|
||||||
LDRB r6, [r1], #1 ; r6 = y0 = *y_ptr++
|
|
||||||
LDRB r7, [r1], #1 ; r7 = y1 = *y_ptr++
|
|
||||||
ADD r12,r12,#512
|
|
||||||
LDR r11,[r4, r11,LSL #2] ; r11 = u = u_table[u]
|
|
||||||
LDR r12,[r14,r12,LSL #2] ; r12 = v = v_table[v]
|
|
||||||
LDR r7, [r14,r7, LSL #2] ; r7 = y1 = y_table[y1]
|
|
||||||
LDR r6, [r14,r6, LSL #2] ; r6 = y0 = y_table[y0]
|
|
||||||
ADD r11,r11,r12 ; r11 = uv = u+v
|
|
||||||
|
|
||||||
ADD r6, r6, r11 ; r6 = y0 + uv
|
|
||||||
ADD r7, r7, r11 ; r7 = y1 + uv
|
|
||||||
ANDS r12,r7, r5
|
|
||||||
TSTEQ r6, r5
|
|
||||||
BNE fix104
|
|
||||||
return104
|
|
||||||
; Store the bottom one first
|
|
||||||
STRB r6,[r0], #1 ; Store R
|
|
||||||
MOV r6, r6, ROR #22
|
|
||||||
STRB r6,[r0], #1 ; Store G
|
|
||||||
MOV r6, r6, ROR #21
|
|
||||||
STRB r6,[r0], #1 ; Store B
|
|
||||||
|
|
||||||
; Then store the top one
|
|
||||||
STRB r7,[r0], #1 ; Store R
|
|
||||||
MOV r7, r7, ROR #22
|
|
||||||
STRB r7,[r0], #1 ; Store G
|
|
||||||
MOV r7, r7, ROR #21
|
|
||||||
STRB r7,[r0], #1 ; Store B
|
|
||||||
|
|
||||||
ADDS r8, r8, #2<<16
|
|
||||||
BLT xloop12
|
|
||||||
MOVS r8, r8, LSL #16 ; Clear the top 16 bits of r8
|
|
||||||
MOV r8, r8, LSR #16 ; If the C bit is clear we still have
|
|
||||||
BCC trail_pix1 ; 1 more pixel pair to do
|
|
||||||
end
|
|
||||||
LDMFD r13!,{r4-r11,pc}
|
|
||||||
trail_pix1
|
|
||||||
; We have a single extra pixel to do
|
|
||||||
LDRB r11,[r2], #1 ; r11 = u = *u_ptr++
|
|
||||||
LDRB r12,[r3], #1 ; r12 = v = *v_ptr++
|
|
||||||
LDRB r6, [r1], #1 ; r6 = y0 = *y_ptr++
|
|
||||||
ADD r12,r12,#512
|
|
||||||
LDR r11,[r4, r11,LSL #2] ; r11 = u = u_table[u]
|
|
||||||
LDR r12,[r14,r12,LSL #2] ; r12 = v = v_table[v]
|
|
||||||
LDR r6, [r14,r6, LSL #2] ; r6 = y0 = y_table[y0]
|
|
||||||
ADD r11,r11,r12 ; r11 = uv = u+v
|
|
||||||
|
|
||||||
ADD r6, r6, r11 ; r6 = y0 + uv
|
|
||||||
ANDS r12,r6, r5
|
|
||||||
BNE fix105
|
|
||||||
return105
|
|
||||||
STRB r6,[r0], #1 ; Store R
|
|
||||||
MOV r6, r6, ROR #22
|
|
||||||
STRB r6,[r0], #1 ; Store G
|
|
||||||
MOV r6, r6, ROR #21
|
|
||||||
STRB r6,[r0], #1 ; Store B
|
|
||||||
|
|
||||||
LDMFD r13!,{r4-r11,pc}
|
|
||||||
|
|
||||||
trail_pair1
|
|
||||||
; We have a pair of pixels left to do
|
|
||||||
LDRB r11,[r2] ; r11 = u = *u_ptr++
|
|
||||||
LDRB r12,[r3] ; r12 = v = *v_ptr++
|
|
||||||
LDRB r7, [r1, r10] ; r7 = y2 = y_ptr[stride]
|
|
||||||
LDRB r6, [r1], #1 ; r6 = y0 = *y_ptr++
|
|
||||||
ADD r12,r12,#512
|
|
||||||
LDR r11,[r4, r11,LSL #2] ; r11 = u = u_table[u]
|
|
||||||
LDR r12,[r14,r12,LSL #2] ; r12 = v = v_table[v]
|
|
||||||
LDR r7, [r14,r7, LSL #2] ; r7 = y2 = y_table[y2]
|
|
||||||
LDR r6, [r14,r6, LSL #2] ; r6 = y0 = y_table[y0]
|
|
||||||
ADD r11,r11,r12 ; r11 = uv = u+v
|
|
||||||
|
|
||||||
ADD r7, r7, r11 ; r7 = y2 + uv
|
|
||||||
ADD r6, r6, r11 ; r6 = y0 + uv
|
|
||||||
ANDS r12,r7, r5
|
|
||||||
TSTEQ r6, r5
|
|
||||||
BNE fix103
|
|
||||||
return103
|
|
||||||
; Store the bottom one first
|
|
||||||
ADD r12,r0, r9
|
|
||||||
STRB r7,[r12],#1 ; Store R
|
|
||||||
MOV r7, r7, ROR #22
|
|
||||||
STRB r7,[r12],#1 ; Store G
|
|
||||||
MOV r7, r7, ROR #21
|
|
||||||
STRB r7,[r12],#1 ; Store B
|
|
||||||
|
|
||||||
; Then store the top one
|
|
||||||
STRB r6,[r0], #1 ; Store R
|
|
||||||
MOV r6, r6, ROR #22
|
|
||||||
STRB r6,[r0], #1 ; Store G
|
|
||||||
MOV r6, r6, ROR #21
|
|
||||||
STRB r6,[r0], #1 ; Store B
|
|
||||||
B end_xloop1
|
|
||||||
fix101
|
|
||||||
; r7 and r6 are the values, at least one of which has overflowed
|
|
||||||
; r12 = r7 & mask = .s......s......s......
|
|
||||||
SUB r12,r12,r12,LSR #8 ; r12 = ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
ORR r7, r7, r12 ; r7 |= ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
BIC r12,r5, r7, LSR #1 ; r12 = .o......o......o......
|
|
||||||
ADD r7, r7, r12,LSR #8 ; r7 = fixed value
|
|
||||||
|
|
||||||
AND r12, r6, r5 ; r12 = .S......S......S......
|
|
||||||
SUB r12,r12,r12,LSR #8 ; r12 = ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
ORR r6, r6, r12 ; r6 |= ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
BIC r12,r5, r6, LSR #1 ; r12 = .o......o......o......
|
|
||||||
ADD r6, r6, r12,LSR #8 ; r6 = fixed value
|
|
||||||
B return101
|
|
||||||
fix102
|
|
||||||
; r7 and r6 are the values, at least one of which has overflowed
|
|
||||||
; r12 = r7 & mask = .s......s......s......
|
|
||||||
SUB r12,r12,r12,LSR #8 ; r12 = ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
ORR r7, r7, r12 ; r7 |= ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
BIC r12,r5, r7, LSR #1 ; r12 = .o......o......o......
|
|
||||||
ADD r7, r7, r12,LSR #8 ; r7 = fixed value
|
|
||||||
|
|
||||||
AND r12, r6, r5 ; r12 = .S......S......S......
|
|
||||||
SUB r12,r12,r12,LSR #8 ; r12 = ..SSSSSS..SSSSS.SSSSSS
|
|
||||||
ORR r6, r6, r12 ; r6 |= ..SSSSSS..SSSSS.SSSSSS
|
|
||||||
BIC r12,r5, r6, LSR #1 ; r12 = .o......o......o......
|
|
||||||
ADD r6, r6, r12,LSR #8 ; r6 = fixed value
|
|
||||||
B return102
|
|
||||||
fix103
|
|
||||||
; r7 and r6 are the values, at least one of which has overflowed
|
|
||||||
; r12 = r7 & mask = .s......s......s......
|
|
||||||
SUB r12,r12,r12,LSR #8 ; r12 = ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
ORR r7, r7, r12 ; r7 |= ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
BIC r12,r5, r7, LSR #1 ; r12 = .o......o......o......
|
|
||||||
ADD r7, r7, r12,LSR #8 ; r7 = fixed value
|
|
||||||
|
|
||||||
AND r12, r6, r5 ; r12 = .S......S......S......
|
|
||||||
SUB r12,r12,r12,LSR #8 ; r12 = ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
ORR r6, r6, r12 ; r6 |= ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
BIC r12,r5, r6, LSR #1 ; r12 = .o......o......o......
|
|
||||||
ADD r6, r6, r12,LSR #8 ; r6 = fixed value
|
|
||||||
B return103
|
|
||||||
fix104
|
|
||||||
; r7 and r6 are the values, at least one of which has overflowed
|
|
||||||
; r12 = r7 & mask = .s......s......s......
|
|
||||||
SUB r12,r12,r12,LSR #8 ; r12 = ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
ORR r7, r7, r12 ; r7 |= ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
BIC r12,r5, r7, LSR #1 ; r12 = .o......o......o......
|
|
||||||
ADD r7, r7, r12,LSR #8 ; r7 = fixed value
|
|
||||||
|
|
||||||
AND r12, r6, r5 ; r12 = .S......S......S......
|
|
||||||
SUB r12,r12,r12,LSR #8 ; r12 = ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
ORR r6, r6, r12 ; r6 |= ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
BIC r12,r5, r6, LSR #1 ; r12 = .o......o......o......
|
|
||||||
ADD r6, r6, r12,LSR #8 ; r6 = fixed value
|
|
||||||
B return104
|
|
||||||
fix105
|
|
||||||
; r6 is the value, which has has overflowed
|
|
||||||
; r12 = r7 & mask = .s......s......s......
|
|
||||||
SUB r12,r12,r12,LSR #8 ; r12 = ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
ORR r6, r6, r12 ; r6 |= ..SSSSSS.SSSSSS.SSSSSS
|
|
||||||
BIC r12,r5, r6, LSR #1 ; r12 = .o......o......o......
|
|
||||||
ADD r6, r6, r12,LSR #8 ; r6 = fixed value
|
|
||||||
B return105
|
|
||||||
|
|
||||||
END
|
|
@ -1,208 +0,0 @@
|
|||||||
/* YUV-> RGB conversion code. (YUV420 to RGB565)
|
|
||||||
*
|
|
||||||
* Copyright (C) 2008-9 Robin Watts (robin@wss.co.uk) for Pinknoise
|
|
||||||
* Productions Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU GPL. If you need it under another license, contact
|
|
||||||
* me and ask.
|
|
||||||
*
|
|
||||||
* This program is free software ; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation ; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program ; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* The algorithm used here is based heavily on one created by Sophie Wilson
|
|
||||||
* of Acorn/e-14/Broadcomm. Many thanks.
|
|
||||||
*
|
|
||||||
* Additional tweaks (in the fast fixup code) are from Paul Gardiner.
|
|
||||||
*
|
|
||||||
* The old implementation of YUV -> RGB did:
|
|
||||||
*
|
|
||||||
* R = CLAMP((Y-16)*1.164 + 1.596*V)
|
|
||||||
* G = CLAMP((Y-16)*1.164 - 0.391*U - 0.813*V)
|
|
||||||
* B = CLAMP((Y-16)*1.164 + 2.018*U )
|
|
||||||
*
|
|
||||||
* We're going to bend that here as follows:
|
|
||||||
*
|
|
||||||
* R = CLAMP(y + 1.596*V)
|
|
||||||
* G = CLAMP(y - 0.383*U - 0.813*V)
|
|
||||||
* B = CLAMP(y + 1.976*U )
|
|
||||||
*
|
|
||||||
* where y = 0 for Y <= 16,
|
|
||||||
* y = ( Y-16)*1.164, for 16 < Y <= 239,
|
|
||||||
* y = (239-16)*1.164, for 239 < Y
|
|
||||||
*
|
|
||||||
* i.e. We clamp Y to the 16 to 239 range (which it is supposed to be in
|
|
||||||
* anyway). We then pick the B_U factor so that B never exceeds 511. We then
|
|
||||||
* shrink the G_U factor in line with that to avoid a colour shift as much as
|
|
||||||
* possible.
|
|
||||||
*
|
|
||||||
* We're going to use tables to do it faster, but rather than doing it using
|
|
||||||
* 5 tables as as the above suggests, we're going to do it using just 3.
|
|
||||||
*
|
|
||||||
* We do this by working in parallel within a 32 bit word, and using one
|
|
||||||
* table each for Y U and V.
|
|
||||||
*
|
|
||||||
* Source Y values are 0 to 255, so 0.. 260 after scaling
|
|
||||||
* Source U values are -128 to 127, so -49.. 49(G), -253..251(B) after
|
|
||||||
* Source V values are -128 to 127, so -204..203(R), -104..103(G) after
|
|
||||||
*
|
|
||||||
* So total summed values:
|
|
||||||
* -223 <= R <= 481, -173 <= G <= 431, -253 <= B < 511
|
|
||||||
*
|
|
||||||
* We need to pack R G and B into a 32 bit word, and because of Bs range we
|
|
||||||
* need 2 bits above the valid range of B to detect overflow, and another one
|
|
||||||
* to detect the sense of the overflow. We therefore adopt the following
|
|
||||||
* representation:
|
|
||||||
*
|
|
||||||
* osGGGGGgggggosBBBBBbbbosRRRRRrrr
|
|
||||||
*
|
|
||||||
* Each such word breaks down into 3 ranges.
|
|
||||||
*
|
|
||||||
* osGGGGGggggg osBBBBBbbb osRRRRRrrr
|
|
||||||
*
|
|
||||||
* Thus we have 8 bits for each B and R table entry, and 10 bits for G (good
|
|
||||||
* as G is the most noticable one). The s bit for each represents the sign,
|
|
||||||
* and o represents the overflow.
|
|
||||||
*
|
|
||||||
* For R and B we pack the table by taking the 11 bit representation of their
|
|
||||||
* values, and toggling bit 10 in the U and V tables.
|
|
||||||
*
|
|
||||||
* For the green case we calculate 4*G (thus effectively using 10 bits for the
|
|
||||||
* valid range) truncate to 12 bits. We toggle bit 11 in the Y table.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "yuv2rgb.h"
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
FLAGS = 0x40080100
|
|
||||||
};
|
|
||||||
|
|
||||||
#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
|
|
||||||
#define READY(Y) tables[Y]
|
|
||||||
#define FIXUP(Y) \
|
|
||||||
do { \
|
|
||||||
int tmp = (Y) & FLAGS; \
|
|
||||||
if (tmp != 0) \
|
|
||||||
{ \
|
|
||||||
tmp -= tmp>>8; \
|
|
||||||
(Y) |= tmp; \
|
|
||||||
tmp = FLAGS & ~(Y>>1); \
|
|
||||||
(Y) += tmp>>8; \
|
|
||||||
} \
|
|
||||||
} while (0 == 1)
|
|
||||||
|
|
||||||
#define STORE(Y,DSTPTR) \
|
|
||||||
do { \
|
|
||||||
uint32_t Y2 = (Y); \
|
|
||||||
uint8_t *DSTPTR2 = (DSTPTR); \
|
|
||||||
(DSTPTR2)[0] = (Y2); \
|
|
||||||
(DSTPTR2)[1] = (Y2)>>22; \
|
|
||||||
(DSTPTR2)[2] = (Y2)>>11; \
|
|
||||||
} while (0 == 1)
|
|
||||||
|
|
||||||
void yuv420_2_rgb888(uint8_t *dst_ptr,
|
|
||||||
const uint8_t *y_ptr,
|
|
||||||
const uint8_t *u_ptr,
|
|
||||||
const uint8_t *v_ptr,
|
|
||||||
int32_t width,
|
|
||||||
int32_t height,
|
|
||||||
int32_t y_span,
|
|
||||||
int32_t uv_span,
|
|
||||||
int32_t dst_span,
|
|
||||||
const uint32_t *tables,
|
|
||||||
int32_t dither)
|
|
||||||
{
|
|
||||||
height -= 1;
|
|
||||||
while (height > 0)
|
|
||||||
{
|
|
||||||
height -= width<<16;
|
|
||||||
height += 1<<16;
|
|
||||||
while (height < 0)
|
|
||||||
{
|
|
||||||
/* Do 2 column pairs */
|
|
||||||
uint32_t uv, y0, y1;
|
|
||||||
|
|
||||||
uv = READUV(*u_ptr++,*v_ptr++);
|
|
||||||
y1 = uv + READY(y_ptr[y_span]);
|
|
||||||
y0 = uv + READY(*y_ptr++);
|
|
||||||
FIXUP(y1);
|
|
||||||
FIXUP(y0);
|
|
||||||
STORE(y1, &dst_ptr[dst_span]);
|
|
||||||
STORE(y0, dst_ptr);
|
|
||||||
dst_ptr += 3;
|
|
||||||
y1 = uv + READY(y_ptr[y_span]);
|
|
||||||
y0 = uv + READY(*y_ptr++);
|
|
||||||
FIXUP(y1);
|
|
||||||
FIXUP(y0);
|
|
||||||
STORE(y1, &dst_ptr[dst_span]);
|
|
||||||
STORE(y0, dst_ptr);
|
|
||||||
dst_ptr += 3;
|
|
||||||
height += (2<<16);
|
|
||||||
}
|
|
||||||
if ((height>>16) == 0)
|
|
||||||
{
|
|
||||||
/* Trailing column pair */
|
|
||||||
uint32_t uv, y0, y1;
|
|
||||||
|
|
||||||
uv = READUV(*u_ptr,*v_ptr);
|
|
||||||
y1 = uv + READY(y_ptr[y_span]);
|
|
||||||
y0 = uv + READY(*y_ptr++);
|
|
||||||
FIXUP(y1);
|
|
||||||
FIXUP(y0);
|
|
||||||
STORE(y0, &dst_ptr[dst_span]);
|
|
||||||
STORE(y1, dst_ptr);
|
|
||||||
dst_ptr += 3;
|
|
||||||
}
|
|
||||||
dst_ptr += dst_span*2-width*3;
|
|
||||||
y_ptr += y_span*2-width;
|
|
||||||
u_ptr += uv_span-(width>>1);
|
|
||||||
v_ptr += uv_span-(width>>1);
|
|
||||||
height = (height<<16)>>16;
|
|
||||||
height -= 2;
|
|
||||||
}
|
|
||||||
if (height == 0)
|
|
||||||
{
|
|
||||||
/* Trail row */
|
|
||||||
height -= width<<16;
|
|
||||||
height += 1<<16;
|
|
||||||
while (height < 0)
|
|
||||||
{
|
|
||||||
/* Do a row pair */
|
|
||||||
uint32_t uv, y0, y1;
|
|
||||||
|
|
||||||
uv = READUV(*u_ptr++,*v_ptr++);
|
|
||||||
y1 = uv + READY(*y_ptr++);
|
|
||||||
y0 = uv + READY(*y_ptr++);
|
|
||||||
FIXUP(y1);
|
|
||||||
FIXUP(y0);
|
|
||||||
STORE(y1, dst_ptr);
|
|
||||||
dst_ptr += 3;
|
|
||||||
STORE(y0, dst_ptr);
|
|
||||||
dst_ptr += 3;
|
|
||||||
height += (2<<16);
|
|
||||||
}
|
|
||||||
if ((height>>16) == 0)
|
|
||||||
{
|
|
||||||
/* Trailing pix */
|
|
||||||
uint32_t uv, y0;
|
|
||||||
|
|
||||||
uv = READUV(*u_ptr++,*v_ptr++);
|
|
||||||
y0 = uv + READY(*y_ptr++);
|
|
||||||
FIXUP(y0);
|
|
||||||
STORE(y0, dst_ptr);
|
|
||||||
dst_ptr += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,156 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
#include <jni.h>
|
|
||||||
|
|
||||||
#include <yuv420sp2rgb.h>
|
|
||||||
#include <yuv2rgb.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved
|
|
||||||
U/V plane containing 8 bit 2x2 subsampled chroma samples.
|
|
||||||
except the interleave order of U and V is reversed.
|
|
||||||
|
|
||||||
H V
|
|
||||||
Y Sample Period 1 1
|
|
||||||
U (Cb) Sample Period 2 2
|
|
||||||
V (Cr) Sample Period 2 2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
size of a char:
|
|
||||||
find . -name limits.h -exec grep CHAR_BIT {} \;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef max
|
|
||||||
#define max(a,b) (a > b ? a : b )
|
|
||||||
#define min(a,b) (a < b ? a : b )
|
|
||||||
#endif
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
FLAGS = 0x40080100
|
|
||||||
};
|
|
||||||
|
|
||||||
#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
|
|
||||||
#define READY(Y) tables[Y]
|
|
||||||
#define FIXUP(Y) \
|
|
||||||
do { \
|
|
||||||
int tmp = (Y) & FLAGS; \
|
|
||||||
if (tmp != 0) \
|
|
||||||
{ \
|
|
||||||
tmp -= tmp>>8; \
|
|
||||||
(Y) |= tmp; \
|
|
||||||
tmp = FLAGS & ~(Y>>1); \
|
|
||||||
(Y) += tmp>>8; \
|
|
||||||
} \
|
|
||||||
} while (0 == 1)
|
|
||||||
|
|
||||||
#define STORE(Y,DSTPTR) \
|
|
||||||
do { \
|
|
||||||
uint32_t Y2 = (Y); \
|
|
||||||
uint8_t *DSTPTR2 = (DSTPTR); \
|
|
||||||
(DSTPTR2)[2] = (Y2); \
|
|
||||||
(DSTPTR2)[1] = (Y2)>>22; \
|
|
||||||
(DSTPTR2)[0] = (Y2)>>11; \
|
|
||||||
} while (0 == 1)
|
|
||||||
|
|
||||||
typedef unsigned char byte;
|
|
||||||
const int bytes_per_pixel = 2;
|
|
||||||
void color_convert_common(const unsigned char *pY, const unsigned char *pUV, int width, int height,
|
|
||||||
unsigned char *buffer, int grey)
|
|
||||||
{
|
|
||||||
#define LOOKUP 1
|
|
||||||
#if ! LOOKUP
|
|
||||||
int nR, nG, nB;
|
|
||||||
#endif
|
|
||||||
int dest_span = 3 * width;
|
|
||||||
unsigned char *out = buffer;
|
|
||||||
if (grey)
|
|
||||||
{
|
|
||||||
memcpy(out, pY, width * height * sizeof(unsigned char));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
#if LOOKUP
|
|
||||||
const uint32_t* tables = yuv2rgb565_table;
|
|
||||||
const byte* nY = pY;
|
|
||||||
const byte* nUV = pUV;
|
|
||||||
int idx = 0;
|
|
||||||
while (nY+width < pUV)
|
|
||||||
{
|
|
||||||
int y = (idx / width);
|
|
||||||
int x = (idx % width);
|
|
||||||
byte Y = *nY;
|
|
||||||
byte Y2 = nY[width];
|
|
||||||
byte V = *nUV;
|
|
||||||
byte U = *(nUV + 1);
|
|
||||||
/* Do 2 row pairs */
|
|
||||||
uint32_t uv, y0, y1;
|
|
||||||
|
|
||||||
uv = READUV(U,V);
|
|
||||||
y1 = uv + READY(Y);
|
|
||||||
y0 = uv + READY(Y2);
|
|
||||||
FIXUP(y1);
|
|
||||||
FIXUP(y0);
|
|
||||||
STORE(y1, &out[dest_span]);
|
|
||||||
STORE(y0, out);
|
|
||||||
out += 3;
|
|
||||||
Y = *(++nY);
|
|
||||||
Y2 = nY[width];
|
|
||||||
y1 = uv + READY(Y);
|
|
||||||
y0 = uv + READY(Y2);
|
|
||||||
FIXUP(y1);
|
|
||||||
FIXUP(y0);
|
|
||||||
STORE(y1, &out[dest_span]);
|
|
||||||
STORE(y0, out);
|
|
||||||
out += 3;
|
|
||||||
height += (2 << 16);
|
|
||||||
++nY;
|
|
||||||
nUV = pUV + (y / 2) * width + 2 * (x / 2);
|
|
||||||
idx+=2;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
const byte* nY = pY;
|
|
||||||
const byte* nUV = pUV;
|
|
||||||
int idx = 0;
|
|
||||||
while (nY < pUV)
|
|
||||||
{
|
|
||||||
|
|
||||||
int y = (idx / width);
|
|
||||||
int x = (idx % width);
|
|
||||||
int Y = *nY;
|
|
||||||
int V = *nUV;
|
|
||||||
int U = *(nUV + 1);
|
|
||||||
|
|
||||||
Y -= 16;
|
|
||||||
V -= 128;
|
|
||||||
U -= 128;
|
|
||||||
if (y < 0)
|
|
||||||
y = 0;
|
|
||||||
|
|
||||||
nB = (int)(1192 * Y + 2066 * U);
|
|
||||||
nG = (int)(1192 * Y - 833 * V - 400 * U);
|
|
||||||
nR = (int)(1192 * Y + 1634 * V);
|
|
||||||
|
|
||||||
nR = min(262143, max(0, nR));
|
|
||||||
nG = min(262143, max(0, nG));
|
|
||||||
nB = min(262143, max(0, nB));
|
|
||||||
|
|
||||||
nR >>= 10;
|
|
||||||
nR &= 0xff;
|
|
||||||
nG >>= 10;
|
|
||||||
nG &= 0xff;
|
|
||||||
nB >>= 10;
|
|
||||||
nB &= 0xff;
|
|
||||||
|
|
||||||
*(out++) = (unsigned char)nR;
|
|
||||||
*(out++) = (unsigned char)nG;
|
|
||||||
*(out++) = (unsigned char)nB;
|
|
||||||
nY += 1;
|
|
||||||
nUV = pUV + (y / 2) * width + 2 * (x / 2);
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#this generates an ant based cli build of the android-jni project
|
|
||||||
android update project --name android-opencv \
|
|
||||||
--path .
|
|
Before Width: | Height: | Size: 161 KiB |
@ -1,11 +0,0 @@
|
|||||||
<?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:scrollbars="vertical" android:id="@+id/calibtext" android:text="" android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" android:padding="20dip"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,28 +0,0 @@
|
|||||||
<?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">
|
|
||||||
<!--<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/button_capture" android:layout_width="60dip"
|
|
||||||
android:layout_height="60dip" android:layout_marginBottom="10dip"></ImageButton>
|
|
||||||
<ImageButton android:src="@android:drawable/ic_menu_preferences"
|
|
||||||
android:id="@+id/button_camera_settings" android:layout_width="60dip"
|
|
||||||
android:layout_height="60dip" android:layout_marginBottom="10dip"></ImageButton>
|
|
||||||
</LinearLayout>
|
|
||||||
</RelativeLayout>
|
|
@ -1,43 +0,0 @@
|
|||||||
<?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/settings_text"
|
|
||||||
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="@string/image_size_prompt" />
|
|
||||||
<Spinner android:id="@+id/image_size" android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content" android:saveEnabled="true"
|
|
||||||
android:prompt="@string/image_size_prompt" android:entries="@array/image_sizes">
|
|
||||||
</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="@string/camera_mode_prompt" />
|
|
||||||
<Spinner android:id="@+id/camera_mode" android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content" android:saveEnabled="true"
|
|
||||||
android:prompt="@string/camera_mode_prompt" android:entries="@array/camera_mode">
|
|
||||||
</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="@string/whitebalance_prompt" />
|
|
||||||
<Spinner android:id="@+id/whitebalance" android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content" android:saveEnabled="true"
|
|
||||||
android:prompt="@string/whitebalance_prompt" android:entries="@array/whitebalance">
|
|
||||||
</Spinner>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,40 +0,0 @@
|
|||||||
<?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>
|
|
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<declare-styleable name="CameraParams">
|
|
||||||
|
|
||||||
<attr name="preview_width" format="integer"/>
|
|
||||||
<attr name="preview_height" format="integer"/>
|
|
||||||
|
|
||||||
</declare-styleable>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string-array name="chesssizes">
|
|
||||||
<item>2</item>
|
|
||||||
<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>
|
|
@ -1,31 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string-array name="image_sizes">
|
|
||||||
<item>320x240</item>
|
|
||||||
<item>400x300</item>
|
|
||||||
<item>640x480</item>
|
|
||||||
<item>800x600</item>
|
|
||||||
<item>1000x800</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="camera_mode">
|
|
||||||
<item>color</item>
|
|
||||||
<item>BW</item>
|
|
||||||
</string-array>
|
|
||||||
<string name="image_size_prompt">
|
|
||||||
Image Size:\n(may not be exact)
|
|
||||||
</string>
|
|
||||||
<string name="camera_mode_prompt">
|
|
||||||
Camera Mode:
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<string-array name="whitebalance">
|
|
||||||
<item>auto</item>
|
|
||||||
<item>incandescent</item>
|
|
||||||
<item>fluorescent</item>
|
|
||||||
<item>daylight</item>
|
|
||||||
<item>cloudy-daylight</item>
|
|
||||||
</string-array>
|
|
||||||
<string name="whitebalance_prompt">
|
|
||||||
Whitebalance:
|
|
||||||
</string>
|
|
||||||
</resources>
|
|
@ -1,20 +0,0 @@
|
|||||||
<?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="camera_settings_label">Camera Settings</string>
|
|
||||||
<string name="settings_text">Change the camera settings. Be aware that BW is much faster for previewing, than color. Also, if you change the image size, you should
|
|
||||||
rerun calibration. Default values: BW and 640x480 are a good start.</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 10 images of the pattern!</string>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -1,157 +0,0 @@
|
|||||||
package com.opencv;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.view.ViewGroup.LayoutParams;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import com.opencv.camera.NativePreviewer;
|
|
||||||
import com.opencv.camera.NativeProcessor;
|
|
||||||
import com.opencv.camera.NativeProcessor.PoolCallback;
|
|
||||||
import com.opencv.opengl.GL2CameraViewer;
|
|
||||||
|
|
||||||
public class OpenCV extends Activity {
|
|
||||||
private NativePreviewer mPreview;
|
|
||||||
|
|
||||||
private GL2CameraViewer glview;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see android.app.Activity#onKeyUp(int, android.view.KeyEvent)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
|
||||||
|
|
||||||
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("Sample");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
// if(item.getTitle().equals("Sample")){
|
|
||||||
// //do stuff...
|
|
||||||
// }
|
|
||||||
|
|
||||||
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(getApplication());
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
frame.addView(glview);
|
|
||||||
|
|
||||||
setContentView(frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
|
|
||||||
mPreview.onPause();
|
|
||||||
|
|
||||||
glview.onPause();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
glview.onResume();
|
|
||||||
LinkedList<NativeProcessor.PoolCallback> callbackstack = new LinkedList<PoolCallback>();
|
|
||||||
callbackstack.add(glview.getDrawCallback());
|
|
||||||
mPreview.addCallbackStack(callbackstack);
|
|
||||||
mPreview.onResume();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package com.opencv.calibration;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.text.method.ScrollingMovementMethod;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.opencv.R;
|
|
||||||
|
|
||||||
public class CalibrationViewer extends Activity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.calibrationviewer);
|
|
||||||
|
|
||||||
Bundle extras = getIntent().getExtras();
|
|
||||||
String filename = extras.getString("calibfile");
|
|
||||||
if (filename != null) {
|
|
||||||
TextView text = (TextView) findViewById(R.id.calibtext);
|
|
||||||
text.setMovementMethod(new ScrollingMovementMethod());
|
|
||||||
try {
|
|
||||||
BufferedReader reader = new BufferedReader(new FileReader(
|
|
||||||
filename));
|
|
||||||
while (reader.ready()) {
|
|
||||||
text.append(reader.readLine() +"\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
Log.e("opencv", "could not open calibration file at:"
|
|
||||||
+ filename);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e("opencv", "error reading file: "
|
|
||||||
+ filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,124 +0,0 @@
|
|||||||
package com.opencv.calibration;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
|
|
||||||
import com.opencv.camera.NativeProcessor;
|
|
||||||
import com.opencv.camera.NativeProcessor.PoolCallback;
|
|
||||||
import com.opencv.jni.Calibration;
|
|
||||||
import com.opencv.jni.Size;
|
|
||||||
import com.opencv.jni.image_pool;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class Calibrator implements PoolCallback {
|
|
||||||
private Calibration calibration;
|
|
||||||
|
|
||||||
static public interface CalibrationCallback{
|
|
||||||
public void onFoundChessboard(Calibrator calibrator);
|
|
||||||
public void onDoneCalibration(Calibrator calibration, File calibfile);
|
|
||||||
public void onFailedChessboard(Calibrator calibrator);
|
|
||||||
}
|
|
||||||
private CalibrationCallback callback;
|
|
||||||
public Calibrator(CalibrationCallback callback) {
|
|
||||||
calibration = new Calibration();
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetCalibration(){
|
|
||||||
calibration.resetChess();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPatternSize(Size size){
|
|
||||||
Size csize = calibration.getPatternsize();
|
|
||||||
if(size.getWidth() == csize.getWidth()&&
|
|
||||||
size.getHeight() == csize.getHeight())
|
|
||||||
return;
|
|
||||||
calibration.setPatternsize(size);
|
|
||||||
resetCalibration();
|
|
||||||
}
|
|
||||||
public void setPatternSize(int width, int height){
|
|
||||||
Size patternsize = new Size(width,height);
|
|
||||||
setPatternSize(patternsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean capture_chess;
|
|
||||||
|
|
||||||
ReentrantLock lock = new ReentrantLock();
|
|
||||||
public void calibrate(File calibration_file) throws IOException{
|
|
||||||
if(getNumberPatternsDetected() < 3){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CalibrationTask calibtask = new CalibrationTask(calibration_file);
|
|
||||||
calibtask.execute((Object[])null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void queueChessCapture(){
|
|
||||||
capture_chess = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CalibrationTask extends AsyncTask<Object, Object, Object> {
|
|
||||||
File calibfile;
|
|
||||||
|
|
||||||
public CalibrationTask(File calib) throws IOException{
|
|
||||||
super();
|
|
||||||
calibfile = calib;
|
|
||||||
calibfile.createNewFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object doInBackground(Object... params) {
|
|
||||||
lock.lock();
|
|
||||||
try{
|
|
||||||
calibration.calibrate(calibfile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Object result) {
|
|
||||||
callback.onDoneCalibration(Calibrator.this, calibfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//@Override
|
|
||||||
public void process(int idx, image_pool pool, long timestamp,
|
|
||||||
NativeProcessor nativeProcessor) {
|
|
||||||
if(lock.tryLock()){
|
|
||||||
try{
|
|
||||||
if(capture_chess){
|
|
||||||
if(calibration.detectAndDrawChessboard(idx, pool)){
|
|
||||||
callback.onFoundChessboard(this);
|
|
||||||
|
|
||||||
}else
|
|
||||||
callback.onFailedChessboard(this);
|
|
||||||
capture_chess = false;
|
|
||||||
}
|
|
||||||
}finally{
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int getNumberPatternsDetected(){
|
|
||||||
return calibration.getNumberDetectedChessboards();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCallback(CalibrationCallback callback) {
|
|
||||||
this.callback = callback;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package com.opencv.calibration;
|
|
||||||
|
|
||||||
import com.opencv.R;
|
|
||||||
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 = 2;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,166 +0,0 @@
|
|||||||
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.R;
|
|
||||||
import com.opencv.calibration.CalibrationViewer;
|
|
||||||
import com.opencv.calibration.Calibrator;
|
|
||||||
import com.opencv.calibration.Calibrator.CalibrationCallback;
|
|
||||||
|
|
||||||
|
|
||||||
public class CalibrationService extends Service implements CalibrationCallback {
|
|
||||||
|
|
||||||
Class<?> activity;
|
|
||||||
int icon;
|
|
||||||
File calibration_file;
|
|
||||||
public void startCalibrating(Class<?> activitycaller,int icon_id, Calibrator calibrator, File calibration_file)
|
|
||||||
throws IOException {
|
|
||||||
activity = activitycaller;
|
|
||||||
icon = icon_id;
|
|
||||||
// Display a notification about us starting. We put an icon in the
|
|
||||||
// status bar.
|
|
||||||
showNotification();
|
|
||||||
this.calibration_file = calibration_file;
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@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(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, activity), 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(icon, text,
|
|
||||||
System.currentTimeMillis());
|
|
||||||
|
|
||||||
Intent intent = new Intent(this,CalibrationViewer.class);
|
|
||||||
intent.putExtra("calibfile", calibration_file.getAbsolutePath());
|
|
||||||
// The PendingIntent to launch our activity if the user selects this
|
|
||||||
// notification
|
|
||||||
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
|
||||||
intent, 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
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,128 +0,0 @@
|
|||||||
package com.opencv.camera;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import com.opencv.camera.CameraButtonsHandler.CaptureListener;
|
|
||||||
import com.opencv.opengl.GL2CameraViewer;
|
|
||||||
|
|
||||||
public abstract class CameraActivity extends Activity implements CaptureListener {
|
|
||||||
|
|
||||||
/** Called when the activity is first created. */
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setFullscreen();
|
|
||||||
setOrientation();
|
|
||||||
disableScreenTurnOff();
|
|
||||||
setContentView(com.opencv.R.layout.camera);
|
|
||||||
cameraButtonHandler = new CameraButtonsHandler(this,this);
|
|
||||||
mPreview = (NativePreviewer) findViewById(com.opencv.R.id.nativepreviewer);
|
|
||||||
LinearLayout glview_layout = (LinearLayout) findViewById(com.opencv.R.id.glview_layout);
|
|
||||||
glview = new GL2CameraViewer(getApplication(), true, 0, 0);
|
|
||||||
glview_layout.addView(glview);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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:
|
|
||||||
cameraButtonHandler.setIsCapture(true);
|
|
||||||
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) {
|
|
||||||
cameraButtonHandler.setIsCapture(true);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
mPreview.onPause();
|
|
||||||
glview.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
mPreview.setParamsFromPrefs(getApplicationContext());
|
|
||||||
glview.onResume();
|
|
||||||
mPreview.onResume();
|
|
||||||
setCallbackStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setCallbackStack() {
|
|
||||||
LinkedList<NativeProcessor.PoolCallback> callbackstack = getCallBackStack();
|
|
||||||
if (callbackstack == null){
|
|
||||||
callbackstack = new LinkedList<NativeProcessor.PoolCallback>();
|
|
||||||
callbackstack.add(glview.getDrawCallback());
|
|
||||||
}
|
|
||||||
mPreview.addCallbackStack(callbackstack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overide this and provide your processors to the camera
|
|
||||||
*
|
|
||||||
* @return null for default drawing
|
|
||||||
*/
|
|
||||||
protected abstract LinkedList<NativeProcessor.PoolCallback> getCallBackStack();
|
|
||||||
public void onCapture(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected NativePreviewer mPreview;
|
|
||||||
protected GL2CameraViewer glview;
|
|
||||||
protected CameraButtonsHandler cameraButtonHandler;
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
package com.opencv.camera;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
|
|
||||||
public class CameraButtonsHandler {
|
|
||||||
/** Constructs a buttons handler, will register with the capture button
|
|
||||||
* and the camera settings button.
|
|
||||||
* @param a The activity that has inflated the com.opencv.R.layout.camera
|
|
||||||
* as its layout.
|
|
||||||
*/
|
|
||||||
public CameraButtonsHandler(Activity a, CaptureListener l) {
|
|
||||||
ImageButton capture = (ImageButton) a
|
|
||||||
.findViewById(com.opencv.R.id.button_capture);
|
|
||||||
ImageButton settings = (ImageButton) a
|
|
||||||
.findViewById(com.opencv.R.id.button_camera_settings);
|
|
||||||
capture.setOnClickListener(capture_listener);
|
|
||||||
settings.setOnClickListener(settings_listener);
|
|
||||||
captureListener = l;
|
|
||||||
ctx = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CameraButtonsHandler(Activity a) {
|
|
||||||
ImageButton capture = (ImageButton) a
|
|
||||||
.findViewById(com.opencv.R.id.button_capture);
|
|
||||||
ImageButton settings = (ImageButton) a
|
|
||||||
.findViewById(com.opencv.R.id.button_camera_settings);
|
|
||||||
capture.setOnClickListener(capture_listener);
|
|
||||||
settings.setOnClickListener(settings_listener);
|
|
||||||
ctx = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Check if the capture button has been pressed
|
|
||||||
* @return true if the capture button has been pressed
|
|
||||||
*/
|
|
||||||
synchronized public boolean isCapture(){
|
|
||||||
return capture_flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reset the capture flag
|
|
||||||
*/
|
|
||||||
synchronized public void resetIsCapture(){
|
|
||||||
capture_flag = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Manually set the flag - call this on any event that should trigger
|
|
||||||
* a capture
|
|
||||||
* @param isCapture true if a capture should take place
|
|
||||||
*/
|
|
||||||
synchronized public void setIsCapture(boolean isCapture){
|
|
||||||
capture_flag = isCapture;
|
|
||||||
if(capture_flag && captureListener != null){
|
|
||||||
captureListener.onCapture();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private OnClickListener capture_listener = new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
setIsCapture(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private OnClickListener settings_listener = new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent configurer = new Intent(ctx,
|
|
||||||
CameraConfig.class);
|
|
||||||
ctx.startActivity(configurer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
interface CaptureListener{
|
|
||||||
public void onCapture();
|
|
||||||
}
|
|
||||||
private CaptureListener captureListener;
|
|
||||||
private Context ctx;
|
|
||||||
private boolean capture_flag = false;
|
|
||||||
}
|
|
@ -1,214 +0,0 @@
|
|||||||
package com.opencv.camera;
|
|
||||||
|
|
||||||
import com.opencv.R;
|
|
||||||
|
|
||||||
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 CameraConfig extends Activity {
|
|
||||||
public static final String CAMERA_SETTINGS = "CAMERA_SETTINGS";
|
|
||||||
public static final String CAMERA_MODE = "camera_mode";
|
|
||||||
public static final String IMAGE_WIDTH = "IMAGE_WIDTH";
|
|
||||||
public static final String IMAGE_HEIGHT = "IMAGE_HEIGHT";
|
|
||||||
public static final int CAMERA_MODE_BW = 0;
|
|
||||||
public static final int CAMERA_MODE_COLOR = 1;
|
|
||||||
private static final String WHITEBALANCE = "WHITEBALANCE";
|
|
||||||
|
|
||||||
public static int readCameraMode(Context ctx) {
|
|
||||||
// Restore preferences
|
|
||||||
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS,
|
|
||||||
0);
|
|
||||||
int mode = settings.getInt(CAMERA_MODE, CAMERA_MODE_BW);
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String readWhitebalace(Context ctx) {
|
|
||||||
// Restore preferences
|
|
||||||
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS,
|
|
||||||
0);
|
|
||||||
return settings.getString(WHITEBALANCE, "auto");
|
|
||||||
}
|
|
||||||
|
|
||||||
static public void setCameraMode(Context context, String mode) {
|
|
||||||
int m = 0;
|
|
||||||
if (mode.equals("BW")) {
|
|
||||||
m = CAMERA_MODE_BW;
|
|
||||||
} else if (mode.equals("color"))
|
|
||||||
m = CAMERA_MODE_COLOR;
|
|
||||||
setCameraMode(context, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String sizeToString(int[] size) {
|
|
||||||
return size[0] + "x" + size[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void parseStrToSize(String ssize, int[] size) {
|
|
||||||
String sz[] = ssize.split("x");
|
|
||||||
size[0] = Integer.valueOf(sz[0]);
|
|
||||||
size[1] = Integer.valueOf(sz[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void readImageSize(Context ctx, int[] size) {
|
|
||||||
// Restore preferences
|
|
||||||
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS,
|
|
||||||
0);
|
|
||||||
size[0] = settings.getInt(IMAGE_WIDTH, 640);
|
|
||||||
size[1] = settings.getInt(IMAGE_HEIGHT, 480);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setCameraMode(Context ctx, int mode) {
|
|
||||||
// Restore preferences
|
|
||||||
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS,
|
|
||||||
0);
|
|
||||||
Editor editor = settings.edit();
|
|
||||||
editor.putInt(CAMERA_MODE, mode);
|
|
||||||
editor.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setImageSize(Context ctx, String strsize) {
|
|
||||||
int size[] = { 0, 0 };
|
|
||||||
parseStrToSize(strsize, size);
|
|
||||||
setImageSize(ctx, size[0], size[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setImageSize(Context ctx, int width, int height) {
|
|
||||||
// Restore preferences
|
|
||||||
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS,
|
|
||||||
0);
|
|
||||||
Editor editor = settings.edit();
|
|
||||||
editor.putInt(IMAGE_WIDTH, width);
|
|
||||||
editor.putInt(IMAGE_HEIGHT, height);
|
|
||||||
editor.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.camerasettings);
|
|
||||||
int mode = readCameraMode(this);
|
|
||||||
int size[] = { 0, 0 };
|
|
||||||
readImageSize(this, size);
|
|
||||||
|
|
||||||
final Spinner size_spinner;
|
|
||||||
final Spinner mode_spinner;
|
|
||||||
final Spinner whitebalance_spinner;
|
|
||||||
size_spinner = (Spinner) findViewById(R.id.image_size);
|
|
||||||
mode_spinner = (Spinner) findViewById(R.id.camera_mode);
|
|
||||||
whitebalance_spinner = (Spinner) findViewById(R.id.whitebalance);
|
|
||||||
|
|
||||||
String strsize = sizeToString(size);
|
|
||||||
String strmode = modeToString(mode);
|
|
||||||
String wbmode = readWhitebalace(getApplicationContext());
|
|
||||||
|
|
||||||
String sizes[] = getResources().getStringArray(R.array.image_sizes);
|
|
||||||
|
|
||||||
int i = 1;
|
|
||||||
for (String x : sizes) {
|
|
||||||
if (x.equals(strsize))
|
|
||||||
break;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if(i <= sizes.length)
|
|
||||||
size_spinner.setSelection(i-1);
|
|
||||||
|
|
||||||
i = 1;
|
|
||||||
String modes[] = getResources().getStringArray(R.array.camera_mode);
|
|
||||||
for (String x :modes) {
|
|
||||||
if (x.equals(strmode))
|
|
||||||
break;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if(i <= modes.length)
|
|
||||||
mode_spinner.setSelection(i-1);
|
|
||||||
|
|
||||||
i = 1;
|
|
||||||
String wbmodes[] = getResources().getStringArray(R.array.whitebalance);
|
|
||||||
for (String x :wbmodes) {
|
|
||||||
if (x.equals(wbmode))
|
|
||||||
break;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if(i <= wbmodes.length)
|
|
||||||
whitebalance_spinner.setSelection(i-1);
|
|
||||||
|
|
||||||
size_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> arg0, View spinner,
|
|
||||||
int position, long arg3) {
|
|
||||||
Object o = size_spinner.getItemAtPosition(position);
|
|
||||||
if (o != null)
|
|
||||||
setImageSize(spinner.getContext(), (String) o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> arg0) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mode_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> arg0, View spinner,
|
|
||||||
int position, long arg3) {
|
|
||||||
Object o = mode_spinner.getItemAtPosition(position);
|
|
||||||
if (o != null)
|
|
||||||
setCameraMode(spinner.getContext(), (String) o);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> arg0) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
whitebalance_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> arg0, View spinner,
|
|
||||||
int position, long arg3) {
|
|
||||||
Object o = whitebalance_spinner.getItemAtPosition(position);
|
|
||||||
if (o != null)
|
|
||||||
setWhitebalance(spinner.getContext(), (String) o);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> arg0) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setWhitebalance(Context ctx, String o) {
|
|
||||||
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS,
|
|
||||||
0);
|
|
||||||
Editor editor = settings.edit();
|
|
||||||
editor.putString(WHITEBALANCE, o);
|
|
||||||
editor.commit();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String modeToString(int mode) {
|
|
||||||
switch (mode) {
|
|
||||||
case CAMERA_MODE_BW:
|
|
||||||
return "BW";
|
|
||||||
case CAMERA_MODE_COLOR:
|
|
||||||
return "color";
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,476 +0,0 @@
|
|||||||
package com.opencv.camera;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.hardware.Camera;
|
|
||||||
import android.hardware.Camera.PreviewCallback;
|
|
||||||
import android.hardware.Camera.Size;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.SurfaceHolder;
|
|
||||||
import android.view.SurfaceView;
|
|
||||||
|
|
||||||
import com.opencv.camera.NativeProcessor.NativeProcessorCallback;
|
|
||||||
import com.opencv.camera.NativeProcessor.PoolCallback;
|
|
||||||
|
|
||||||
public class NativePreviewer extends SurfaceView implements
|
|
||||||
SurfaceHolder.Callback, Camera.PreviewCallback, NativeProcessorCallback {
|
|
||||||
|
|
||||||
private String whitebalance_mode = "auto";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor useful for defining a NativePreviewer in android layout xml
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @param attributes
|
|
||||||
*/
|
|
||||||
public NativePreviewer(Context context, AttributeSet attributes) {
|
|
||||||
super(context, attributes);
|
|
||||||
listAllCameraMethods();
|
|
||||||
// Install a SurfaceHolder.Callback so we get notified when the
|
|
||||||
// underlying surface is created and destroyed.
|
|
||||||
mHolder = getHolder();
|
|
||||||
mHolder.addCallback(this);
|
|
||||||
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO get this working! Can't figure out how to define these in xml
|
|
||||||
*/
|
|
||||||
preview_width = attributes.getAttributeIntValue("opencv",
|
|
||||||
"preview_width", 600);
|
|
||||||
preview_height = attributes.getAttributeIntValue("opencv",
|
|
||||||
"preview_height", 600);
|
|
||||||
|
|
||||||
Log.d("NativePreviewer", "Trying to use preview size of "
|
|
||||||
+ preview_width + " " + preview_height);
|
|
||||||
|
|
||||||
processor = new NativeProcessor();
|
|
||||||
|
|
||||||
setZOrderMediaOverlay(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @param preview_width
|
|
||||||
* the desired camera preview width - will attempt to get as
|
|
||||||
* close to this as possible
|
|
||||||
* @param preview_height
|
|
||||||
* the desired camera preview height
|
|
||||||
*/
|
|
||||||
public NativePreviewer(Context context, int preview_width,
|
|
||||||
int preview_height) {
|
|
||||||
super(context);
|
|
||||||
|
|
||||||
listAllCameraMethods();
|
|
||||||
// Install a SurfaceHolder.Callback so we get notified when the
|
|
||||||
// underlying surface is created and destroyed.
|
|
||||||
mHolder = getHolder();
|
|
||||||
mHolder.addCallback(this);
|
|
||||||
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
|
||||||
|
|
||||||
this.preview_width = preview_width;
|
|
||||||
this.preview_height = preview_height;
|
|
||||||
|
|
||||||
processor = new NativeProcessor();
|
|
||||||
setZOrderMediaOverlay(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only call in the oncreate function of the instantiating activity
|
|
||||||
*
|
|
||||||
* @param width
|
|
||||||
* desired width
|
|
||||||
* @param height
|
|
||||||
* desired height
|
|
||||||
*/
|
|
||||||
public void setPreviewSize(int width, int height){
|
|
||||||
preview_width = width;
|
|
||||||
preview_height = height;
|
|
||||||
|
|
||||||
Log.d("NativePreviewer", "Trying to use preview size of "
|
|
||||||
+ preview_width + " " + preview_height);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParamsFromPrefs(Context ctx){
|
|
||||||
int size[] ={0,0};
|
|
||||||
CameraConfig.readImageSize(ctx, size);
|
|
||||||
int mode = CameraConfig.readCameraMode(ctx);
|
|
||||||
setPreviewSize(size[0], size[1]);
|
|
||||||
setGrayscale(mode == CameraConfig.CAMERA_MODE_BW ? true : false);
|
|
||||||
whitebalance_mode = CameraConfig.readWhitebalace(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void surfaceCreated(SurfaceHolder holder) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
|
||||||
releaseCamera();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
initCamera(mHolder);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that the size is known, set up the camera parameters and begin
|
|
||||||
// the preview.
|
|
||||||
|
|
||||||
Camera.Parameters parameters = mCamera.getParameters();
|
|
||||||
List<Camera.Size> pvsizes = mCamera.getParameters()
|
|
||||||
.getSupportedPreviewSizes();
|
|
||||||
int best_width = 1000000;
|
|
||||||
int best_height = 1000000;
|
|
||||||
int bdist = 100000;
|
|
||||||
for (Size x : pvsizes) {
|
|
||||||
if (Math.abs(x.width - preview_width) < bdist) {
|
|
||||||
bdist = Math.abs(x.width - preview_width);
|
|
||||||
best_width = x.width;
|
|
||||||
best_height = x.height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
preview_width = best_width;
|
|
||||||
preview_height = best_height;
|
|
||||||
|
|
||||||
Log.d("NativePreviewer", "Determined compatible preview size is: ("
|
|
||||||
+ preview_width + "," + preview_height + ")");
|
|
||||||
|
|
||||||
Log.d("NativePreviewer", "Supported params: "
|
|
||||||
+ mCamera.getParameters().flatten());
|
|
||||||
|
|
||||||
List<String> whiteBalanceModes = parameters.getSupportedWhiteBalance();
|
|
||||||
if (whiteBalanceModes != null
|
|
||||||
&& whiteBalanceModes.contains(whitebalance_mode) ) {
|
|
||||||
parameters.setWhiteBalance(whitebalance_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameters.get("meter-mode") != null)
|
|
||||||
parameters.set("meter-mode", "meter-average");
|
|
||||||
|
|
||||||
List<String> fmodes = mCamera.getParameters().getSupportedFocusModes();
|
|
||||||
if(fmodes != null)
|
|
||||||
{
|
|
||||||
int idx = fmodes.indexOf(Camera.Parameters.FOCUS_MODE_INFINITY);
|
|
||||||
if (idx != -1) {
|
|
||||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
|
|
||||||
} else if (fmodes.indexOf(Camera.Parameters.FOCUS_MODE_FIXED) != -1) {
|
|
||||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fmodes.indexOf(Camera.Parameters.FOCUS_MODE_AUTO) != -1) {
|
|
||||||
hasAutoFocus = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> scenemodes = mCamera.getParameters()
|
|
||||||
.getSupportedSceneModes();
|
|
||||||
if (scenemodes != null)
|
|
||||||
if (scenemodes.indexOf(Camera.Parameters.SCENE_MODE_ACTION) != -1) {
|
|
||||||
parameters.setSceneMode(Camera.Parameters.SCENE_MODE_ACTION);
|
|
||||||
Log.d("NativePreviewer", "set scenemode to action");
|
|
||||||
}
|
|
||||||
|
|
||||||
parameters.setPreviewSize(preview_width, preview_height);
|
|
||||||
|
|
||||||
mCamera.setParameters(parameters);
|
|
||||||
|
|
||||||
pixelinfo = new PixelFormat();
|
|
||||||
pixelformat = mCamera.getParameters().getPreviewFormat();
|
|
||||||
PixelFormat.getPixelFormatInfo(pixelformat, pixelinfo);
|
|
||||||
|
|
||||||
Size preview_size = mCamera.getParameters().getPreviewSize();
|
|
||||||
preview_width = preview_size.width;
|
|
||||||
preview_height = preview_size.height;
|
|
||||||
int bufSize = preview_width * preview_height * pixelinfo.bitsPerPixel
|
|
||||||
/ 8;
|
|
||||||
|
|
||||||
// Must call this before calling addCallbackBuffer to get all the
|
|
||||||
// reflection variables setup
|
|
||||||
initForACB();
|
|
||||||
initForPCWB();
|
|
||||||
|
|
||||||
// Use only one buffer, so that we don't preview too many frames and bog
|
|
||||||
// down system
|
|
||||||
byte[] buffer = new byte[bufSize];
|
|
||||||
addCallbackBuffer(buffer);
|
|
||||||
setPreviewCallbackWithBuffer();
|
|
||||||
|
|
||||||
mCamera.startPreview();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void postautofocus(int delay) {
|
|
||||||
if (hasAutoFocus)
|
|
||||||
handler.postDelayed(autofocusrunner, delay);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Demonstration of how to use onPreviewFrame. In this case I'm not
|
|
||||||
* processing the data, I'm just adding the buffer back to the buffer queue
|
|
||||||
* for re-use
|
|
||||||
*/
|
|
||||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
|
||||||
|
|
||||||
if (start == null) {
|
|
||||||
start = new Date();
|
|
||||||
}
|
|
||||||
|
|
||||||
processor.post(data, preview_width, preview_height, pixelformat,
|
|
||||||
System.nanoTime(), this);
|
|
||||||
|
|
||||||
fcount++;
|
|
||||||
if (fcount % 100 == 0) {
|
|
||||||
double ms = (new Date()).getTime() - start.getTime();
|
|
||||||
Log.i("NativePreviewer", "fps:" + fcount / (ms / 1000.0));
|
|
||||||
start = new Date();
|
|
||||||
fcount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDoneNativeProcessing(byte[] buffer) {
|
|
||||||
addCallbackBuffer(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addCallbackStack(LinkedList<PoolCallback> callbackstack) {
|
|
||||||
processor.addCallbackStack(callbackstack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This must be called when the activity pauses, in Activity.onPause This
|
|
||||||
* has the side effect of clearing the callback stack.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void onPause() {
|
|
||||||
|
|
||||||
releaseCamera();
|
|
||||||
|
|
||||||
addCallbackStack(null);
|
|
||||||
|
|
||||||
processor.stop();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResume() {
|
|
||||||
|
|
||||||
processor.start();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Method mPCWB;
|
|
||||||
|
|
||||||
private void initForPCWB() {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
mPCWB = Class.forName("android.hardware.Camera").getMethod(
|
|
||||||
"setPreviewCallbackWithBuffer", PreviewCallback.class);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e("NativePreviewer",
|
|
||||||
"Problem setting up for setPreviewCallbackWithBuffer: "
|
|
||||||
+ e.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method allows you to add a byte buffer to the queue of buffers to be
|
|
||||||
* used by preview. See:
|
|
||||||
* http://android.git.kernel.org/?p=platform/frameworks
|
|
||||||
* /base.git;a=blob;f=core/java/android/hardware/Camera.java;hb=9d
|
|
||||||
* b3d07b9620b4269ab33f78604a36327e536ce1
|
|
||||||
*
|
|
||||||
* @param b
|
|
||||||
* The buffer to register. Size should be width * height *
|
|
||||||
* bitsPerPixel / 8.
|
|
||||||
*/
|
|
||||||
private void addCallbackBuffer(byte[] b) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
mAcb.invoke(mCamera, b);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e("NativePreviewer",
|
|
||||||
"invoking addCallbackBuffer failed: " + e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this method instead of setPreviewCallback if you want to use manually
|
|
||||||
* allocated buffers. Assumes that "this" implements Camera.PreviewCallback
|
|
||||||
*/
|
|
||||||
private void setPreviewCallbackWithBuffer() {
|
|
||||||
// mCamera.setPreviewCallback(this);
|
|
||||||
// return;
|
|
||||||
try {
|
|
||||||
|
|
||||||
// If we were able to find the setPreviewCallbackWithBuffer method
|
|
||||||
// of Camera,
|
|
||||||
// we can now invoke it on our Camera instance, setting 'this' to be
|
|
||||||
// the
|
|
||||||
// callback handler
|
|
||||||
mPCWB.invoke(mCamera, this);
|
|
||||||
|
|
||||||
// Log.d("NativePrevier","setPreviewCallbackWithBuffer: Called method");
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
Log.e("NativePreviewer", e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private void clearPreviewCallbackWithBuffer() {
|
|
||||||
// mCamera.setPreviewCallback(this);
|
|
||||||
// return;
|
|
||||||
try {
|
|
||||||
|
|
||||||
// If we were able to find the setPreviewCallbackWithBuffer method
|
|
||||||
// of Camera,
|
|
||||||
// we can now invoke it on our Camera instance, setting 'this' to be
|
|
||||||
// the
|
|
||||||
// callback handler
|
|
||||||
mPCWB.invoke(mCamera, (PreviewCallback) null);
|
|
||||||
|
|
||||||
// Log.d("NativePrevier","setPreviewCallbackWithBuffer: cleared");
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
Log.e("NativePreviewer", e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These variables are re-used over and over by addCallbackBuffer
|
|
||||||
*/
|
|
||||||
private Method mAcb;
|
|
||||||
|
|
||||||
private void initForACB() {
|
|
||||||
try {
|
|
||||||
|
|
||||||
mAcb = Class.forName("android.hardware.Camera").getMethod(
|
|
||||||
"addCallbackBuffer", byte[].class);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e("NativePreviewer",
|
|
||||||
"Problem setting up for addCallbackBuffer: " + e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Runnable autofocusrunner = new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mCamera.autoFocus(autocallback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private Camera.AutoFocusCallback autocallback = new Camera.AutoFocusCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAutoFocus(boolean success, Camera camera) {
|
|
||||||
if (!success)
|
|
||||||
postautofocus(1000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will list all methods of the android.hardware.Camera class,
|
|
||||||
* even the hidden ones. With the information it provides, you can use the
|
|
||||||
* same approach I took below to expose methods that were written but hidden
|
|
||||||
* in eclair
|
|
||||||
*/
|
|
||||||
private void listAllCameraMethods() {
|
|
||||||
try {
|
|
||||||
Class<?> c = Class.forName("android.hardware.Camera");
|
|
||||||
Method[] m = c.getMethods();
|
|
||||||
for (int i = 0; i < m.length; i++) {
|
|
||||||
Log.d("NativePreviewer", " method:" + m[i].toString());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
Log.e("NativePreviewer", e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initCamera(SurfaceHolder holder) throws InterruptedException {
|
|
||||||
if (mCamera == null) {
|
|
||||||
// The Surface has been created, acquire the camera and tell it
|
|
||||||
// where
|
|
||||||
// to draw.
|
|
||||||
int i = 0;
|
|
||||||
while (i++ < 5) {
|
|
||||||
try {
|
|
||||||
mCamera = Camera.open();
|
|
||||||
break;
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
Thread.sleep(200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
mCamera.setPreviewDisplay(holder);
|
|
||||||
} catch (IOException exception) {
|
|
||||||
mCamera.release();
|
|
||||||
mCamera = null;
|
|
||||||
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
Log.e("camera", "stacktrace", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void releaseCamera() {
|
|
||||||
if (mCamera != null) {
|
|
||||||
// Surface will be destroyed when we return, so stop the preview.
|
|
||||||
// Because the CameraDevice object is not a shared resource, it's
|
|
||||||
// very
|
|
||||||
// important to release it when the activity is paused.
|
|
||||||
mCamera.stopPreview();
|
|
||||||
mCamera.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// processor = null;
|
|
||||||
mCamera = null;
|
|
||||||
mAcb = null;
|
|
||||||
mPCWB = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Handler handler = new Handler();
|
|
||||||
|
|
||||||
private Date start;
|
|
||||||
private int fcount = 0;
|
|
||||||
private boolean hasAutoFocus = false;
|
|
||||||
private SurfaceHolder mHolder;
|
|
||||||
private Camera mCamera;
|
|
||||||
|
|
||||||
private NativeProcessor processor;
|
|
||||||
|
|
||||||
private int preview_width, preview_height;
|
|
||||||
private int pixelformat;
|
|
||||||
private PixelFormat pixelinfo;
|
|
||||||
|
|
||||||
public void setGrayscale(boolean b) {
|
|
||||||
processor.setGrayscale(b);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,285 +0,0 @@
|
|||||||
package com.opencv.camera;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.locks.Lock;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.opencv.jni.image_pool;
|
|
||||||
import com.opencv.jni.opencv;
|
|
||||||
|
|
||||||
/** The NativeProcessor is a native processing stack engine.
|
|
||||||
*
|
|
||||||
* What this means is that the NativeProcessor handles loading
|
|
||||||
* live camera frames into native memory space, i.e. the image_pool
|
|
||||||
* and then calling a stack of PoolCallback's and passing them the
|
|
||||||
* image_pool.
|
|
||||||
*
|
|
||||||
* The image_pool index 0 is populated with the live video image
|
|
||||||
*
|
|
||||||
* And any modifications to this the pool are in place, so you may
|
|
||||||
* pass on changes to the pool to the next PoolCallback in the stack.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class NativeProcessor {
|
|
||||||
/** Users that would like to be able to have access to live video frames
|
|
||||||
* should implement a PoolCallback
|
|
||||||
* the idx and pool contain the images, specifically at idx == 0 is the
|
|
||||||
* live video frame.
|
|
||||||
*/
|
|
||||||
static public interface PoolCallback {
|
|
||||||
void process(int idx, image_pool pool, long timestamp,
|
|
||||||
NativeProcessor nativeProcessor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**At every frame, each PoolCallback is called in order and is passed the
|
|
||||||
* the same pool and index
|
|
||||||
*
|
|
||||||
* @param stack A list of PoolCallback objects, that will be called in order
|
|
||||||
*/
|
|
||||||
public void addCallbackStack(LinkedList<PoolCallback> stack) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
while (!stacklock.tryLock(10, TimeUnit.MILLISECONDS)) {
|
|
||||||
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
nextStack = stack;
|
|
||||||
} finally {
|
|
||||||
stacklock.unlock();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a NativeProcessor. The processor will not start running until
|
|
||||||
* start is called, at which point it will operate in its own thread and
|
|
||||||
* sleep until a post is called. The processor should not be started until
|
|
||||||
* an onSurfaceChange event, and should be shut down when the surface is
|
|
||||||
* destroyed by calling interupt.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public NativeProcessor() {
|
|
||||||
gray_scale_only = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Grayscale only is much faster because the yuv does not get decoded, and grayscale is only one
|
|
||||||
* byter per pixel - giving fast opengl texture loading.
|
|
||||||
*
|
|
||||||
* You still have access to the whole yuv image, but grayscale is only immediately available to
|
|
||||||
* use without further effort.
|
|
||||||
*
|
|
||||||
* Suggestion - use grayscale only and save your yuv images to disk if you would like color images
|
|
||||||
*
|
|
||||||
* Also, in grayscale mode, the images in the pool are only single channel, so please keep this in mind
|
|
||||||
* when accessing the color images - check the cv::Mat::channels() or cv::Mat::type() if your messing
|
|
||||||
* with color channels
|
|
||||||
*
|
|
||||||
* @param grayscale true if you want to only process grayscale images
|
|
||||||
*/
|
|
||||||
public void setGrayscale(boolean grayscale){
|
|
||||||
gray_scale_only = grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A callback that allows the NativeProcessor to pass back the buffer when
|
|
||||||
* it has completed processing a frame.
|
|
||||||
*/
|
|
||||||
static protected interface NativeProcessorCallback {
|
|
||||||
/**
|
|
||||||
* Called after processing, meant to be recieved by the NativePreviewer
|
|
||||||
* wich reuses the byte buffer for the camera preview...
|
|
||||||
*
|
|
||||||
* @param buffer
|
|
||||||
* the buffer passed to the NativeProcessor with post.
|
|
||||||
*/
|
|
||||||
void onDoneNativeProcessing(byte[] buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void stop() {
|
|
||||||
mthread.interrupt();
|
|
||||||
try {
|
|
||||||
mthread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Log.w("NativeProcessor",
|
|
||||||
"interupted while stoping " + e.getMessage());
|
|
||||||
}
|
|
||||||
mthread = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void start() {
|
|
||||||
mthread = new ProcessorThread();
|
|
||||||
mthread.start();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* post is used to notify the processor that a preview frame is ready, this
|
|
||||||
* will return almost immediately. if the processor is busy, returns false
|
|
||||||
* and is essentially a nop.
|
|
||||||
*
|
|
||||||
* @param buffer
|
|
||||||
* a preview frame from the Android Camera onPreviewFrame
|
|
||||||
* callback
|
|
||||||
* @param width
|
|
||||||
* of preview frame
|
|
||||||
* @param height
|
|
||||||
* of preview frame
|
|
||||||
* @param format
|
|
||||||
* of preview frame
|
|
||||||
* @return true if the processor wasn't busy and accepted the post, false if
|
|
||||||
* the processor is still processing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
protected boolean post(byte[] buffer, int width, int height, int format,
|
|
||||||
long timestamp, NativeProcessorCallback callback) {
|
|
||||||
|
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
NPPostObject pobj = new NPPostObject(buffer, width, height, format,
|
|
||||||
timestamp, callback);
|
|
||||||
postobjects.addFirst(pobj);
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ProcessorThread extends Thread {
|
|
||||||
|
|
||||||
private void process(NPPostObject pobj) throws Exception {
|
|
||||||
|
|
||||||
if (pobj.format == PixelFormat.YCbCr_420_SP) {
|
|
||||||
// add as color image, because we know how to decode this
|
|
||||||
opencv.addYUVtoPool(pool, pobj.buffer, 0, pobj.width,
|
|
||||||
pobj.height, gray_scale_only);
|
|
||||||
|
|
||||||
} else if (pobj.format == PixelFormat.YCbCr_422_SP) {
|
|
||||||
// add as gray image, because this format is not coded
|
|
||||||
// for...//TODO figure out how to decode this
|
|
||||||
// format
|
|
||||||
opencv.addYUVtoPool(pool, pobj.buffer, 0, pobj.width,
|
|
||||||
pobj.height, true);
|
|
||||||
} else
|
|
||||||
throw new Exception("bad pixel format!");
|
|
||||||
|
|
||||||
for (PoolCallback x : stack) {
|
|
||||||
if (interrupted()) {
|
|
||||||
throw new InterruptedException(
|
|
||||||
"Native Processor interupted while processing");
|
|
||||||
}
|
|
||||||
x.process(0, pool, pobj.timestamp, NativeProcessor.this);
|
|
||||||
}
|
|
||||||
|
|
||||||
pobj.done(); // tell the postobject that we're done doing
|
|
||||||
// all the processing.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
try {
|
|
||||||
while (true) {
|
|
||||||
yield();
|
|
||||||
|
|
||||||
while (!stacklock.tryLock(5, TimeUnit.MILLISECONDS)) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (nextStack != null) {
|
|
||||||
stack = nextStack;
|
|
||||||
nextStack = null;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stacklock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
NPPostObject pobj = null;
|
|
||||||
|
|
||||||
while (!lock.tryLock(5, TimeUnit.MILLISECONDS)) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (postobjects.isEmpty())
|
|
||||||
continue;
|
|
||||||
pobj = postobjects.removeLast();
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (interrupted())
|
|
||||||
throw new InterruptedException();
|
|
||||||
|
|
||||||
if (stack != null && pobj != null)
|
|
||||||
process(pobj);
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
|
|
||||||
Log.i("NativeProcessor",
|
|
||||||
"native processor interupted, ending now");
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static private class NPPostObject {
|
|
||||||
public NPPostObject(byte[] buffer, int width, int height, int format,
|
|
||||||
long timestamp, NativeProcessorCallback callback) {
|
|
||||||
this.buffer = buffer;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.format = format;
|
|
||||||
this.timestamp = timestamp;
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void done() {
|
|
||||||
callback.onDoneNativeProcessing(buffer);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int width, height;
|
|
||||||
byte[] buffer;
|
|
||||||
int format;
|
|
||||||
long timestamp;
|
|
||||||
NativeProcessorCallback callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private LinkedList<NPPostObject> postobjects = new LinkedList<NPPostObject>();
|
|
||||||
|
|
||||||
private image_pool pool = new image_pool();
|
|
||||||
|
|
||||||
private final Lock lock = new ReentrantLock();
|
|
||||||
|
|
||||||
private LinkedList<PoolCallback> stack = new LinkedList<PoolCallback>();
|
|
||||||
private boolean gray_scale_only;
|
|
||||||
|
|
||||||
private Lock stacklock = new ReentrantLock();
|
|
||||||
|
|
||||||
private LinkedList<PoolCallback> nextStack;
|
|
||||||
|
|
||||||
private ProcessorThread mthread;
|
|
||||||
|
|
||||||
}
|
|
@ -1,411 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.opencv.opengl;
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2008 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGL10;
|
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
|
||||||
import javax.microedition.khronos.egl.EGLContext;
|
|
||||||
import javax.microedition.khronos.egl.EGLDisplay;
|
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
|
||||||
|
|
||||||
import com.opencv.camera.NativeProcessor;
|
|
||||||
import com.opencv.camera.NativeProcessor.PoolCallback;
|
|
||||||
import com.opencv.jni.glcamera;
|
|
||||||
import com.opencv.jni.image_pool;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.opengl.GLSurfaceView;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple GLSurfaceView sub-class that demonstrate how to perform
|
|
||||||
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
|
|
||||||
* details:
|
|
||||||
*
|
|
||||||
* - The class must use a custom context factory to enable 2.0 rendering.
|
|
||||||
* See ContextFactory class definition below.
|
|
||||||
*
|
|
||||||
* - The class must use a custom EGLConfigChooser to be able to select
|
|
||||||
* an EGLConfig that supports 2.0. This is done by providing a config
|
|
||||||
* specification to eglChooseConfig() that has the attribute
|
|
||||||
* EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES2_BIT flag
|
|
||||||
* set. See ConfigChooser class definition below.
|
|
||||||
*
|
|
||||||
* - The class must select the surface's format, then choose an EGLConfig
|
|
||||||
* that matches it exactly (with regards to red/green/blue/alpha channels
|
|
||||||
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
|
|
||||||
*/
|
|
||||||
public class GL2CameraViewer extends GLSurfaceView{
|
|
||||||
private static String TAG = "GL2JNIView";
|
|
||||||
private static final boolean DEBUG = false;
|
|
||||||
|
|
||||||
private PoolCallback poolcallback = new PoolCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(int idx, image_pool pool, long timestamp,
|
|
||||||
NativeProcessor nativeProcessor){
|
|
||||||
|
|
||||||
|
|
||||||
drawMatToGL(idx, pool);
|
|
||||||
|
|
||||||
requestRender();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public GL2CameraViewer(Context context,AttributeSet attributeSet) {
|
|
||||||
super(context,attributeSet);
|
|
||||||
|
|
||||||
init(false, 0, 0);
|
|
||||||
setZOrderMediaOverlay(true);
|
|
||||||
}
|
|
||||||
public GL2CameraViewer(Context context) {
|
|
||||||
super(context);
|
|
||||||
init(false, 0, 0);
|
|
||||||
setZOrderMediaOverlay(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GL2CameraViewer(Context context, boolean translucent, int depth, int stencil) {
|
|
||||||
super(context);
|
|
||||||
init(translucent, depth, stencil);
|
|
||||||
setZOrderMediaOverlay(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(boolean translucent, int depth, int stencil) {
|
|
||||||
|
|
||||||
|
|
||||||
/* By default, GLSurfaceView() creates a RGB_565 opaque surface.
|
|
||||||
* If we want a translucent one, we should change the surface's
|
|
||||||
* format here, using PixelFormat.TRANSLUCENT for GL Surfaces
|
|
||||||
* is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
|
|
||||||
*/
|
|
||||||
if (translucent) {
|
|
||||||
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup the context factory for 2.0 rendering.
|
|
||||||
* See ContextFactory class definition below
|
|
||||||
*/
|
|
||||||
setEGLContextFactory(new ContextFactory());
|
|
||||||
|
|
||||||
/* We need to choose an EGLConfig that matches the format of
|
|
||||||
* our surface exactly. This is going to be done in our
|
|
||||||
* custom config chooser. See ConfigChooser class definition
|
|
||||||
* below.
|
|
||||||
*/
|
|
||||||
setEGLConfigChooser( translucent ?
|
|
||||||
new ConfigChooser(8, 8, 8, 8, depth, stencil) :
|
|
||||||
new ConfigChooser(5, 6, 5, 0, depth, stencil) );
|
|
||||||
|
|
||||||
/* Set the renderer responsible for frame rendering */
|
|
||||||
setRenderer(new Renderer());
|
|
||||||
setRenderMode(RENDERMODE_WHEN_DIRTY);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
|
|
||||||
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
|
||||||
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
|
|
||||||
Log.w(TAG, "creating OpenGL ES 2.0 context");
|
|
||||||
checkEglError("Before eglCreateContext", egl);
|
|
||||||
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
|
|
||||||
EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
|
|
||||||
checkEglError("After eglCreateContext", egl);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
|
|
||||||
egl.eglDestroyContext(display, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkEglError(String prompt, EGL10 egl) {
|
|
||||||
int error;
|
|
||||||
while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
|
|
||||||
Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
|
|
||||||
|
|
||||||
public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
|
|
||||||
mRedSize = r;
|
|
||||||
mGreenSize = g;
|
|
||||||
mBlueSize = b;
|
|
||||||
mAlphaSize = a;
|
|
||||||
mDepthSize = depth;
|
|
||||||
mStencilSize = stencil;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This EGL config specification is used to specify 2.0 rendering.
|
|
||||||
* We use a minimum size of 4 bits for red/green/blue, but will
|
|
||||||
* perform actual matching in chooseConfig() below.
|
|
||||||
*/
|
|
||||||
private static int EGL_OPENGL_ES2_BIT = 4;
|
|
||||||
private static int[] s_configAttribs2 =
|
|
||||||
{
|
|
||||||
EGL10.EGL_RED_SIZE, 4,
|
|
||||||
EGL10.EGL_GREEN_SIZE, 4,
|
|
||||||
EGL10.EGL_BLUE_SIZE, 4,
|
|
||||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
|
||||||
EGL10.EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
|
|
||||||
|
|
||||||
/* Get the number of minimally matching EGL configurations
|
|
||||||
*/
|
|
||||||
int[] num_config = new int[1];
|
|
||||||
egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
|
|
||||||
|
|
||||||
int numConfigs = num_config[0];
|
|
||||||
|
|
||||||
if (numConfigs <= 0) {
|
|
||||||
throw new IllegalArgumentException("No configs match configSpec");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate then read the array of minimally matching EGL configs
|
|
||||||
*/
|
|
||||||
EGLConfig[] configs = new EGLConfig[numConfigs];
|
|
||||||
egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
printConfigs(egl, display, configs);
|
|
||||||
}
|
|
||||||
/* Now return the "best" one
|
|
||||||
*/
|
|
||||||
return chooseConfig(egl, display, configs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
|
|
||||||
EGLConfig[] configs) {
|
|
||||||
for(EGLConfig config : configs) {
|
|
||||||
int d = findConfigAttrib(egl, display, config,
|
|
||||||
EGL10.EGL_DEPTH_SIZE, 0);
|
|
||||||
int s = findConfigAttrib(egl, display, config,
|
|
||||||
EGL10.EGL_STENCIL_SIZE, 0);
|
|
||||||
|
|
||||||
// We need at least mDepthSize and mStencilSize bits
|
|
||||||
if (d < mDepthSize || s < mStencilSize)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// We want an *exact* match for red/green/blue/alpha
|
|
||||||
int r = findConfigAttrib(egl, display, config,
|
|
||||||
EGL10.EGL_RED_SIZE, 0);
|
|
||||||
int g = findConfigAttrib(egl, display, config,
|
|
||||||
EGL10.EGL_GREEN_SIZE, 0);
|
|
||||||
int b = findConfigAttrib(egl, display, config,
|
|
||||||
EGL10.EGL_BLUE_SIZE, 0);
|
|
||||||
int a = findConfigAttrib(egl, display, config,
|
|
||||||
EGL10.EGL_ALPHA_SIZE, 0);
|
|
||||||
|
|
||||||
if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
|
|
||||||
EGLConfig config, int attribute, int defaultValue) {
|
|
||||||
|
|
||||||
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
|
|
||||||
return mValue[0];
|
|
||||||
}
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void printConfigs(EGL10 egl, EGLDisplay display,
|
|
||||||
EGLConfig[] configs) {
|
|
||||||
int numConfigs = configs.length;
|
|
||||||
Log.w(TAG, String.format("%d configurations", numConfigs));
|
|
||||||
for (int i = 0; i < numConfigs; i++) {
|
|
||||||
Log.w(TAG, String.format("Configuration %d:\n", i));
|
|
||||||
printConfig(egl, display, configs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void printConfig(EGL10 egl, EGLDisplay display,
|
|
||||||
EGLConfig config) {
|
|
||||||
int[] attributes = {
|
|
||||||
EGL10.EGL_BUFFER_SIZE,
|
|
||||||
EGL10.EGL_ALPHA_SIZE,
|
|
||||||
EGL10.EGL_BLUE_SIZE,
|
|
||||||
EGL10.EGL_GREEN_SIZE,
|
|
||||||
EGL10.EGL_RED_SIZE,
|
|
||||||
EGL10.EGL_DEPTH_SIZE,
|
|
||||||
EGL10.EGL_STENCIL_SIZE,
|
|
||||||
EGL10.EGL_CONFIG_CAVEAT,
|
|
||||||
EGL10.EGL_CONFIG_ID,
|
|
||||||
EGL10.EGL_LEVEL,
|
|
||||||
EGL10.EGL_MAX_PBUFFER_HEIGHT,
|
|
||||||
EGL10.EGL_MAX_PBUFFER_PIXELS,
|
|
||||||
EGL10.EGL_MAX_PBUFFER_WIDTH,
|
|
||||||
EGL10.EGL_NATIVE_RENDERABLE,
|
|
||||||
EGL10.EGL_NATIVE_VISUAL_ID,
|
|
||||||
EGL10.EGL_NATIVE_VISUAL_TYPE,
|
|
||||||
0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
|
|
||||||
EGL10.EGL_SAMPLES,
|
|
||||||
EGL10.EGL_SAMPLE_BUFFERS,
|
|
||||||
EGL10.EGL_SURFACE_TYPE,
|
|
||||||
EGL10.EGL_TRANSPARENT_TYPE,
|
|
||||||
EGL10.EGL_TRANSPARENT_RED_VALUE,
|
|
||||||
EGL10.EGL_TRANSPARENT_GREEN_VALUE,
|
|
||||||
EGL10.EGL_TRANSPARENT_BLUE_VALUE,
|
|
||||||
0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
|
|
||||||
0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
|
|
||||||
0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
|
|
||||||
0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
|
|
||||||
EGL10.EGL_LUMINANCE_SIZE,
|
|
||||||
EGL10.EGL_ALPHA_MASK_SIZE,
|
|
||||||
EGL10.EGL_COLOR_BUFFER_TYPE,
|
|
||||||
EGL10.EGL_RENDERABLE_TYPE,
|
|
||||||
0x3042 // EGL10.EGL_CONFORMANT
|
|
||||||
};
|
|
||||||
String[] names = {
|
|
||||||
"EGL_BUFFER_SIZE",
|
|
||||||
"EGL_ALPHA_SIZE",
|
|
||||||
"EGL_BLUE_SIZE",
|
|
||||||
"EGL_GREEN_SIZE",
|
|
||||||
"EGL_RED_SIZE",
|
|
||||||
"EGL_DEPTH_SIZE",
|
|
||||||
"EGL_STENCIL_SIZE",
|
|
||||||
"EGL_CONFIG_CAVEAT",
|
|
||||||
"EGL_CONFIG_ID",
|
|
||||||
"EGL_LEVEL",
|
|
||||||
"EGL_MAX_PBUFFER_HEIGHT",
|
|
||||||
"EGL_MAX_PBUFFER_PIXELS",
|
|
||||||
"EGL_MAX_PBUFFER_WIDTH",
|
|
||||||
"EGL_NATIVE_RENDERABLE",
|
|
||||||
"EGL_NATIVE_VISUAL_ID",
|
|
||||||
"EGL_NATIVE_VISUAL_TYPE",
|
|
||||||
"EGL_PRESERVED_RESOURCES",
|
|
||||||
"EGL_SAMPLES",
|
|
||||||
"EGL_SAMPLE_BUFFERS",
|
|
||||||
"EGL_SURFACE_TYPE",
|
|
||||||
"EGL_TRANSPARENT_TYPE",
|
|
||||||
"EGL_TRANSPARENT_RED_VALUE",
|
|
||||||
"EGL_TRANSPARENT_GREEN_VALUE",
|
|
||||||
"EGL_TRANSPARENT_BLUE_VALUE",
|
|
||||||
"EGL_BIND_TO_TEXTURE_RGB",
|
|
||||||
"EGL_BIND_TO_TEXTURE_RGBA",
|
|
||||||
"EGL_MIN_SWAP_INTERVAL",
|
|
||||||
"EGL_MAX_SWAP_INTERVAL",
|
|
||||||
"EGL_LUMINANCE_SIZE",
|
|
||||||
"EGL_ALPHA_MASK_SIZE",
|
|
||||||
"EGL_COLOR_BUFFER_TYPE",
|
|
||||||
"EGL_RENDERABLE_TYPE",
|
|
||||||
"EGL_CONFORMANT"
|
|
||||||
};
|
|
||||||
int[] value = new int[1];
|
|
||||||
for (int i = 0; i < attributes.length; i++) {
|
|
||||||
int attribute = attributes[i];
|
|
||||||
String name = names[i];
|
|
||||||
if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
|
|
||||||
Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
|
|
||||||
} else {
|
|
||||||
// Log.w(TAG, String.format(" %s: failed\n", name));
|
|
||||||
while (egl.eglGetError() != EGL10.EGL_SUCCESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subclasses can adjust these values:
|
|
||||||
protected int mRedSize;
|
|
||||||
protected int mGreenSize;
|
|
||||||
protected int mBlueSize;
|
|
||||||
protected int mAlphaSize;
|
|
||||||
protected int mDepthSize;
|
|
||||||
protected int mStencilSize;
|
|
||||||
private int[] mValue = new int[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
glcamera mglcamera;
|
|
||||||
public void drawMatToGL(int idx, image_pool pool){
|
|
||||||
if(mglcamera != null)
|
|
||||||
mglcamera.drawMatToGL(idx, pool);
|
|
||||||
else
|
|
||||||
Log.e("android-opencv", "null glcamera!!!!");
|
|
||||||
}
|
|
||||||
public void clear(){
|
|
||||||
if(mglcamera != null)
|
|
||||||
mglcamera.clear();
|
|
||||||
else
|
|
||||||
Log.e("android-opencv", "null glcamera!!!!");
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Renderer implements GLSurfaceView.Renderer {
|
|
||||||
|
|
||||||
public void onDrawFrame(GL10 gl) {
|
|
||||||
|
|
||||||
mglcamera.step();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
|
||||||
|
|
||||||
mglcamera.init(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
mglcamera = null;
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
super.onPause();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
mglcamera = new glcamera();
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
super.onResume();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public PoolCallback getDrawCallback() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return poolcallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package com.opencv.utils;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.opencv.jni.Mat;
|
|
||||||
import com.opencv.jni.Size;
|
|
||||||
import com.opencv.jni.opencv;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Bitmap.Config;
|
|
||||||
|
|
||||||
public class BitmapBridge {
|
|
||||||
static void copyBitmap(Bitmap bmap, Mat mat) throws Exception {
|
|
||||||
if ((bmap.getConfig() == null) || bmap.getConfig() == Config.ARGB_8888)
|
|
||||||
throw new Exception("bad config");
|
|
||||||
Size sz = new Size(bmap.getWidth(), bmap.getHeight());
|
|
||||||
mat.create(sz, opencv.CV_8UC4);
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(4 * bmap.getWidth()
|
|
||||||
* bmap.getHeight());
|
|
||||||
bmap.copyPixelsToBuffer(buffer);
|
|
||||||
opencv.copyBufferToMat(mat, buffer);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bitmap matToBitmap(Mat mat) {
|
|
||||||
Bitmap bmap = Bitmap.createBitmap(mat.getCols(), mat.getRows(),
|
|
||||||
Config.ARGB_8888);
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(4 * bmap.getWidth()
|
|
||||||
* bmap.getHeight());
|
|
||||||
opencv.copyMatToBuffer(buffer, mat);
|
|
||||||
bmap.copyPixelsFromBuffer(buffer);
|
|
||||||
return bmap;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
<?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>
|
|
||||||
|
|
||||||
<activity android:name="com.opencv.camera.CameraConfig" android:label="@string/app_name"
|
|
||||||
android:screenOrientation="landscape"
|
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard">
|
|
||||||
</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>
|
|
@ -1,5 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
|
||||||
|
|
||||||
project(CVCamera)
|
|
||||||
|
|
||||||
add_subdirectory(jni)
|
|
@ -1,2 +0,0 @@
|
|||||||
see http://code.google.com/p/android-opencv/wiki/CVCamera
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
# 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-opencv
|
|
||||||
# Project target.
|
|
||||||
target=android-7
|
|
@ -1,62 +0,0 @@
|
|||||||
#########################################################
|
|
||||||
# Find opencv and android-opencv
|
|
||||||
#########################################################
|
|
||||||
|
|
||||||
set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../../build
|
|
||||||
CACHE PATH "The path where you built opencv for android")
|
|
||||||
set(AndroidOpenCV_DIR ${CMAKE_SOURCE_DIR}/../../android-opencv/build
|
|
||||||
CACHE PATH "The path where you built android-opencv")
|
|
||||||
|
|
||||||
find_package(OpenCV REQUIRED)
|
|
||||||
FIND_PACKAGE(AndroidOpenCV REQUIRED )
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
#c flags, included, and lib dependencies
|
|
||||||
#########################################################
|
|
||||||
|
|
||||||
#notice the "recycling" of CMAKE_C_FLAGS
|
|
||||||
#this is necessary to pick up android flags
|
|
||||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -fPIC" )
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
|
|
||||||
set( LIBRARY_DEPS ${AndroidOpenCV_LIBS} ${OpenCV_LIBS} )
|
|
||||||
if(ANDROID)
|
|
||||||
set( LIBRARY_DEPS ${LIBRARY_DEPS} log dl)
|
|
||||||
endif(ANDROID)
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
#SWIG STUFF
|
|
||||||
#########################################################
|
|
||||||
#the java package to place swig generated java files in
|
|
||||||
set(MY_PACKAGE com.theveganrobot.cvcamera.jni)
|
|
||||||
|
|
||||||
if(NOT ANDROID)
|
|
||||||
#non android swig and jni
|
|
||||||
#jni is available by default on android
|
|
||||||
find_package(JNI REQUIRED)
|
|
||||||
include_directories(${JNI_INCLUDE_DIRS})
|
|
||||||
FIND_PACKAGE(SWIG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
INCLUDE(${SWIG_USE_FILE}) #on android this is found by the cmake toolchain
|
|
||||||
|
|
||||||
if(ANDROID)
|
|
||||||
#this will set the output path for the java package
|
|
||||||
#and properly create the package declarations in generated java sources
|
|
||||||
SET_SWIG_JAVA_PACKAGE( ${MY_PACKAGE} ) #defined in the android toolchain
|
|
||||||
endif(ANDROID)
|
|
||||||
|
|
||||||
#this add's the swig path for the opencv wrappers
|
|
||||||
SET(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} "-I${AndroidOpenCV_SWIG_DIR}" )
|
|
||||||
|
|
||||||
SET_SOURCE_FILES_PROPERTIES(cvcamera.i PROPERTIES CPLUSPLUS ON)
|
|
||||||
|
|
||||||
#add the swig module, giving it the name, java, and then all of the source files
|
|
||||||
SWIG_ADD_MODULE(cvcamera java
|
|
||||||
cvcamera.i #swig file
|
|
||||||
Processor.cpp #cpp files can be compiled to
|
|
||||||
)
|
|
||||||
|
|
||||||
#link the module like any other
|
|
||||||
target_link_libraries(cvcamera ${LIBRARY_DEPS} )
|
|
@ -1,286 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
Mat img = pool->getImage(input_idx);
|
|
||||||
|
|
||||||
if (img.empty() || 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);
|
|
||||||
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();
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
private:
|
|
||||||
cv::StarFeatureDetector stard;
|
|
||||||
cv::FastFeatureDetector fastd;
|
|
||||||
cv::SurfFeatureDetector surfd;
|
|
||||||
std::vector<cv::KeyPoint> keypoints;
|
|
||||||
std::vector<std::vector<cv::Point2f> > imagepoints;
|
|
||||||
|
|
||||||
cv::Mat K;
|
|
||||||
cv::Mat distortion;
|
|
||||||
cv::Size imgsize;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* PROCESSOR_H_ */
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
};
|
|
@ -1,36 +0,0 @@
|
|||||||
/* 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"
|
|
@ -1,2 +0,0 @@
|
|||||||
android update project --name CVCamera \
|
|
||||||
--path .
|
|
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.8 KiB |
@ -1,8 +0,0 @@
|
|||||||
<?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>
|
|
@ -1,7 +0,0 @@
|
|||||||
<?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>
|
|
@ -1,505 +0,0 @@
|
|||||||
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.Intent;
|
|
||||||
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.ViewGroup.LayoutParams;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.opencv.camera.CameraConfig;
|
|
||||||
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");
|
|
||||||
menu.add("Settings");
|
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (item.getTitle().equals("Settings")) {
|
|
||||||
|
|
||||||
Intent intent = new Intent(this,CameraConfig.class);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
LinearLayout gllay = new LinearLayout(getApplication());
|
|
||||||
|
|
||||||
gllay.setGravity(Gravity.CENTER);
|
|
||||||
gllay.addView(glview, params);
|
|
||||||
frame.addView(gllay);
|
|
||||||
|
|
||||||
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(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();
|
|
||||||
mPreview.setParamsFromPrefs(getApplicationContext());
|
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
echo uninstalling CVCamera from phone
|
|
||||||
adb uninstall com.theveganrobot.cvcamera
|
|
@ -1,46 +0,0 @@
|
|||||||
<?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>
|
|
||||||
<!--
|
|
||||||
These activities are defined in the android-jni library, and just reused here
|
|
||||||
-->
|
|
||||||
<activity android:name="com.opencv.calibration.ChessBoardChooser" android:label="@string/app_name"
|
|
||||||
android:screenOrientation="landscape"
|
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard">
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity android:name="com.opencv.camera.CameraConfig" android:label="@string/app_name"
|
|
||||||
android:screenOrientation="landscape"
|
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard">
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity android:name="com.opencv.calibration.CalibrationViewer" android:label="@string/app_name"/>
|
|
||||||
|
|
||||||
<service android:name="com.opencv.calibration.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>
|
|
@ -1,10 +0,0 @@
|
|||||||
to build completeley from command line:
|
|
||||||
sh project_create.sh
|
|
||||||
ant debug
|
|
||||||
ant install
|
|
||||||
|
|
||||||
That assumes that you have already build the opencv/android/android-jni project
|
|
||||||
|
|
||||||
If you're in eclipse, try to create a new android project from existing sources.
|
|
||||||
Make sure that you also have the android-jni project open in eclipse is this is the case
|
|
||||||
or the android library dependency will give you errors.
|
|
@ -1,12 +0,0 @@
|
|||||||
# 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-opencv/
|
|
||||||
# Project target.
|
|
||||||
target=android-7
|
|
@ -1,2 +0,0 @@
|
|||||||
android update project --name Calibration \
|
|
||||||
--path .
|
|
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 409 B |
@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:opencv="http://schemas.android.com/apk/res/com.opencv"
|
|
||||||
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>
|
|
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/calibrate" android:titleCondensed="Calib"
|
|
||||||
android:title="Calibrate"></item>
|
|
||||||
<item android:id="@+id/patternsize" android:titleCondensed="Size"
|
|
||||||
android:title="@string/patternsize" android:icon="@drawable/patternicon"></item>
|
|
||||||
|
|
||||||
|
|
||||||
<item android:id="@+id/settings" android:title="Settings" android:icon="@android:drawable/ic_menu_preferences"></item>
|
|
||||||
<item android:id="@+id/help" android:title="Help" android:icon="@android:drawable/ic_menu_help"></item>
|
|
||||||
</menu>
|
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="good_color">#00ff00</color>
|
|
||||||
<color name="bad_color">#FF0000</color>
|
|
||||||
</resources>
|
|
@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<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 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>
|
|
@ -1,325 +0,0 @@
|
|||||||
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.CameraConfig;
|
|
||||||
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;
|
|
||||||
case R.id.settings:
|
|
||||||
Intent configurer = new Intent(getApplicationContext(),
|
|
||||||
CameraConfig.class);
|
|
||||||
startActivity(configurer);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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(Calibration.class, R.drawable.icon,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.calib_camera);
|
|
||||||
mPreview = (NativePreviewer) findViewById(R.id.nativepreviewer);
|
|
||||||
mPreview.setPreviewSize(800, 400);
|
|
||||||
mPreview.setGrayscale(true);
|
|
||||||
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();
|
|
||||||
int size[] ={0,0};
|
|
||||||
CameraConfig.readImageSize(getApplicationContext(), size);
|
|
||||||
int mode = CameraConfig.readCameraMode(getApplicationContext());
|
|
||||||
mPreview.setPreviewSize(size[0], size[1]);
|
|
||||||
mPreview.setGrayscale(mode == CameraConfig.CAMERA_MODE_BW ? true : false);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="com.OpenCV_SAMPLE" android:versionCode="1"
|
|
||||||
android:versionName="1.0">
|
|
||||||
<application android:label="@string/app_name"
|
|
||||||
android:debuggable="true" android:icon="@drawable/icon">
|
|
||||||
<activity android:name=".OpenCV_SAMPLE" android:label="@string/app_name"
|
|
||||||
android:screenOrientation="landscape" android:configChanges="orientation|keyboardHidden|keyboard">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<!-- These activities are defined in the android-opencv library, and just
|
|
||||||
reused here -->
|
|
||||||
<activity android:name="com.opencv.camera.CameraConfig"
|
|
||||||
android:label="@string/app_name" android:screenOrientation="landscape"
|
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard">
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="7" />
|
|
||||||
|
|
||||||
<!-- set the opengl version -->
|
|
||||||
<uses-feature android:glEsVersion="0x00020000" />
|
|
||||||
<!-- use the camera -->
|
|
||||||
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
|
|
||||||
|
|
||||||
</manifest>
|
|
@ -1,5 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
|
||||||
|
|
||||||
project(OpenCV_SAMPLE)
|
|
||||||
|
|
||||||
add_subdirectory(jni)
|
|
@ -1,7 +0,0 @@
|
|||||||
@ECHO OFF
|
|
||||||
SETLOCAL
|
|
||||||
PUSHD %~dp0
|
|
||||||
SET PROJECT_NAME=OpenCV_SAMPLE
|
|
||||||
CALL ..\..\scripts\build.cmd %*
|
|
||||||
POPD
|
|
||||||
ENDLOCAL
|
|
@ -1,4 +0,0 @@
|
|||||||
mkdir build_neon
|
|
||||||
cd build_neon
|
|
||||||
cmake -DOpenCV_DIR=../../../build_neon -DAndroidOpenCV_DIR=../../../android-opencv/build_neon -DARM_TARGETS="armeabi-v7a with NEON" -DCMAKE_TOOLCHAIN_FILE=$ANDTOOLCHAIN ..
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
# This file is automatically generated by Android Tools.
|
|
||||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
|
||||||
#
|
|
||||||
# This file must be checked in Version Control Systems.
|
|
||||||
#
|
|
||||||
# To customize properties used by the Ant build system use,
|
|
||||||
# "build.properties", and override values to adapt the script to your
|
|
||||||
# project structure.
|
|
||||||
|
|
||||||
# Project target.
|
|
||||||
target=android-7
|
|
||||||
android.library.reference.1=../../android-opencv/
|
|
@ -1,68 +0,0 @@
|
|||||||
#########################################################
|
|
||||||
# Find opencv and android-opencv
|
|
||||||
#########################################################
|
|
||||||
|
|
||||||
set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../../build
|
|
||||||
CACHE PATH "The path where you built opencv for android")
|
|
||||||
set(AndroidOpenCV_DIR ${CMAKE_SOURCE_DIR}/../../android-opencv/build
|
|
||||||
CACHE PATH "The path where you built android-opencv")
|
|
||||||
|
|
||||||
find_package(OpenCV REQUIRED)
|
|
||||||
FIND_PACKAGE(AndroidOpenCV REQUIRED )
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
#c flags, included, and lib dependencies
|
|
||||||
#########################################################
|
|
||||||
|
|
||||||
#notice the "recycling" of CMAKE_C_FLAGS
|
|
||||||
#this is necessary to pick up android flags
|
|
||||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -fPIC" )
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
|
|
||||||
set( LIBRARY_DEPS ${AndroidOpenCV_LIBS} ${OpenCV_LIBS} )
|
|
||||||
if(ANDROID)
|
|
||||||
set( LIBRARY_DEPS ${LIBRARY_DEPS} log dl)
|
|
||||||
endif(ANDROID)
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
#SWIG STUFF
|
|
||||||
#########################################################
|
|
||||||
#the java package to place swig generated java files in
|
|
||||||
set(MY_PACKAGE com.OpenCV_SAMPLE.jni )
|
|
||||||
set(MY_MODULE OpenCV_SAMPLE )
|
|
||||||
set(MY_SWIG
|
|
||||||
OpenCV_SAMPLE.i #swig file
|
|
||||||
)
|
|
||||||
set(MY_SRCS
|
|
||||||
cvsample.cpp #cpp files can be compiled to
|
|
||||||
)
|
|
||||||
|
|
||||||
if(NOT ANDROID)
|
|
||||||
#non android swig and jni
|
|
||||||
#jni is available by default on android
|
|
||||||
find_package(JNI REQUIRED)
|
|
||||||
include_directories(${JNI_INCLUDE_DIRS})
|
|
||||||
FIND_PACKAGE(SWIG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
INCLUDE(${SWIG_USE_FILE}) #on android this is found by the cmake toolchain
|
|
||||||
|
|
||||||
if(ANDROID)
|
|
||||||
#this will set the output path for the java package
|
|
||||||
#and properly create the package declarations in generated java sources
|
|
||||||
SET_SWIG_JAVA_PACKAGE( ${MY_PACKAGE} ) #defined in the android toolchain
|
|
||||||
endif(ANDROID)
|
|
||||||
|
|
||||||
#this add's the swig path for the opencv wrappers
|
|
||||||
SET(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} "-I${AndroidOpenCV_SWIG_DIR}" )
|
|
||||||
|
|
||||||
SET_SOURCE_FILES_PROPERTIES(${MY_SWIG} PROPERTIES CPLUSPLUS ON)
|
|
||||||
|
|
||||||
#add the swig module, giving it the name, java, and then all of the source files
|
|
||||||
SWIG_ADD_MODULE(${MY_MODULE} java
|
|
||||||
${MY_SWIG}
|
|
||||||
${MY_SRCS}
|
|
||||||
)
|
|
||||||
#link the module like any other
|
|
||||||
target_link_libraries(${MY_MODULE} ${LIBRARY_DEPS} )
|
|
@ -1,48 +0,0 @@
|
|||||||
/* File : foobar.i */
|
|
||||||
%module OpenCV_SAMPLE
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 up our shared libraries
|
|
||||||
System.loadLibrary("android-opencv");
|
|
||||||
System.loadLibrary("OpenCV_SAMPLE");
|
|
||||||
} catch (UnsatisfiedLinkError e) {
|
|
||||||
//badness
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
%}
|
|
||||||
|
|
||||||
//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"
|
|
||||||
|
|
||||||
%{
|
|
||||||
#include "cvsample.h"
|
|
||||||
using cv::Mat;
|
|
||||||
%}
|
|
||||||
|
|
||||||
//make sure to import the image_pool as it is
|
|
||||||
//referenced by the Processor java generated
|
|
||||||
//class
|
|
||||||
%typemap(javaimports) CVSample "
|
|
||||||
import com.opencv.jni.*;// import the opencv java bindings
|
|
||||||
"
|
|
||||||
class CVSample
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void canny(const Mat& input, Mat& output, int edgeThresh);
|
|
||||||
void invert(Mat& inout);
|
|
||||||
void blur(Mat& inout, int half_kernel_size);
|
|
||||||
};
|
|
@ -1,27 +0,0 @@
|
|||||||
#include "cvsample.h"
|
|
||||||
#include <opencv2/imgproc/imgproc.hpp>
|
|
||||||
|
|
||||||
void CVSample::canny(const cv::Mat& input, cv::Mat& output, int edgeThresh)
|
|
||||||
{
|
|
||||||
if (input.empty())
|
|
||||||
return;
|
|
||||||
cv::Mat gray;
|
|
||||||
if (input.channels() == 3)
|
|
||||||
{
|
|
||||||
cv::cvtColor(input, gray, CV_RGB2GRAY);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
gray = input;
|
|
||||||
cv::Canny(gray, output, edgeThresh, edgeThresh * 3, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVSample::invert(cv::Mat& inout)
|
|
||||||
{
|
|
||||||
cv::bitwise_not(inout, inout);
|
|
||||||
}
|
|
||||||
void CVSample::blur(cv::Mat& inout, int half_kernel_size)
|
|
||||||
{
|
|
||||||
int ksz = half_kernel_size*2 + 1;
|
|
||||||
cv::Size kernel(ksz,ksz);
|
|
||||||
cv::blur(inout,inout,kernel);
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <opencv2/core/core.hpp>
|
|
||||||
|
|
||||||
class CVSample
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void canny(const cv::Mat& input, cv::Mat& output, int edgeThresh);
|
|
||||||
void invert(cv::Mat& inout);
|
|
||||||
void blur(cv::Mat& inout, int half_kernel_size);
|
|
||||||
};
|
|
@ -1,3 +0,0 @@
|
|||||||
#this generates an ant based cli build of the android-jni project
|
|
||||||
android update project --name OpenCV_SAMPLE \
|
|
||||||
--path .
|
|
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.8 KiB |
@ -1,12 +0,0 @@
|
|||||||
<?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"
|
|
||||||
>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/hello"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|