Added the camera calibration pattern detection.
This commit is contained in:
@@ -22,6 +22,7 @@
|
|||||||
//#define CAN_LOG
|
//#define CAN_LOG
|
||||||
|
|
||||||
extern "C"{
|
extern "C"{
|
||||||
|
|
||||||
#ifdef CAN_LOG
|
#ifdef CAN_LOG
|
||||||
#define log(TAG, MSG) (__android_log_write(ANDROID_LOG_DEBUG, TAG, MSG))
|
#define log(TAG, MSG) (__android_log_write(ANDROID_LOG_DEBUG, TAG, MSG))
|
||||||
const char * TAG = "CVPROC_NATIVE";
|
const char * TAG = "CVPROC_NATIVE";
|
||||||
@@ -29,13 +30,13 @@ const char * TAG = "CVPROC_NATIVE";
|
|||||||
#define log(TAG, MSG) (1 + 1)
|
#define log(TAG, MSG) (1 + 1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_ve_ucv_ciens_ccg_nxtar_MainActivity_getMarkerCodesAndLocations(
|
JNIEXPORT void JNICALL Java_ve_ucv_ciens_ccg_nxtar_MainActivity_getMarkerCodesAndLocations(
|
||||||
JNIEnv* env,
|
JNIEnv* env,
|
||||||
jobject jobj,
|
jobject jobj,
|
||||||
jlong addrMatIn,
|
jlong addrMatIn,
|
||||||
jlong addrMatOut,
|
jlong addrMatOut,
|
||||||
jintArray codes
|
jintArray codes
|
||||||
){
|
){
|
||||||
char codeMsg[128];
|
char codeMsg[128];
|
||||||
std::vector<int> vCodes;
|
std::vector<int> vCodes;
|
||||||
|
|
||||||
@@ -62,5 +63,24 @@ const char * TAG = "CVPROC_NATIVE";
|
|||||||
log(TAG, "Releasing native data.");
|
log(TAG, "Releasing native data.");
|
||||||
|
|
||||||
env->ReleaseIntArrayElements(codes, _codes, 0);
|
env->ReleaseIntArrayElements(codes, _codes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_ve_ucv_ciens_ccg_nxtar_MainActivity_findCalibrationPattern(
|
||||||
|
JNIEnv* env,
|
||||||
|
jobject jobj,
|
||||||
|
jlong addrMatIn,
|
||||||
|
jlong addrMatOut
|
||||||
|
){
|
||||||
|
log(TAG, "Requesting native data.");
|
||||||
|
|
||||||
|
cv::Mat& myuv = *(cv::Mat*)addrMatIn;
|
||||||
|
cv::Mat& mbgr = *(cv::Mat*)addrMatOut;
|
||||||
|
|
||||||
|
log(TAG, "Converting color space before processing.");
|
||||||
|
cv::cvtColor(myuv, mbgr, CV_RGB2BGR);
|
||||||
|
|
||||||
|
log(TAG, "Finding markers.");
|
||||||
|
nxtar::calibrateCamera(mbgr);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
166
jni/marker.cpp
166
jni/marker.cpp
@@ -24,86 +24,33 @@
|
|||||||
|
|
||||||
namespace nxtar{
|
namespace nxtar{
|
||||||
|
|
||||||
static const cv::Scalar COLOR = cv::Scalar(255, 255, 255);
|
static int PATTERN_DETECTION_PARAMS = cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE + cv::CALIB_CB_FAST_CHECK;
|
||||||
|
static const cv::TermCriteria termCriteria = cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1);
|
||||||
|
static const cv::Scalar COLOR = cv::Scalar(255, 255, 255);
|
||||||
|
static const cv::Size checkersPatternSize(6, 9);
|
||||||
|
|
||||||
class Marker;
|
float perimeter (points_vector &);
|
||||||
|
int hammDistMarker (cv::Mat);
|
||||||
|
cv::Mat rotate (cv::Mat);
|
||||||
|
int decodeMarker (cv::Mat &);
|
||||||
|
void renderMarkers (markers_vector &, cv::Mat &);
|
||||||
|
void isolateMarkers (const contours_vector &, markers_vector &);
|
||||||
|
void findContours (cv::Mat &, contours_vector &, int);
|
||||||
|
void warpMarker (Marker &, cv::Mat &, cv::Mat &);
|
||||||
|
|
||||||
typedef std::vector<std::vector<cv::Point> > contours_vector;
|
void getAllMarkers(std::vector<int> & codes, cv::Mat & img){
|
||||||
typedef std::vector<cv::Point2f> points_vector;
|
|
||||||
typedef std::vector<Marker> markers_vector;
|
|
||||||
|
|
||||||
class Marker{
|
|
||||||
public:
|
|
||||||
~Marker();
|
|
||||||
points_vector points;
|
|
||||||
int code;
|
|
||||||
};
|
|
||||||
|
|
||||||
float perimeter(points_vector &);
|
|
||||||
int hammDistMarker(cv::Mat);
|
|
||||||
cv::Mat rotate(cv::Mat);
|
|
||||||
void binarize(cv::Mat &, cv::Mat &);
|
|
||||||
void findContours(cv::Mat &, contours_vector &, int);
|
|
||||||
void renderContours(contours_vector &, cv::Mat &);
|
|
||||||
void renderMarkers(markers_vector &, cv::Mat &);
|
|
||||||
void warpMarker(Marker &, cv::Mat &, cv::Mat &);
|
|
||||||
int decodeMarker(cv::Mat &);
|
|
||||||
void fixCorners(cv::Mat &, Marker &);
|
|
||||||
void isolateMarkers(const contours_vector &, markers_vector &);
|
|
||||||
|
|
||||||
void getAllMarkers(std::vector<int> & codes, cv::Mat & img){
|
|
||||||
cv::Mat gray, thresh, cont, mark;
|
|
||||||
contours_vector contours;
|
|
||||||
markers_vector markers;
|
|
||||||
markers_vector valid_markers;
|
|
||||||
|
|
||||||
codes.clear();
|
|
||||||
|
|
||||||
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
|
||||||
binarize(gray, thresh);
|
|
||||||
findContours(thresh, contours, 40);
|
|
||||||
isolateMarkers(contours, markers);
|
|
||||||
|
|
||||||
for(int i = 0; i < markers.size(); i++){
|
|
||||||
warpMarker(markers[i], gray, mark);
|
|
||||||
|
|
||||||
int code = decodeMarker(mark);
|
|
||||||
|
|
||||||
if(code != -1){
|
|
||||||
markers[i].code = code;
|
|
||||||
valid_markers.push_back(markers[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < valid_markers.size(); i++)
|
|
||||||
fixCorners(gray, valid_markers[i]);
|
|
||||||
|
|
||||||
cont = cv::Mat::zeros(img.size(), CV_8UC3);
|
|
||||||
renderMarkers(valid_markers, cont);
|
|
||||||
|
|
||||||
img = img + cont;
|
|
||||||
|
|
||||||
for(int i = 0; i < valid_markers.size(); i++){
|
|
||||||
codes.push_back(valid_markers[i].code);
|
|
||||||
}
|
|
||||||
|
|
||||||
markers.clear();
|
|
||||||
contours.clear();
|
|
||||||
valid_markers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DESKTOP
|
|
||||||
void getAllMarkers_d(std::vector<int> & codes, cv::Mat & img){
|
|
||||||
cv::Mat gray, thresh, cont, mark;
|
cv::Mat gray, thresh, cont, mark;
|
||||||
contours_vector contours;
|
contours_vector contours;
|
||||||
markers_vector markers;
|
markers_vector markers;
|
||||||
markers_vector valid_markers;
|
markers_vector valid_markers;
|
||||||
|
#ifdef DESKTOP
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
#endif
|
||||||
|
|
||||||
codes.clear();
|
codes.clear();
|
||||||
|
|
||||||
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
||||||
binarize(gray, thresh);
|
cv::adaptiveThreshold(gray, thresh, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 7, 7);
|
||||||
findContours(thresh, contours, 40);
|
findContours(thresh, contours, 40);
|
||||||
isolateMarkers(contours, markers);
|
isolateMarkers(contours, markers);
|
||||||
|
|
||||||
@@ -118,15 +65,8 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < valid_markers.size(); i++)
|
|
||||||
fixCorners(gray, valid_markers[i]);
|
|
||||||
|
|
||||||
cont = cv::Mat::zeros(img.size(), CV_8UC3);
|
|
||||||
renderMarkers(valid_markers, cont);
|
|
||||||
|
|
||||||
img = img + cont;
|
|
||||||
|
|
||||||
for(int i = 0; i < valid_markers.size(); i++){
|
for(int i = 0; i < valid_markers.size(); i++){
|
||||||
|
#ifdef DESKTOP
|
||||||
oss << valid_markers[i].code;
|
oss << valid_markers[i].code;
|
||||||
|
|
||||||
cv::putText(mark, oss.str(), cv::Point(5, 250), cv::FONT_HERSHEY_PLAIN, 2, cv::Scalar::all(128), 3, 8);
|
cv::putText(mark, oss.str(), cv::Point(5, 250), cv::FONT_HERSHEY_PLAIN, 2, cv::Scalar::all(128), 3, 8);
|
||||||
@@ -140,21 +80,36 @@ namespace nxtar{
|
|||||||
|
|
||||||
oss.str("");
|
oss.str("");
|
||||||
oss.clear();
|
oss.clear();
|
||||||
|
#endif
|
||||||
|
cv::cornerSubPix(gray, valid_markers[i].points, cvSize(10, 10), cvSize(-1, -1), termCriteria);
|
||||||
codes.push_back(valid_markers[i].code);
|
codes.push_back(valid_markers[i].code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cont = cv::Mat::zeros(img.size(), CV_8UC3);
|
||||||
|
renderMarkers(valid_markers, cont);
|
||||||
|
|
||||||
|
img = img + cont;
|
||||||
|
|
||||||
markers.clear();
|
markers.clear();
|
||||||
contours.clear();
|
contours.clear();
|
||||||
valid_markers.clear();
|
valid_markers.clear();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void binarize(cv::Mat & src, cv::Mat & dst){
|
void calibrateCamera(cv::Mat & img){
|
||||||
cv::adaptiveThreshold(src, dst, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 7, 7);
|
bool patternfound;
|
||||||
}
|
points_vector corners;
|
||||||
|
cv::Mat gray;
|
||||||
|
|
||||||
void findContours(cv::Mat & img, contours_vector & v, int minP){
|
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
||||||
|
patternfound = cv::findChessboardCorners(gray, checkersPatternSize, corners, PATTERN_DETECTION_PARAMS);
|
||||||
|
|
||||||
|
if(patternfound)
|
||||||
|
cv::cornerSubPix(gray, corners, cv::Size(11, 11), cv::Size(-1, -1), termCriteria);
|
||||||
|
|
||||||
|
cv::drawChessboardCorners(img, checkersPatternSize, cv::Mat(corners), patternfound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void findContours(cv::Mat & img, contours_vector & v, int minP){
|
||||||
std::vector<std::vector<cv::Point> > c;
|
std::vector<std::vector<cv::Point> > c;
|
||||||
cv::findContours(img, c, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
|
cv::findContours(img, c, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
|
||||||
|
|
||||||
@@ -164,13 +119,9 @@ namespace nxtar{
|
|||||||
v.push_back(c[i]);
|
v.push_back(c[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderContours(contours_vector & v, cv::Mat & dst){
|
void renderMarkers(markers_vector & v, cv::Mat & dst){
|
||||||
cv::drawContours(dst, v, -1, COLOR, 1, CV_AA);
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderMarkers(markers_vector & v, cv::Mat & dst){
|
|
||||||
contours_vector cv;
|
contours_vector cv;
|
||||||
|
|
||||||
for(size_t i = 0; i < v.size(); i++){
|
for(size_t i = 0; i < v.size(); i++){
|
||||||
@@ -181,9 +132,9 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
|
|
||||||
cv::drawContours(dst, cv, -1, COLOR, 1, CV_AA);
|
cv::drawContours(dst, cv, -1, COLOR, 1, CV_AA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isolateMarkers(const contours_vector & vc, markers_vector & vm){
|
void isolateMarkers(const contours_vector & vc, markers_vector & vm){
|
||||||
std::vector<cv::Point> appCurve;
|
std::vector<cv::Point> appCurve;
|
||||||
markers_vector posMarkers;
|
markers_vector posMarkers;
|
||||||
|
|
||||||
@@ -254,9 +205,9 @@ namespace nxtar{
|
|||||||
for(size_t i = 0; i < posMarkers.size(); ++i){
|
for(size_t i = 0; i < posMarkers.size(); ++i){
|
||||||
if(remMask[i]) vm.push_back(posMarkers[i]);
|
if(remMask[i]) vm.push_back(posMarkers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void warpMarker(Marker & m, cv::Mat & in, cv::Mat & out){
|
void warpMarker(Marker & m, cv::Mat & in, cv::Mat & out){
|
||||||
cv::Mat bin;
|
cv::Mat bin;
|
||||||
cv::Size markerSize(350, 350);
|
cv::Size markerSize(350, 350);
|
||||||
points_vector v;
|
points_vector v;
|
||||||
@@ -269,9 +220,9 @@ namespace nxtar{
|
|||||||
cv::warpPerspective(in, bin, M, markerSize);
|
cv::warpPerspective(in, bin, M, markerSize);
|
||||||
|
|
||||||
cv::threshold(bin, out, 128, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
|
cv::threshold(bin, out, 128, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hammDistMarker(cv::Mat bits){
|
int hammDistMarker(cv::Mat bits){
|
||||||
int ids[4][5] = {
|
int ids[4][5] = {
|
||||||
{1,0,0,0,0},
|
{1,0,0,0,0},
|
||||||
{1,0,1,1,1},
|
{1,0,1,1,1},
|
||||||
@@ -299,8 +250,9 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return dist;
|
return dist;
|
||||||
}
|
}
|
||||||
cv::Mat rotate(cv::Mat in){
|
|
||||||
|
cv::Mat rotate(cv::Mat in){
|
||||||
cv::Mat out;
|
cv::Mat out;
|
||||||
in.copyTo(out);
|
in.copyTo(out);
|
||||||
for (int i=0;i<in.rows;i++){
|
for (int i=0;i<in.rows;i++){
|
||||||
@@ -310,9 +262,9 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
int decodeMarker(cv::Mat & marker){
|
int decodeMarker(cv::Mat & marker){
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int code = 0;
|
int code = 0;
|
||||||
cv::Mat bits;
|
cv::Mat bits;
|
||||||
@@ -373,13 +325,9 @@ namespace nxtar{
|
|||||||
return code;
|
return code;
|
||||||
}else
|
}else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fixCorners(cv::Mat & img, Marker & m){
|
float perimeter(points_vector & p){
|
||||||
cv::cornerSubPix(img, m.points, cvSize(10, 10), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_ITER, 30, 0.1));
|
|
||||||
}
|
|
||||||
|
|
||||||
float perimeter(points_vector & p){
|
|
||||||
float per = 0.0f, dx, dy;
|
float per = 0.0f, dx, dy;
|
||||||
|
|
||||||
for(size_t i; i < p.size(); ++i){
|
for(size_t i; i < p.size(); ++i){
|
||||||
@@ -389,10 +337,10 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return per;
|
return per;
|
||||||
}
|
}
|
||||||
|
|
||||||
Marker::~Marker(){
|
Marker::~Marker(){
|
||||||
points.clear();
|
points.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -20,10 +20,22 @@
|
|||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
|
|
||||||
namespace nxtar{
|
namespace nxtar{
|
||||||
void getAllMarkers(std::vector<int> &, cv::Mat &);
|
|
||||||
#ifdef DESKTOP
|
class Marker;
|
||||||
void getAllMarkers_d(std::vector<int> &, cv::Mat &);
|
|
||||||
#endif
|
typedef std::vector<std::vector<cv::Point> > contours_vector;
|
||||||
|
typedef std::vector<cv::Point2f> points_vector;
|
||||||
|
typedef std::vector<Marker> markers_vector;
|
||||||
|
|
||||||
|
class Marker{
|
||||||
|
public:
|
||||||
|
~Marker();
|
||||||
|
points_vector points;
|
||||||
|
int code;
|
||||||
|
};
|
||||||
|
|
||||||
|
void getAllMarkers(std::vector<int> &, cv::Mat &);
|
||||||
|
void calibrateCamera(cv::Mat &);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -9,4 +9,4 @@
|
|||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-19
|
target=android-19
|
||||||
android.library.reference.1=../../../../../Escritorio/OpenCV-2.4.7-android-sdk/sdk/java
|
android.library.reference.1=../../../../../NVPACK/OpenCV-2.4.5-Tegra-sdk-r2/sdk/java
|
||||||
|
@@ -57,17 +57,18 @@ public class MainActivity extends AndroidApplication implements Toaster, Multica
|
|||||||
|
|
||||||
static{
|
static{
|
||||||
if(!OpenCVLoader.initDebug()){
|
if(!OpenCVLoader.initDebug()){
|
||||||
Gdx.app.exit();
|
System.exit(1);
|
||||||
}
|
}
|
||||||
try{
|
try{
|
||||||
System.loadLibrary("cvproc");
|
System.loadLibrary("cvproc");
|
||||||
ocvOn = true;
|
ocvOn = true;
|
||||||
}catch(UnsatisfiedLinkError u){
|
}catch(UnsatisfiedLinkError u){
|
||||||
Gdx.app.exit();
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public native void getMarkerCodesAndLocations(long inMat, long outMat, int[] codes);
|
public native void getMarkerCodesAndLocations(long inMat, long outMat, int[] codes);
|
||||||
|
public native void findCalibrationPattern(long inMat, long outMat);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState){
|
public void onCreate(Bundle savedInstanceState){
|
||||||
@@ -167,7 +168,8 @@ public class MainActivity extends AndroidApplication implements Toaster, Multica
|
|||||||
Mat outImg = new Mat();
|
Mat outImg = new Mat();
|
||||||
Utils.bitmapToMat(tFrame, inImg);
|
Utils.bitmapToMat(tFrame, inImg);
|
||||||
|
|
||||||
getMarkerCodesAndLocations(inImg.getNativeObjAddr(), outImg.getNativeObjAddr(), codes);
|
//getMarkerCodesAndLocations(inImg.getNativeObjAddr(), outImg.getNativeObjAddr(), codes);
|
||||||
|
findCalibrationPattern(inImg.getNativeObjAddr(), outImg.getNativeObjAddr());
|
||||||
|
|
||||||
Mat temp = new Mat();
|
Mat temp = new Mat();
|
||||||
Imgproc.cvtColor(outImg, temp, Imgproc.COLOR_BGR2RGB);
|
Imgproc.cvtColor(outImg, temp, Imgproc.COLOR_BGR2RGB);
|
||||||
|
Reference in New Issue
Block a user