Skip to content

Commit

Permalink
added structure for marker ident.
Browse files Browse the repository at this point in the history
  • Loading branch information
internaut committed May 28, 2014
1 parent 93d7875 commit 66ee8e8
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 25 deletions.
4 changes: 4 additions & 0 deletions common/conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@
#define OCV_AR_CONF_MIN_CONTOUR_LENGTH 30.0f
#define OCV_AR_CONF_MAX_DUPLICATE_DIST 2.0f

#define OCV_AR_CONF_MARKER_SIZE_REAL 0.05f // "real world" marker size in meters

#define OCV_AR_CONF_REFINE_CORNERS_ITER 0

#endif
129 changes: 111 additions & 18 deletions common/detect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ using namespace ocv_ar;

#pragma mark public methods

Detect::Detect() {
Detect::Detect(IdentificatorType identType) {
prepared = false;
inputFrameCvtType = -1;
outFrameProcLvl = DEFAULT;
Expand All @@ -17,6 +17,9 @@ Detect::Detect() {

downsampleSizeW = downsampleSizeH = 0;

ident = NULL;
setIdentificator(identType);

#if !defined(OCV_AR_CONF_DOWNSAMPLE) && defined(OCV_AR_CONF_RESIZE_W) && defined(OCV_AR_CONF_RESIZE_H)
downsampleSizeW = OCV_AR_CONF_RESIZE_W;
downsampleSizeH = OCV_AR_CONF_RESIZE_H;
Expand All @@ -27,6 +30,42 @@ Detect::~Detect() {
if (inFrameOrigGray) delete inFrameOrigGray;
if (inFrame) delete inFrame;
if (outFrame) delete outFrame;
if (ident) delete ident;
}

void Detect::setIdentificator(IdentificatorType identType) {
if (ident) delete ident;

switch (identType) {
case CODE_7BIT:
ident = new Identificator7BitCode();
break;

default:
ident = NULL;
break;
}

normMarkerCoord2D.clear();
normMarkerCoord3D.clear();

if (ident) {
normMarkerSize = ident->getRequiredMarkerSize();

const int s = normMarkerSize - 1;
normMarkerCoord2D.push_back(cv::Point2f(0, 0));
normMarkerCoord2D.push_back(cv::Point2f(s, 0));
normMarkerCoord2D.push_back(cv::Point2f(s, s));
normMarkerCoord2D.push_back(cv::Point2f(0, s));

const float sm = OCV_AR_CONF_MARKER_SIZE_REAL; // size in meters
normMarkerCoord3D.push_back(cv::Point3f(-0.5f * sm, 0.5f * sm, 0.0f));
normMarkerCoord3D.push_back(cv::Point3f( 0.5f * sm, 0.5f * sm, 0.0f));
normMarkerCoord3D.push_back(cv::Point3f( 0.5f * sm, -0.5f * sm, 0.0f));
normMarkerCoord3D.push_back(cv::Point3f(-0.5f * sm, -0.5f * sm, 0.0f));
} else {
normMarkerSize = 0;
}
}

void Detect::prepare(int frameW, int frameH, int frameChan, int cvtType) {
Expand Down Expand Up @@ -113,6 +152,7 @@ void Detect::processFrame() {
performThreshold();
findContours();
findMarkerCandidates();
identifyMarkers();
}

cv::Mat *Detect::getOutputFrame() const {
Expand Down Expand Up @@ -163,7 +203,7 @@ void Detect::findContours() {
// filter out contours consisting of
// less than <minContourPointsAllowed> points
curContours.clear();
for (ContourVec::iterator it = allContours.begin();
for (ContourVec::const_iterator it = allContours.begin();
it != allContours.end();
++it)
{
Expand All @@ -186,7 +226,7 @@ void Detect::findMarkerCandidates() {
possibleMarkers.clear();
PointVec approxCurve;

for (ContourVec::iterator it = curContours.begin();
for (ContourVec::const_iterator it = curContours.begin();
it != curContours.end();
++it)
{
Expand Down Expand Up @@ -217,11 +257,11 @@ void Detect::findMarkerCandidates() {
possibleMarkers.push_back(markerCand);
}

printf("Num. marker candidates: %lu\n", possibleMarkers.size());
printf("ocv_ar::Detect - Num. marker candidates: %lu\n", possibleMarkers.size());

discardDuplicateMarkers(possibleMarkers);

printf("Num. marker candidates without duplicates: %lu\n", possibleMarkers.size());
printf("ocv_ar::Detect - Num. marker candidates without duplicates: %lu\n", possibleMarkers.size());

// draw markers if necessary
if (outFrameProcLvl == POSS_MARKERS) {
Expand All @@ -238,8 +278,61 @@ void Detect::findMarkerCandidates() {
}
}

void Detect::checkMarkerCandidates() {
void Detect::identifyMarkers() {
if (!ident) return;

if (outFrame && outFrameProcLvl == DETECTED_MARKERS) {
// outFrame->setTo(cv::Scalar(0, 0, 0, 255)); // clear: fill black
inFrame->copyTo(*outFrame);
}

foundMarkers.clear();

// normalize (deskew) all possible markers and identify them
for (vector<Marker>::iterator it = possibleMarkers.begin();
it != possibleMarkers.end();
++it)
{
cv::Mat normMarkerImg(normMarkerSize, normMarkerSize, CV_8UC1);

// Find the perspective transformation that brings current marker to
// rectangular form
const cv::Mat perspMat = cv::getPerspectiveTransform(it->getPoints(), normMarkerCoord2D);
cv::warpPerspective(*inFrame, normMarkerImg, perspMat, cv::Size(normMarkerSize, normMarkerSize), cv::INTER_NEAREST);
cv::threshold(normMarkerImg, normMarkerImg, 125, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);

// try to read the marker code
// if this is successfull, it will be saved as the marker's ID
// and the marker's corner points will be correctly rotated
if (ident->readMarkerCode(normMarkerImg, *it)) {
// a valid code could be read -> add this marker to the "found markers"
foundMarkers.push_back(*it);

// refine corners
#if OCV_AR_CONF_REFINE_CORNERS_ITER > 0
cv::cornerSubPix(*inFrame, it->getPoints(),
cv::Size(5, 5), cv::Size(-1,-1),
cv::TermCriteria(CV_TERMCRIT_ITER, OCV_AR_CONF_REFINE_CORNERS_ITER, 0.1f)); // max. iterations, min. epsilon
#endif
// draw marker
if (outFrame && outFrameProcLvl == DETECTED_MARKERS) {
float r = it->getPerimeterRadius();
cv::Point o = it->getCentroid() - (0.5f * cv::Point2f(r, r));
printf("ocv_ar::Detect - drawing marker with id %d at pos %d, %d", it->getId(), o.x, o.y);
cv::Rect roi(o, normMarkerImg.size());
cv::rectangle(*outFrame, roi, cv::Scalar(255,255,255,255));
cv::Mat dstMat = (*outFrame)(roi);
normMarkerImg.copyTo(dstMat);

drawMarker(*outFrame, *it);

// LOGINFO("pers. mat.:");
// for (int i = 0; i < perspMat.rows; i++) {
// LOGINFO("%f\t%f\t%f", perspMat.at<float>(i, 0), perspMat.at<float>(i, 1), perspMat.at<float>(i, 2));
// }
}
}
}
}

void Detect::estimatePositions() {
Expand Down Expand Up @@ -280,17 +373,17 @@ void Detect::discardDuplicateMarkers(vector<Marker> &markerList) {
}
}

int Detect::readMarkerCode(cv::Mat &img, int *validRot) {
return 0;
}

bool Detect::checkMarkerCode(const cv::Mat &m, int dir) const {
return false;
}

int Detect::markerCodeToId(const cv::Mat &m, int dir) const {
return 0;
}
//int Detect::readMarkerCode(cv::Mat &img, int *validRot) {
// return 0;
//}
//
//bool Detect::checkMarkerCode(const cv::Mat &m, int dir) const {
// return false;
//}
//
//int Detect::markerCodeToId(const cv::Mat &m, int dir) const {
// return 0;
//}

void Detect::setOutputFrameOnCurProcLevel(FrameProcLevel curLvl, cv::Mat *srcFrame) {
assert(srcFrame);
Expand All @@ -303,7 +396,7 @@ void Detect::setOutputFrameOnCurProcLevel(FrameProcLevel curLvl, cv::Mat *srcFra
void Detect::drawMarker(cv::Mat &img, const Marker &m) {
// draw outline
Point2fVec markerPts = m.getPoints();
const int numPts = markerPts.size();
const int numPts = (int)markerPts.size();
cv::Scalar white(255, 255, 255, 255);
for (int i = 0; i < numPts; i++) {
cv::line(img, markerPts[i], markerPts[(i + 1) % numPts], white);
Expand Down
26 changes: 19 additions & 7 deletions common/detect.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
#include "conf.h"
#include "types.h"
#include "marker.h"
#include "ident.h"
#include "ident_7bit.h"

using namespace std;

namespace ocv_ar {

class Detect {
public:
Detect();
Detect(IdentificatorType identType);
~Detect();

void prepare(int frameW, int frameH, int frameChan, int cvtType = -1);
Expand All @@ -27,6 +29,10 @@ class Detect {

void setInputFrame(cv::Mat *frame);

void setIdentificator(IdentificatorType identType);

IdentificatorType getIdentificator() const { return ident ? ident->getType() : NONE; }

void processFrame();

cv::Mat *getOutputFrame() const;
Expand All @@ -46,18 +52,18 @@ class Detect {

void findMarkerCandidates();

void checkMarkerCandidates();
void identifyMarkers();

void discardDuplicateMarkers(vector<Marker> &markerList);

void estimatePositions();

void setOutputFrameOnCurProcLevel(FrameProcLevel curLvl, cv::Mat *srcFrame);

int readMarkerCode(cv::Mat &img, int *validRot);

bool checkMarkerCode(const cv::Mat &m, int dir) const;
int markerCodeToId(const cv::Mat &m, int dir) const;
// int readMarkerCode(cv::Mat &img, int *validRot);
//
// bool checkMarkerCode(const cv::Mat &m, int dir) const;
// int markerCodeToId(const cv::Mat &m, int dir) const;

void drawMarker(cv::Mat &img, const Marker &m);

Expand All @@ -78,7 +84,13 @@ class Detect {
int downsampleSizeH;

vector<Marker> possibleMarkers;
vector<Marker> foundMarkers; // maps marker id -> marker object
vector<Marker> foundMarkers;

IdentificatorBase *ident;

int normMarkerSize;
Point2fVec normMarkerCoord2D; // standard coordinates for a normalized rectangular marker in 2D
Point3fVec normMarkerCoord3D; // standard coordinates for a normalized rectangular marker in 3D
};

}
Expand Down
1 change: 1 addition & 0 deletions common/ident.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "ident.h"
35 changes: 35 additions & 0 deletions common/ident.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef OCV_AR_IDENT_H
#define OCV_AR_IDENT_H

#include <opencv2/opencv.hpp>

#include "marker.h"
#include "types.h"

namespace ocv_ar {

class IdentificatorBase {
public:
IdentificatorBase(int markerSize) : reqMarkerSize(markerSize) {};

virtual ~IdentificatorBase() {};

virtual bool readMarkerCode(cv::Mat &area, Marker &marker) = 0;

virtual int getRequiredMarkerSize() const { return reqMarkerSize; }

static IdentificatorType getType() { return type; }

protected:
virtual bool checkMarkerCode(const cv::Mat &m, int dir) const = 0;
virtual int markerCodeToId(const cv::Mat &m, int dir) const = 0;


static IdentificatorType type;

int reqMarkerSize;
};

}

#endif
17 changes: 17 additions & 0 deletions common/ident_7bit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "ident_7bit.h"

using namespace ocv_ar;

IdentificatorType IdentificatorBase::type = CODE_7BIT;

bool Identificator7BitCode::readMarkerCode(cv::Mat &area, Marker &marker) {
return false;
}

bool Identificator7BitCode::checkMarkerCode(const cv::Mat &m, int dir) const {
return false;
}

int Identificator7BitCode::markerCodeToId(const cv::Mat &m, int dir) const {
return 0;
}
26 changes: 26 additions & 0 deletions common/ident_7bit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef OCV_AR_IDENT_7BIT_H
#define OCV_AR_IDENT_7BIT_H

#include <opencv2/opencv.hpp>

#include "marker.h"
#include "types.h"
#include "ident.h"

namespace ocv_ar {

class Identificator7BitCode : public IdentificatorBase {
public:
Identificator7BitCode() : IdentificatorBase(56) {};


virtual bool readMarkerCode(cv::Mat &area, Marker &marker);

protected:
virtual bool checkMarkerCode(const cv::Mat &m, int dir) const;
virtual int markerCodeToId(const cv::Mat &m, int dir) const;
};

}

#endif
7 changes: 7 additions & 0 deletions common/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ namespace ocv_ar {
DETECTED_MARKERS
} FrameProcLevel;

typedef enum _IdentificatorType {
NONE = -1,
CODE_7BIT,
CODE_8BIT,
TEMPLATE
} IdentificatorType;

typedef std::vector<cv::Point> PointVec;
typedef std::vector<cv::Point2f> Point2fVec;
typedef std::vector<cv::Point3f> Point3fVec;
Expand Down
1 change: 1 addition & 0 deletions ocv_ar.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <opencv2/opencv.hpp>

#include "common/conf.h"
#include "common/types.h"
#include "common/detect.h"

#endif

0 comments on commit 66ee8e8

Please sign in to comment.