Ported camera calibration code.
This commit is contained in:
@@ -3,8 +3,9 @@ LOCAL_PATH := $(call my-dir)
|
|||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
OPENCV_CAMERA_MODULES:=off
|
OPENCV_CAMERA_MODULES:=off
|
||||||
OPENCV_LIB_TYPE:=STATIC
|
OPENCV_LIB_TYPE:=STATIC #SHARED
|
||||||
include C:\Users\miguel.astor\Documents\OpenCV-2.4.8-android-sdk\sdk\native\jni\OpenCV.mk
|
include C:\Users\miguel.astor\Documents\OpenCV-2.4.8-android-sdk\sdk\native\jni\OpenCV.mk
|
||||||
|
#include C:\NVPACK\OpenCV-2.4.5-Tegra-sdk-r2\sdk\native\jni\OpenCV-tegra3.mk
|
||||||
|
|
||||||
LOCAL_MODULE := cvproc
|
LOCAL_MODULE := cvproc
|
||||||
LOCAL_SRC_FILES := cv_proc.cpp marker.cpp
|
LOCAL_SRC_FILES := cv_proc.cpp marker.cpp
|
||||||
|
200
jni/marker.cpp
200
jni/marker.cpp
@@ -24,93 +24,74 @@
|
|||||||
|
|
||||||
namespace nxtar{
|
namespace nxtar{
|
||||||
|
|
||||||
typedef std::vector<cv::Point3f> points_vector_3D;
|
typedef std::vector<cv::Point3f> points_vector_3D;
|
||||||
typedef std::vector<std::vector<cv::Point> > contours_vector;
|
typedef std::vector<std::vector<cv::Point> > contours_vector;
|
||||||
typedef std::vector<Marker> markers_vector;
|
typedef std::vector<Marker> markers_vector;
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* PRIVATE CONSTANTS *
|
* PRIVATE CONSTANTS *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Minimal number of points in a contour.
|
||||||
|
*/
|
||||||
|
static const int MIN_POINTS = 40;
|
||||||
|
|
||||||
|
/**
|
||||||
* Size of a square cell in the calibration pattern.
|
* Size of a square cell in the calibration pattern.
|
||||||
*/
|
*/
|
||||||
static const float SQUARE_SIZE = 1.0f;
|
static const float SQUARE_SIZE = 1.0f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimal lenght of a contour to be considered as a marker candidate.
|
* Minimal lenght of a contour to be considered as a marker candidate.
|
||||||
*/
|
*/
|
||||||
static const float MIN_CONTOUR_LENGTH = 0.1;
|
static const float MIN_CONTOUR_LENGTH = 0.1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flags for the calibration pattern detecion function.
|
* Flags for the calibration pattern detecion function.
|
||||||
*/
|
*/
|
||||||
static const int PATTERN_DETECTION_FLAGS = cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE + cv::CALIB_CB_FAST_CHECK;
|
static const int PATTERN_DETECTION_FLAGS = cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE + cv::CALIB_CB_FAST_CHECK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Color for rendering the marker outlines.
|
* Color for rendering the marker outlines.
|
||||||
*/
|
*/
|
||||||
static const cv::Scalar COLOR = cv::Scalar(255, 255, 255);
|
static const cv::Scalar COLOR = cv::Scalar(255, 255, 255);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Size of the chessboard pattern image (columns, rows).
|
* Size of the chessboard pattern image (columns, rows).
|
||||||
*/
|
*/
|
||||||
static const cv::Size CHESSBOARD_PATTERN_SIZE(6, 9);
|
static const cv::Size CHESSBOARD_PATTERN_SIZE(6, 9);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Termination criteria for OpenCV's iterative algorithms.
|
* Termination criteria for OpenCV's iterative algorithms.
|
||||||
*/
|
*/
|
||||||
static const cv::TermCriteria TERM_CRITERIA = cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1);
|
static const cv::TermCriteria TERM_CRITERIA = cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1);
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* PRIVATE FUNCTION PROTOTYPES *
|
* PRIVATE FUNCTION PROTOTYPES *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/**
|
float perimeter(points_vector &);
|
||||||
* Calculates the perimeter of a points vector defining a polygon.
|
|
||||||
*/
|
|
||||||
float perimeter(points_vector &);
|
|
||||||
|
|
||||||
/**
|
int hammDistMarker(cv::Mat);
|
||||||
* Calculates the Hamming distance of a 5x5 marker.
|
|
||||||
*/
|
|
||||||
int hammDistMarker(cv::Mat);
|
|
||||||
|
|
||||||
/**
|
cv::Mat rotate(cv::Mat);
|
||||||
* Rotates an OpenCV matrix in place by 90 degrees clockwise.
|
|
||||||
*/
|
|
||||||
cv::Mat rotate(cv::Mat);
|
|
||||||
|
|
||||||
/**
|
int decodeMarker(cv::Mat &);
|
||||||
* Returns the code of a 5x5 marker or -1 if the marker is not valid.
|
|
||||||
*/
|
|
||||||
int decodeMarker(cv::Mat &);
|
|
||||||
|
|
||||||
/**
|
void renderMarkers(markers_vector &, cv::Mat &);
|
||||||
* Renders the polygon defined in the input vector on the specified image.
|
|
||||||
*/
|
|
||||||
void renderMarkers(markers_vector &, cv::Mat &);
|
|
||||||
|
|
||||||
/**
|
void isolateMarkers(const contours_vector &, markers_vector &);
|
||||||
* Identifies all possible marker candidates in a polygon vector.
|
|
||||||
*/
|
|
||||||
void isolateMarkers(const contours_vector &, markers_vector &);
|
|
||||||
|
|
||||||
/**
|
void findContours(cv::Mat &, contours_vector &, int);
|
||||||
* Identifies all roughly 4 side figures in the input image.
|
|
||||||
*/
|
|
||||||
void findContours(cv::Mat &, contours_vector &, int);
|
|
||||||
|
|
||||||
/**
|
void warpMarker(Marker &, cv::Mat &, cv::Mat &);
|
||||||
* Removes the prerspective distortion from a marker candidate image.
|
|
||||||
*/
|
|
||||||
void warpMarker(Marker &, cv::Mat &, cv::Mat &);
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* PUBLIC API *
|
* PUBLIC API *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
void getAllMarkers(std::vector<int> & codes, cv::Mat & img){
|
void getAllMarkers(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;
|
||||||
@@ -127,12 +108,12 @@ namespace nxtar{
|
|||||||
// 3) Finally indentify all 4 sided figures in the binarized image.
|
// 3) Finally indentify all 4 sided figures in the binarized image.
|
||||||
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
||||||
cv::adaptiveThreshold(gray, thresh, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 7, 7);
|
cv::adaptiveThreshold(gray, thresh, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 7, 7);
|
||||||
findContours(thresh, contours, 40);
|
findContours(thresh, contours, MIN_POINTS);
|
||||||
isolateMarkers(contours, markers);
|
isolateMarkers(contours, markers);
|
||||||
|
|
||||||
// Remove the perspective distortion from the detected marker candidates.
|
// Remove the perspective distortion from the detected marker candidates.
|
||||||
// Then attempt to decode them and push the valid ones into the valid
|
// Then attempt to decode them and push the valid ones into the valid
|
||||||
// markes vector.
|
// markers vector.
|
||||||
for(int i = 0; i < markers.size(); i++){
|
for(int i = 0; i < markers.size(); i++){
|
||||||
warpMarker(markers[i], gray, mark);
|
warpMarker(markers[i], gray, mark);
|
||||||
|
|
||||||
@@ -177,9 +158,9 @@ namespace nxtar{
|
|||||||
markers.clear();
|
markers.clear();
|
||||||
contours.clear();
|
contours.clear();
|
||||||
valid_markers.clear();
|
valid_markers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool findCalibrationPattern(points_vector & corners, cv::Mat & img){
|
bool findCalibrationPattern(points_vector & corners, cv::Mat & img){
|
||||||
bool patternfound;
|
bool patternfound;
|
||||||
cv::Mat gray;
|
cv::Mat gray;
|
||||||
|
|
||||||
@@ -196,14 +177,14 @@ namespace nxtar{
|
|||||||
cv::drawChessboardCorners(img, CHESSBOARD_PATTERN_SIZE, cv::Mat(corners), patternfound);
|
cv::drawChessboardCorners(img, CHESSBOARD_PATTERN_SIZE, cv::Mat(corners), patternfound);
|
||||||
|
|
||||||
return patternfound;
|
return patternfound;
|
||||||
}
|
}
|
||||||
|
|
||||||
double getCameraParameters(cv::Mat & camera_matrix, cv::Mat & dist_coeffs, std::vector<points_vector> & image_points, cv::Size image_size){
|
double getCameraParameters(cv::Mat & camera_matrix, cv::Mat & dist_coeffs, std::vector<points_vector> & image_points, cv::Size image_size){
|
||||||
std::vector<cv::Mat> rvecs, tvecs;
|
std::vector<cv::Mat> rvecs, tvecs;
|
||||||
std::vector<points_vector_3D> object_points;
|
std::vector<points_vector_3D> object_points;
|
||||||
points_vector_3D corner_points;
|
points_vector_3D corner_points;
|
||||||
|
|
||||||
// Build the reference object points vector;
|
// Build the reference object points vector.
|
||||||
for(int i = 0; i < CHESSBOARD_PATTERN_SIZE.height; i++){
|
for(int i = 0; i < CHESSBOARD_PATTERN_SIZE.height; i++){
|
||||||
for(int j = 0; j < CHESSBOARD_PATTERN_SIZE.width; j++){
|
for(int j = 0; j < CHESSBOARD_PATTERN_SIZE.width; j++){
|
||||||
corner_points.push_back(cv::Point3f(float( j * SQUARE_SIZE ), float( i * SQUARE_SIZE ), 0));
|
corner_points.push_back(cv::Point3f(float( j * SQUARE_SIZE ), float( i * SQUARE_SIZE ), 0));
|
||||||
@@ -220,14 +201,21 @@ namespace nxtar{
|
|||||||
|
|
||||||
// Calibrate and return the reprojection error.
|
// Calibrate and return the reprojection error.
|
||||||
return cv::calibrateCamera(object_points, image_points, image_size, camera_matrix, dist_coeffs, rvecs, tvecs, 0, TERM_CRITERIA);
|
return cv::calibrateCamera(object_points, image_points, image_size, camera_matrix, dist_coeffs, rvecs, tvecs, 0, TERM_CRITERIA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* PRIVATE HELPER FUNCTIONS *
|
* PRIVATE HELPER FUNCTIONS *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
void findContours(cv::Mat & img, contours_vector & v, int minP){
|
/**
|
||||||
|
* Find all contours in the input image and save them to the output
|
||||||
|
* vector.
|
||||||
|
*/
|
||||||
|
void findContours(cv::Mat & img, contours_vector & v, int minP){
|
||||||
contours_vector c;
|
contours_vector c;
|
||||||
|
|
||||||
|
// A contour is discarded if it possess less than the specified
|
||||||
|
// minimum number of points.
|
||||||
cv::findContours(img, c, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
|
cv::findContours(img, c, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
|
||||||
|
|
||||||
v.clear();
|
v.clear();
|
||||||
@@ -236,11 +224,15 @@ namespace nxtar{
|
|||||||
v.push_back(c[i]);
|
v.push_back(c[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderMarkers(markers_vector & v, cv::Mat & dst){
|
/**
|
||||||
|
* Render the input marker vector onto the output image.
|
||||||
|
*/
|
||||||
|
void renderMarkers(markers_vector & v, cv::Mat & dst){
|
||||||
contours_vector cv;
|
contours_vector cv;
|
||||||
|
|
||||||
|
// Extract the points that form every marker into a contours vector.
|
||||||
for(size_t i = 0; i < v.size(); i++){
|
for(size_t i = 0; i < v.size(); i++){
|
||||||
std::vector<cv::Point> pv;
|
std::vector<cv::Point> pv;
|
||||||
for(size_t j = 0; j < v[i].points.size(); ++j)
|
for(size_t j = 0; j < v[i].points.size(); ++j)
|
||||||
@@ -248,19 +240,30 @@ namespace nxtar{
|
|||||||
cv.push_back(pv);
|
cv.push_back(pv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render.
|
||||||
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){
|
/**
|
||||||
|
* Identify and return all marker candidates.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
// For every detected contour.
|
||||||
for(size_t i = 0; i < vc.size(); ++i){
|
for(size_t i = 0; i < vc.size(); ++i){
|
||||||
double eps = vc[i].size() * 0.05;
|
double eps = vc[i].size() * 0.05;
|
||||||
|
|
||||||
|
// Approximate the contour with a polygon.
|
||||||
cv::approxPolyDP(vc[i], appCurve, eps, true);
|
cv::approxPolyDP(vc[i], appCurve, eps, true);
|
||||||
|
|
||||||
|
// If the polygon is not a cuadrilateral then this is not a marker
|
||||||
|
// candidate.
|
||||||
if(appCurve.size() != 4 || !cv::isContourConvex(appCurve)) continue;
|
if(appCurve.size() != 4 || !cv::isContourConvex(appCurve)) continue;
|
||||||
|
|
||||||
|
// Calculate the lenght of the perimeter of this candidate. If it
|
||||||
|
// is too short then discard it.
|
||||||
float minD = std::numeric_limits<float>::max();
|
float minD = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
@@ -271,6 +274,7 @@ namespace nxtar{
|
|||||||
|
|
||||||
if(minD < MIN_CONTOUR_LENGTH) continue;
|
if(minD < MIN_CONTOUR_LENGTH) continue;
|
||||||
|
|
||||||
|
// Save the marker and order it's points counter-clockwise.
|
||||||
Marker m;
|
Marker m;
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++)
|
for(int i = 0; i < 4; i++)
|
||||||
@@ -285,6 +289,8 @@ namespace nxtar{
|
|||||||
posMarkers.push_back(m);
|
posMarkers.push_back(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Identify contours that are to close to each other to eliminate
|
||||||
|
// possible duplicates.
|
||||||
std::vector<std::pair<int, int> > tooNear;
|
std::vector<std::pair<int, int> > tooNear;
|
||||||
for(size_t i = 0; i < posMarkers.size(); ++i){
|
for(size_t i = 0; i < posMarkers.size(); ++i){
|
||||||
const Marker & m1 = posMarkers[i];
|
const Marker & m1 = posMarkers[i];
|
||||||
@@ -305,8 +311,8 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark one of every pair of duplicates to be discarded.
|
||||||
std::vector<bool> remMask(posMarkers.size(), false);
|
std::vector<bool> remMask(posMarkers.size(), false);
|
||||||
|
|
||||||
for(size_t i = 0; i < tooNear.size(); ++i){
|
for(size_t i = 0; i < tooNear.size(); ++i){
|
||||||
float p1 = perimeter(posMarkers[tooNear[i].first].points);
|
float p1 = perimeter(posMarkers[tooNear[i].first].points);
|
||||||
float p2 = perimeter(posMarkers[tooNear[i].second].points);
|
float p2 = perimeter(posMarkers[tooNear[i].second].points);
|
||||||
@@ -318,28 +324,40 @@ namespace nxtar{
|
|||||||
remMask[remInd] = true;
|
remMask[remInd] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save the candidates that survided the duplicates test.
|
||||||
vm.clear();
|
vm.clear();
|
||||||
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){
|
/**
|
||||||
|
* Warp a marker image to remove it's perspective distortion.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Assemble a unitary reference polygon.
|
||||||
v.push_back(cv::Point2f(0,0));
|
v.push_back(cv::Point2f(0,0));
|
||||||
v.push_back(cv::Point2f(markerSize.width-1,0));
|
v.push_back(cv::Point2f(markerSize.width-1,0));
|
||||||
v.push_back(cv::Point2f(markerSize.width-1,markerSize.height-1));
|
v.push_back(cv::Point2f(markerSize.width-1,markerSize.height-1));
|
||||||
v.push_back(cv::Point2f(0,markerSize.height-1));
|
v.push_back(cv::Point2f(0,markerSize.height-1));
|
||||||
|
|
||||||
|
// Warp the input image's perspective to transform it into the reference
|
||||||
|
// polygon's perspective.
|
||||||
cv::Mat M = cv::getPerspectiveTransform(m.points, v);
|
cv::Mat M = cv::getPerspectiveTransform(m.points, v);
|
||||||
cv::warpPerspective(in, bin, M, markerSize);
|
cv::warpPerspective(in, bin, M, markerSize);
|
||||||
|
|
||||||
|
// Binarize the warped image into the output image.
|
||||||
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){
|
/**
|
||||||
|
* Calculate the hamming distance of a 5x5 bit matrix.
|
||||||
|
*/
|
||||||
|
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},
|
||||||
@@ -367,10 +385,14 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return dist;
|
return dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::Mat rotate(cv::Mat in){
|
/**
|
||||||
|
* Rotate a matrix by 90 degrees clockwise.
|
||||||
|
*/
|
||||||
|
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++){
|
||||||
for (int j=0;j<in.cols;j++){
|
for (int j=0;j<in.cols;j++){
|
||||||
@@ -379,45 +401,53 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
int decodeMarker(cv::Mat & marker){
|
/**
|
||||||
|
* Decode a marker image and return it's code. Returns -1 if the image is
|
||||||
|
* not a valid marker.
|
||||||
|
*/
|
||||||
|
int decodeMarker(cv::Mat & marker){
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int code = 0;
|
int code = 0;
|
||||||
cv::Mat bits;
|
cv::Mat bits;
|
||||||
|
|
||||||
|
// Verify that the outer rim of marker cells are all black.
|
||||||
for(int y = 0; y < 7; y++){
|
for(int y = 0; y < 7; y++){
|
||||||
int inc = (y == 0 || y == 6) ? 1 : 6;
|
int inc = (y == 0 || y == 6) ? 1 : 6;
|
||||||
|
|
||||||
for(int x = 0; x < 7; x += inc){
|
for(int x = 0; x < 7; x += inc){
|
||||||
int cX = x * 50;
|
int cX = x * 50;
|
||||||
int cY = y * 50;
|
int cY = y * 50;
|
||||||
|
|
||||||
cv::Mat cell = marker(cv::Rect(cX, cY, 50, 50));
|
cv::Mat cell = marker(cv::Rect(cX, cY, 50, 50));
|
||||||
|
|
||||||
int nZ = cv::countNonZero(cell);
|
int nZ = cv::countNonZero(cell);
|
||||||
|
|
||||||
// Not a valid marker.
|
// If one of the rim cells is 50% white or more then this
|
||||||
|
// is not a valid marker.
|
||||||
if(nZ > (50 * 50) / 2) return -1;
|
if(nZ > (50 * 50) / 2) return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a 5x5 matrix to hold a simplified representation of this
|
||||||
|
// marker.
|
||||||
bits = cv::Mat::zeros(5, 5, CV_8UC1);
|
bits = cv::Mat::zeros(5, 5, CV_8UC1);
|
||||||
|
|
||||||
|
// For every cell in the marker flip it's corresponding 'bit' in the
|
||||||
|
// bit matrix if it is at least 50 % white.
|
||||||
for(int y = 0; y < 5; y++){
|
for(int y = 0; y < 5; y++){
|
||||||
for(int x = 0; x < 5; x++){
|
for(int x = 0; x < 5; x++){
|
||||||
int cX = (x + 1) * 50;
|
int cX = (x + 1) * 50;
|
||||||
int cY = (y + 1) * 50;
|
int cY = (y + 1) * 50;
|
||||||
|
|
||||||
cv::Mat cell = marker(cv::Rect(cX, cY, 50, 50));
|
cv::Mat cell = marker(cv::Rect(cX, cY, 50, 50));
|
||||||
|
|
||||||
int nZ = cv::countNonZero(cell);
|
int nZ = cv::countNonZero(cell);
|
||||||
|
|
||||||
if(nZ > (50 * 50) / 2) bits.at<uchar>(y, x) = 1;
|
if(nZ > (50 * 50) / 2) bits.at<uchar>(y, x) = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calcultate the hamming distance of the bit matrix and each of it's
|
||||||
|
// 90 degree rotations to determine if this marker has a valid code.
|
||||||
if(hammDistMarker(bits) != 0){
|
if(hammDistMarker(bits) != 0){
|
||||||
for(int r = 1; r < 4; r++){
|
for(int r = 1; r < 4; r++){
|
||||||
bits = rotate(bits);
|
bits = rotate(bits);
|
||||||
@@ -426,7 +456,7 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
}else found = true;
|
}else found = true;
|
||||||
|
|
||||||
|
// If the code is valid then decode it to an int and return it.
|
||||||
if(found){
|
if(found){
|
||||||
for(int y = 0; y < 5; y++){
|
for(int y = 0; y < 5; y++){
|
||||||
code <<= 1;
|
code <<= 1;
|
||||||
@@ -442,9 +472,12 @@ namespace nxtar{
|
|||||||
return code;
|
return code;
|
||||||
}else
|
}else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float perimeter(points_vector & p){
|
/**
|
||||||
|
* Calculate the perimeter of a polygon defined as a vector of points.
|
||||||
|
*/
|
||||||
|
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){
|
||||||
@@ -454,13 +487,16 @@ namespace nxtar{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return per;
|
return per;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* CLASS METHODS *
|
* CLASS METHODS *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
Marker::~Marker(){
|
/**
|
||||||
|
* Clear the points vector associated with this marker.
|
||||||
|
*/
|
||||||
|
Marker::~Marker(){
|
||||||
points.clear();
|
points.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -169,4 +169,10 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void calibrateCamera() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user