diff --git a/.gitmodules b/.gitmodules index e0ca717..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "external/mob_gpgpu"] - path = external/mob_gpgpu - url = ../mob_gpgpu/ diff --git a/common/cam.h b/common/cam.h new file mode 100644 index 0000000..e69de29 diff --git a/common/conf.h b/common/conf.h index 811d252..e69de29 100644 --- a/common/conf.h +++ b/common/conf.h @@ -1,31 +0,0 @@ -#ifndef OCV_AR_CONF_H -#define OCV_AR_CONF_H - -#define OCV_AR_CONF_PLATFORM_IOS -//#define #define OCV_AR_CONF_PLATFORM_ANDROID - -/** Downsampling **/ - -// perform cv::pyrDown N times -#define OCV_AR_CONF_DOWNSAMPLE 1 -// or: use cv::resize -//#define OCV_AR_CONF_RESIZE_W 640 -//#define OCV_AR_CONF_RESIZE_H 360 - -#define OCV_AR_CONF_THRESH_BLOCK_SIZE 5 -#define OCV_AR_CONF_THRESH_C 9.0f - -#define OCV_AR_CONF_MIN_CONTOUR_PTS 4 -#define OCV_AR_CONF_MIN_CONTOUR_LENGTH 30.0f -#define OCV_AR_CONF_MAX_DUPLICATE_DIST 2.0f - -#define OCV_AR_CONF_DEFAULT_MARKER_SIZE_REAL 0.05f // "real world" marker size in meters - -#define OCV_AR_CONF_REFINE_CORNERS_ITER 0 - -#define OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD 8 - -#define OCV_AR_CONF_PROJMAT_NEAR_PLANE 0.01f -#define OCV_AR_CONF_PROJMAT_FAR_PLANE 100.0f - -#endif \ No newline at end of file diff --git a/common/core.h b/common/core.h new file mode 100644 index 0000000..e69de29 diff --git a/common/detect.cpp b/common/detect.cpp deleted file mode 100644 index 94cd73f..0000000 --- a/common/detect.cpp +++ /dev/null @@ -1,638 +0,0 @@ -#include "detect.h" - -#include "tools.h" - -using namespace ocv_ar; - -/* BEGIN code from ArUco lib */ - -static float norm( float a, float b, float c ) -{ - return( sqrt( a*a + b*b + c*c ) ); -} - -static float dot( float a1, float a2, float a3, - float b1, float b2, float b3 ) -{ - return( a1 * b1 + a2 * b2 + a3 * b3 ); -} - -static int arParamDecompMat( float source[3][4], float cpara[3][4], float trans[3][4] ) -{ - int r, c; - float Cpara[3][4]; - float rem1, rem2, rem3; - - if ( source[2][3] >= 0 ) - { - for ( r = 0; r < 3; r++ ) - { - for ( c = 0; c < 4; c++ ) - { - Cpara[r][c] = source[r][c]; - } - } - } - else - { - for ( r = 0; r < 3; r++ ) - { - for ( c = 0; c < 4; c++ ) - { - Cpara[r][c] = -(source[r][c]); - } - } - } - - for ( r = 0; r < 3; r++ ) - { - for ( c = 0; c < 4; c++ ) - { - cpara[r][c] = 0.0; - } - } - cpara[2][2] = norm( Cpara[2][0], Cpara[2][1], Cpara[2][2] ); - trans[2][0] = Cpara[2][0] / cpara[2][2]; - trans[2][1] = Cpara[2][1] / cpara[2][2]; - trans[2][2] = Cpara[2][2] / cpara[2][2]; - trans[2][3] = Cpara[2][3] / cpara[2][2]; - - cpara[1][2] = dot( trans[2][0], trans[2][1], trans[2][2], - Cpara[1][0], Cpara[1][1], Cpara[1][2] ); - rem1 = Cpara[1][0] - cpara[1][2] * trans[2][0]; - rem2 = Cpara[1][1] - cpara[1][2] * trans[2][1]; - rem3 = Cpara[1][2] - cpara[1][2] * trans[2][2]; - cpara[1][1] = norm( rem1, rem2, rem3 ); - trans[1][0] = rem1 / cpara[1][1]; - trans[1][1] = rem2 / cpara[1][1]; - trans[1][2] = rem3 / cpara[1][1]; - - cpara[0][2] = dot( trans[2][0], trans[2][1], trans[2][2], - Cpara[0][0], Cpara[0][1], Cpara[0][2] ); - cpara[0][1] = dot( trans[1][0], trans[1][1], trans[1][2], - Cpara[0][0], Cpara[0][1], Cpara[0][2] ); - rem1 = Cpara[0][0] - cpara[0][1]*trans[1][0] - cpara[0][2]*trans[2][0]; - rem2 = Cpara[0][1] - cpara[0][1]*trans[1][1] - cpara[0][2]*trans[2][1]; - rem3 = Cpara[0][2] - cpara[0][1]*trans[1][2] - cpara[0][2]*trans[2][2]; - cpara[0][0] = norm( rem1, rem2, rem3 ); - trans[0][0] = rem1 / cpara[0][0]; - trans[0][1] = rem2 / cpara[0][0]; - trans[0][2] = rem3 / cpara[0][0]; - - trans[1][3] = (Cpara[1][3] - cpara[1][2]*trans[2][3]) / cpara[1][1]; - trans[0][3] = (Cpara[0][3] - cpara[0][1]*trans[1][3] - - cpara[0][2]*trans[2][3]) / cpara[0][0]; - - for ( r = 0; r < 3; r++ ) - { - for ( c = 0; c < 3; c++ ) - { - cpara[r][c] /= cpara[2][2]; - } - } - - return 0; -} -/* END code from ArUco lib */ - - -#pragma mark public methods - -Detect::Detect(IdentificatorType identType, float markerSizeM, bool flip) { - if (markerSizeM <= 0.0f) markerSizeM = OCV_AR_CONF_DEFAULT_MARKER_SIZE_REAL; - - markerScale = markerSizeM; - flipProj = flip; - prepared = false; - inputFrameCvtType = -1; - outFrameProcLvl = DEFAULT; - - memset(projMat, 0, sizeof(float) * 16); - projMatUsedSize = cv::Size(0, 0); - - inFrameOrigGray = NULL; - inFrame = NULL; - procFrame= NULL; - outFrame = NULL; - - inputFrameW = inputFrameH = 0; - 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; -#endif -} - -Detect::~Detect() { - if (inFrameOrigGray) delete inFrameOrigGray; - if (inFrame) delete inFrame; - if (procFrame) delete procFrame; - 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 = markerScale; // 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) { - assert(frameW > 0 && frameH > 0 && (frameChan == 1 || frameChan == 3 || frameChan == 4)); - - inputFrameW = frameW; - inputFrameH = frameH; - - // alloc mem for orig. sized image in grayscale format - if (inFrameOrigGray) delete inFrameOrigGray; - inFrameOrigGray = new cv::Mat(frameH, frameW, CV_8UC1); - - // alloc mem for downsampled images in grayscale format - if (inFrame) { - delete inFrame; - inFrame = NULL; - } - if (procFrame) { - delete procFrame; - procFrame = NULL; - } - -#ifdef OCV_AR_CONF_DOWNSAMPLE - int frac = pow(2, OCV_AR_CONF_DOWNSAMPLE); - downsampleSizeW = frameW / frac; - downsampleSizeH = frameH / frac; -#elif defined(OCV_AR_CONF_RESIZE_W) && defined(OCV_AR_CONF_RESIZE_H) - assert(downsampleSizeW <= frameW && downsampleSizeH <= frameH); -#else -#error Either OCV_AR_CONF_DOWNSAMPLE or OCV_AR_CONF_RESIZE_W/H must be defined. -#endif - - inFrame = new cv::Mat(downsampleSizeH, downsampleSizeW, CV_8UC1); - procFrame = new cv::Mat(downsampleSizeH, downsampleSizeW, CV_8UC1); - - if (cvtType < 0) { // guess color convert type - if (frameChan == 3) { - cvtType = CV_RGB2GRAY; - } else if (frameChan == 4) { - cvtType = CV_RGBA2GRAY; - } - } - - if (frameChan == 1) { - cvtType = -1; // means we don't need to call cv::cvtColor - } - - // set properties - inputFrameCvtType = cvtType; - prepared = true; - - printf("ocv_ar::Detect - prepared for frames: %dx%d (%d channels)\n", frameW, frameH, frameChan); - printf("ocv_ar::Detect - will downscale to: %dx%d\n", downsampleSizeW, downsampleSizeH); -} - -void Detect::setCamIntrinsics(const cv::Mat &cam, const cv::Mat &dist) { - camMat = cam; - distCoeff = dist; // this mat can also be empty -} - -float *Detect::getProjMat(float viewW, float viewH) { - assert(!camMat.empty() && viewW > 0.0f && viewH > 0.0f && prepared); - - if (viewW != projMatUsedSize.width || viewH != projMatUsedSize.height) { - calcProjMat(viewW, viewH); - } - - return projMat; -} - -void Detect::setFrameOutputLevel(FrameProcLevel level) { - assert(prepared); - - if (outFrameProcLvl == level) return; // no change, no op. - - outFrameProcLvl = level; - - int outW, outH; - - outW = inFrame->cols; - outH = inFrame->rows; - - if (outFrame) { - if (outW == outFrame->cols && outH == outFrame->rows) return; // no change in output frame size - - delete outFrame; - } - - outFrame = new cv::Mat(outH, outW, CV_8UC1); - - printf("ocv_ar::Detect - set output frame level: %d (output frame size %dx%d)", level, outW, outH); -} - -void Detect::setInputFrame(cv::Mat *frame) { - assert(prepared && frame); - - if (inputFrameCvtType >= 0) { // convert to grayscale - cv::cvtColor(*frame, *inFrameOrigGray, inputFrameCvtType); - } -} - -void Detect::processFrame() { - preprocess(); - performThreshold(); - findContours(); - findMarkerCandidates(); - identifyMarkers(); - estimatePositions(); -} - -cv::Mat *Detect::getOutputFrame() const { - if (outFrameProcLvl == DEFAULT) return NULL; - - return outFrame; -} - -#pragma mark private methods - -void Detect::preprocess() { -#ifdef OCV_AR_CONF_DOWNSAMPLE - for (int i = 0; i < OCV_AR_CONF_DOWNSAMPLE; i++) { - cv::pyrDown(*inFrameOrigGray, *inFrame); - - inFrameOrigGray = inFrame; - } -#elif defined(OCV_AR_CONF_RESIZE_W) && defined(OCV_AR_CONF_RESIZE_H) - cv::resize(*inFrameOrigGray, *inFrame, cv::Size(OCV_AR_CONF_RESIZE_W, OCV_AR_CONF_RESIZE_H)); -#else -#error Either OCV_AR_CONF_DOWNSAMPLE or OCV_AR_CONF_RESIZE_W/H must be defined. -#endif - - setOutputFrameOnCurProcLevel(PREPROC, inFrame); -} - -void Detect::performThreshold() { - cv::adaptiveThreshold(*inFrame, - *procFrame, - 255, - cv::ADAPTIVE_THRESH_MEAN_C, // ADAPTIVE_THRESH_GAUSSIAN_C - cv::THRESH_BINARY_INV, - OCV_AR_CONF_THRESH_BLOCK_SIZE, - OCV_AR_CONF_THRESH_C); - - setOutputFrameOnCurProcLevel(THRESH, procFrame); -} - -//void Detect::threshPostProc() { -// -//} - -void Detect::findContours() { - // find contours - ContourVec allContours; - cv::findContours(*procFrame, allContours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); // CV_RETR_LIST or CV_RETR_EXTERNAL - - // filter out contours consisting of - // less than points - curContours.clear(); - for (ContourVec::const_iterator it = allContours.begin(); - it != allContours.end(); - ++it) - { - if (it->size() >= OCV_AR_CONF_MIN_CONTOUR_PTS) { - curContours.push_back(*it); - } - } - - // draw contours if necessary - if (outFrameProcLvl == CONTOURS) { - // LOGINFO("Num. contours: %d", curContours.size()); - outFrame->setTo(cv::Scalar(0, 0, 0, 255)); // clear: fill black - cv::drawContours(*outFrame, curContours, -1, cv::Scalar(255, 255, 255, 255)); - } -} - -void Detect::findMarkerCandidates() { - const float minContourLengthAllowed = OCV_AR_CONF_MIN_CONTOUR_LENGTH * OCV_AR_CONF_MIN_CONTOUR_LENGTH; - - foundMarkers.clear(); - possibleMarkers.clear(); - PointVec approxCurve; - - for (ContourVec::const_iterator it = curContours.begin(); - it != curContours.end(); - ++it) - { - PointVec contour = *it; - // Approximate to a polygon - float eps = contour.size() * 0.05f; - cv::approxPolyDP(contour, approxCurve, eps, true); - - // We interested only in polygons that contains only four points - if (approxCurve.size() != 4 || !cv::isContourConvex(approxCurve)) continue; - - // Ensure that the distance between consecutive points is large enough - float minDist = numeric_limits::max(); - for (int i = 0; i < 4; i++) { - cv::Point side = approxCurve[i] - approxCurve[(i+1)%4]; - float squaredSideLength = side.dot(side); - minDist = min(minDist, squaredSideLength); - } - - if (minDist < minContourLengthAllowed) continue; - - // Create new marker candidate - // Fill it with the points of the curve - // The Marker constructor will also sort the points in anti-clockwise order - Marker markerCand(approxCurve); - - // Add the marker candidate - possibleMarkers.push_back(markerCand); - } - -// printf("ocv_ar::Detect - Num. marker candidates: %lu\n", possibleMarkers.size()); - - discardDuplicateMarkers(possibleMarkers); - -// printf("ocv_ar::Detect - Num. marker candidates without duplicates: %lu\n", possibleMarkers.size()); - - // draw markers if necessary - if (outFrameProcLvl == POSS_MARKERS) { - procFrame->copyTo(*outFrame); - // outFrame->setTo(cv::Scalar(0, 0, 0, 255)); // clear: fill black - - // draw each marker candidate - for (vector::iterator it = possibleMarkers.begin(); - it != possibleMarkers.end(); - ++it) - { - drawMarker(*outFrame, *it); - } - } -} - -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(); // this is done in findMarkerCandidates() - - // normalize (deskew) all possible markers and identify them - for (vector::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)); - -// printf("ocv_ar::Detect - found valid marker with id %d\n", it->getId()); - - // 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\n", 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(i, 0), perspMat.at(i, 1), perspMat.at(i, 2)); - // } - } - } - } -} - -void Detect::estimatePositions() { - for (vector::iterator it = foundMarkers.begin(); it != foundMarkers.end(); ++it) { - Marker *marker = *it; - - cv::Mat rVec; - cv::Mat tVec; - cv::solvePnP(normMarkerCoord3D, marker->getPoints(), - camMat, distCoeff, - rVec, tVec, - false); - - marker->updatePoseMat(rVec, tVec); - } -} - -void Detect::discardDuplicateMarkers(vector &markerList) { - const float maxDuplDistSquared = OCV_AR_CONF_MAX_DUPLICATE_DIST * OCV_AR_CONF_MAX_DUPLICATE_DIST; - - vector::iterator toDel = markerList.end(); // iterator for elem. that will be removed - for (vector::iterator cur = markerList.begin(); - cur != markerList.end();) - { - for (vector::iterator other = markerList.begin(); - other != markerList.end(); - ++other) - { - if (cur == other) continue; - - const float dist = Tools::distSquared(cur->getCentroid(), other->getCentroid()); - - // mark for deletion if the distance is close and the current marker is bigger - if (dist <= maxDuplDistSquared && cur->getPerimeterRadius() < other->getPerimeterRadius()) { -// printf("ocv_ar::Detect - will remove duplicate! dist = %f, r1 = %f, r2 = %f \n", -// dist, cur->getPerimeterRadius(), other->getPerimeterRadius()); - - toDel = cur; - break; - } - } - - if (toDel != markerList.end()) { - cur = markerList.erase(toDel); // advances the iterator - toDel = markerList.end(); // reset - } else { - ++cur; - } - } -} - -void Detect::setOutputFrameOnCurProcLevel(FrameProcLevel curLvl, cv::Mat *srcFrame) { - assert(srcFrame); - - if (curLvl == outFrameProcLvl) { - srcFrame->copyTo(*outFrame); - } -} - -void Detect::drawMarker(cv::Mat &img, const Marker &m) { - // draw outline - Point2fVec markerPts = m.getPoints(); - 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); - } - - // draw centroid - cv::Scalar green(0, 255, 0, 255); - cv::Point cross1(2, 2); - cv::Point cross2(2, -2); - cv::Point c = m.getCentroid(); - cv::line(img, c - cross1, c + cross1, green); - cv::line(img, c + cross2, c - cross2, green); - - // draw perimeter - cv::Scalar blue(0, 0, 255, 255); - cv::circle(img, c, m.getPerimeterRadius(), blue); -} - -void Detect::calcProjMat(float viewW, float viewH) { - printf("ocv_ar::Detect - calculating projection matrix for view size %dx%d\n", - (int)viewW, (int)viewH); - - const float projNear = OCV_AR_CONF_PROJMAT_NEAR_PLANE; - const float projFar = OCV_AR_CONF_PROJMAT_FAR_PLANE; - - projMatUsedSize = cv::Size(viewW, viewH); - - // intrinsics mat contains doubles. we need floats - cv::Mat intrFloats(3, 3, CV_32F); - camMat.convertTo(intrFloats, CV_32F); - - // get cam parameters - /* BEGIN modified code from ArUco lib */ - const float Ax = viewW / (float)downsampleSizeW; - const float Ay = viewH / (float)downsampleSizeH; - const float f_x = intrFloats.at(0, 0) * Ax; // Focal length in x axis - const float f_y = intrFloats.at(1, 1) * Ay; // Focal length in y axis - const float c_x = intrFloats.at(0, 2) * Ax; // Camera primary point x - const float c_y = intrFloats.at(1, 2) * Ay; // Camera primary point y - - float cparam[3][4] = - { - {f_x, 0, c_x, 0}, - { 0, f_y, c_y, 0}, - { 0, 0, 1, 0} - }; - - cparam[0][2] *= -1.0; - cparam[1][2] *= -1.0; - cparam[2][2] *= -1.0; - - float icpara[3][4]; - float trans[3][4]; - float p[3][3], q[4][4]; - - arParamDecompMat(cparam, icpara, trans); - - for (int i = 0; i < 3; i++ ) - { - for (int j = 0; j < 3; j++ ) - { - p[i][j] = icpara[i][j] / icpara[2][2]; - } - } - - q[0][0] = (2.0 * p[0][0] / viewW); - q[0][1] = (2.0 * p[0][1] / viewW); - q[0][2] = ((2.0 * p[0][2] / viewW) - 1.0); - q[0][3] = 0.0; - - q[1][0] = 0.0; - q[1][1] = (2.0 * p[1][1] / viewH); - q[1][2] = ((2.0 * p[1][2] / viewH) - 1.0); - q[1][3] = 0.0; - - q[2][0] = 0.0; - q[2][1] = 0.0; - q[2][2] = (projFar + projNear)/(projFar - projNear); - q[2][3] = -2.0 * projFar * projNear / (projFar - projNear); - - q[3][0] = 0.0; - q[3][1] = 0.0; - q[3][2] = 1.0; - q[3][3] = 0.0; - - for (int i = 0; i < 4; i++ ) - { - for (int j = 0; j < 3; j++ ) - { - projMat[i+j*4] = q[i][0] * trans[0][j] - + q[i][1] * trans[1][j] - + q[i][2] * trans[2][j]; - } - projMat[i+3*4] = q[i][0] * trans[0][3] - + q[i][1] * trans[1][3] - + q[i][2] * trans[2][3] - + q[i][3]; - } - - if (flipProj) - { -// projMat[13] = -projMat[13]; -// projMat[1] = -projMat[1]; -// projMat[5] = -projMat[5]; -// projMat[9] = -projMat[9]; - - projMat[0] = -projMat[0]; - projMat[4] = -projMat[4]; - projMat[8] = -projMat[8]; - projMat[12] = -projMat[12]; - } - - -} \ No newline at end of file diff --git a/common/detect.h b/common/detect.h index f47221e..e69de29 100644 --- a/common/detect.h +++ b/common/detect.h @@ -1,111 +0,0 @@ -#ifndef OCV_AR_DETECT_H -#define OCV_AR_DETECT_H - -#include -#include - -#include - -#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(IdentificatorType identType, float markerSizeM = 0.0f, bool flip = false); - ~Detect(); - - void prepare(int frameW, int frameH, int frameChan, int cvtType = -1); - - void setCamIntrinsics(const cv::Mat &camMat, const cv::Mat &distCoeff); - - void setFrameOutputLevel(FrameProcLevel level); - - void setInputFrame(cv::Mat *frame); - - void setIdentificator(IdentificatorType identType); - - IdentificatorType getIdentificator() const { return ident ? ident->getType() : NONE; } - - void processFrame(); - - cv::Mat *getOutputFrame() const; - - vector getMarkers() const { return foundMarkers; } - - float *getProjMat(float viewW, float viewH); - - float getMarkerScale() const { return markerScale; } - - bool isPrepared() const { return prepared; } - -private: - void preprocess(); - - void performThreshold(); - -// void threshPostProc(); - - void findContours(); - - void findMarkerCandidates(); - - void identifyMarkers(); - - void discardDuplicateMarkers(vector &markerList); - - void estimatePositions(); - - void setOutputFrameOnCurProcLevel(FrameProcLevel curLvl, cv::Mat *srcFrame); - - void drawMarker(cv::Mat &img, const Marker &m); - - void calcProjMat(float viewW, float viewH); - - - bool prepared; - - int inputFrameCvtType; - - FrameProcLevel outFrameProcLvl; - - cv::Mat *inFrameOrigGray; // input frame with original size, grayscale - cv::Mat *inFrame; // input frame downsampled, grayscale - cv::Mat *procFrame; // temporary frame during processing, grayscale/binary - cv::Mat *outFrame; // output frame for debugging, grayscale - - ContourVec curContours; - - int inputFrameW; - int inputFrameH; - int downsampleSizeW; - int downsampleSizeH; - - vector possibleMarkers; - vector foundMarkers; // holds pointers to correct markers in - - 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 - - cv::Mat camMat; - cv::Mat distCoeff; - - float markerScale; - - bool flipProj; - float projMat[16]; - cv::Size projMatUsedSize; -}; - -} - -#endif \ No newline at end of file diff --git a/common/ident.cpp b/common/ident.cpp deleted file mode 100644 index 8c0e71a..0000000 --- a/common/ident.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "ident.h" diff --git a/common/ident.h b/common/ident.h deleted file mode 100644 index f24dd16..0000000 --- a/common/ident.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef OCV_AR_IDENT_H -#define OCV_AR_IDENT_H - -#include - -#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 diff --git a/common/ident_7bit.cpp b/common/ident_7bit.cpp deleted file mode 100644 index 3c7486b..0000000 --- a/common/ident_7bit.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "ident_7bit.h" - -using namespace ocv_ar; - -static unsigned char possibleBitcodes[4][5] = { - { 1,0,0,0,0 }, - { 1,0,1,1,1 }, - { 0,1,0,0,1 }, - { 0,1,1,1,0 } -}; - -IdentificatorType IdentificatorBase::type = CODE_7BIT; - -bool Identificator7BitCode::readMarkerCode(cv::Mat &area, Marker &marker) { - // bitMatrix will contain the read marker code raw bits - cv::Mat bitMatrix = cv::Mat::zeros(5, 5, CV_8UC1); // 5 because in the 7 bit marker, 1 bit on each side must be 0 - - // for each marker cell, count the number of "ones" (white pixels) - // and check if we can alread dismiss the marker (border cell is mainly white) - // or otherwise set the according bitmatrix bit - for (int y = 0; y < 7; y++) { - for (int x = 0; x < 7; x++) { - int cellX = x * markerCellSize; - int cellY = y * markerCellSize; - cv::Mat cell = area(cv::Rect(cellX, cellY, markerCellSize, markerCellSize)); - - int nonZ = cv::countNonZero(cell); - - // Check number of non zero pixels - if (nonZ > minSetMarkerPixels) { - if (y == 0 || y == 6 || x == 0 || x == 6) { // border must be black! - return false; - } else { // set to "1" for this cell - bitMatrix.at(x - 1, y - 1) = 1; - } - } - } - } - - // create transposed bit matrix for rotations - cv::Mat bitMatrixT; - cv::transpose(bitMatrix, bitMatrixT); - - cv::Mat *curBitMat; // a pointer to either bitMatrix or bitMatrixT - - // check marker code for all possible 4 rotations - for (int rot = 0; rot < 4; rot++) { - int dir = -2 * (rot % 2) + 1; // dir is -1 or 1 - if (rot < 2) { - curBitMat = &bitMatrix; - } else { - curBitMat = &bitMatrixT; - } - - if (checkMarkerCode(*curBitMat, dir)) { // found a valid marker code! - // set the Id and rotate the corner points - marker.setId(markerCodeToId(*curBitMat, dir)); - marker.rotatePoints(rot); - - return true; - } - } - - return false; -} - -bool Identificator7BitCode::checkMarkerCode(const cv::Mat &m, int dir) const { - // set start index depending on reading direction - int start = (dir > 0) ? 0 : m.cols - 1; - - // go through all bitcode rows in the read matrix - for (int r = 0; r < m.rows; r++) { - // select read code row - const unsigned char *readCode = m.ptr(r); - - bool foundCode = false; - - // go through all possible bitcodes - const int numPossibleCodes = sizeof(possibleBitcodes) / sizeof(possibleBitcodes[0]); - for (int p = 0; p < numPossibleCodes; p++) { - // select possible code row - const unsigned char *testCode = possibleBitcodes[p]; - - // go through all bits in the row depending on direction - bool nextBit = true; - bool invalidBit = false; - int i = start; - int j = 0; - while (nextBit) { - if (readCode[i] != testCode[j]) { // invalid bit found! - invalidBit = true; - break; - } - - i += dir; - if (dir > 0) { - j = i; - nextBit = (i < m.cols); - } else { - j = start - i; - nextBit = (i > 0); - } - } - - if (!invalidBit) { // this bitcode row is valid! - foundCode = true; // so check the next row - break; - } - } - - if (!foundCode) { - return false; - } - } - - return true; - -} - -int Identificator7BitCode::markerCodeToId(const cv::Mat &m, int dir) const { - int id = 0; - - // set start index depending on reading direction - int start = (dir > 0) ? 0 : m.cols - 1; - - // go through all bitcode rows in the read matrix - int r = start; - unsigned char u, v; - bool nextRow = true; - while (nextRow) { - // cv::Mat row = m.row(r); - // if (dir < 0) { - // cv::flip(row, row, 1); // flip around because we read it in reverse order - // } - const unsigned char *row = m.ptr(r); - - if (dir > 0) { - u = row[1]; - v = row[3]; - } else { // reverse order - u = row[3]; - v = row[1]; - } - - // code from ARuCo: - id <<= 1; - if (u) id |= 1; - id <<= 1; - if (v) id |= 1; - - // next row - r += dir; - nextRow = (dir > 0) ? (r < m.cols) : (r > 0); - } - - return id; -} \ No newline at end of file diff --git a/common/ident_7bit.h b/common/ident_7bit.h deleted file mode 100644 index 2cce440..0000000 --- a/common/ident_7bit.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef OCV_AR_IDENT_7BIT_H -#define OCV_AR_IDENT_7BIT_H - -#include - -#include "marker.h" -#include "types.h" -#include "ident.h" - -namespace ocv_ar { - -class Identificator7BitCode : public IdentificatorBase { -public: - Identificator7BitCode() : IdentificatorBase(7 * OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD), - markerCellSize(OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD), - minSetMarkerPixels(OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD * OCV_AR_CONF_MARKER_CODE_PX_PER_FIELD / 2) - {}; - - - 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; - -private: - int markerCellSize; - int minSetMarkerPixels; -}; - -} - -#endif \ No newline at end of file diff --git a/common/marker.cpp b/common/marker.cpp deleted file mode 100644 index 0b528a5..0000000 --- a/common/marker.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "marker.h" - -using namespace ocv_ar; - -#pragma mark public methods - -Marker::Marker(PointVec &pts) { - for (int i = 0; i < 4; i++) { - points.push_back(cv::Point2f(pts[i].x, pts[i].y)); - } - - init(); -} - - -Marker::Marker(Point2fVec &pts) { - points.assign(pts.begin(), pts.begin() + 4); - - init(); -} - -void Marker::rotatePoints(int rot) { - rotate(points.begin(), points.begin() + 4 - rot, points.end()); -} - -void Marker::updatePoseMat(const cv::Mat &r, const cv::Mat &t) { - cv::Mat cvPoseMat; - cvPoseMat.create(4, 4, CV_32F); - cvPoseMat.eye(4, 4, CV_32F); - - // r and t are double vectors from solvePnP - // convert them! - r.convertTo(rVec, CV_32F); - t.convertTo(tVec, CV_32F); - - cv::Mat rotMat(3, 3, CV_32FC1); - cv::Rodrigues(rVec, rotMat); - - /* BEGIN modified code from ArUco lib */ - float para[3][4]; - for (int i=0; i < 3; i++) { - float *rotMatRow = rotMat.ptr(i); - for (int j = 0; j < 3; j++) { - para[i][j] = rotMatRow[j]; - } - } - //now, add the translation - float *tVecData = tVec.ptr(0); - para[0][3] = tVecData[0]; - para[1][3] = tVecData[1]; - para[2][3] = tVecData[2]; - - // create and init modelview_matrix - memset(poseMat, 0, 16 * sizeof(float)); // init with zeros - - for (int i = 0; i < 3; i++) { - float sign = (i != 2) ? 1.0f : -1.0f; - for (int j = 0; j < 4; j++) { - poseMat[i + j * 4] = sign * para[i][j]; - } - } - - poseMat[15] = 1.0f; - /* END modified code from ArUco lib */ -} - -void Marker::sortPoints() { - // Sort the points in anti-clockwise order - cv::Point v1 = points[1] - points[0]; - cv::Point v2 = points[2] - points[0]; - - // if the third point is in the left side, - // sort in anti-clockwise order - if ((v1.x * v2.y) - (v1.y * v2.x) < 0.0) { - swap(points[1], points[3]); - } -} - -void Marker::calcShapeProperties() { - centroid = 0.25f * (points[0] + points[1] + points[2] + points[3]); - float maxDist = numeric_limits::min(); - for (Point2fVec::iterator it = points.begin(); - it != points.end(); - ++it) - { - float d = cv::norm(centroid - *it); - maxDist = max(maxDist, d); - } - - perimeterRad = maxDist; -} - -#pragma mark private methods - -void Marker::init() { - id = -1; - - rVec.create(3, 1, CV_32F); - tVec.create(3, 1, CV_32F); - - sortPoints(); - calcShapeProperties(); -} \ No newline at end of file diff --git a/common/marker.h b/common/marker.h index 500ac88..e69de29 100644 --- a/common/marker.h +++ b/common/marker.h @@ -1,63 +0,0 @@ -#ifndef OCV_AR_MARKER_H -#define OCV_AR_MARKER_H - -#include - -#include - -#include "conf.h" -#include "types.h" -#include "marker.h" - -using namespace std; - -namespace ocv_ar { - -class Marker { -public: - Marker(PointVec &pts); - Marker(Point2fVec &pts); - - void setId(int newId) { id = newId; }; - int getId() const { return id; }; - - Point2fVec getPoints() const { return points; } - void addPoint(cv::Point2f p) { points.push_back(p); } - void clearPoints() { points.clear(); } - void rotatePoints(int rot); - - cv::Point2f getCentroid() const { return centroid; } - float getPerimeterRadius() const { return perimeterRad; } - - const cv::Mat &getRVec() const { return rVec; }; - const cv::Mat &getTVec() const { return tVec; }; - - void updatePoseMat(const cv::Mat &r, const cv::Mat &t); - -// const glm::mat4 &getPoseMat() const { return poseMat; }; - - const float *getPoseMatPtr() const { return poseMat; }; - - void sortPoints(); - void calcShapeProperties(); - -private: - void init(); - - int id; - - Point2fVec points; - - cv::Point2f centroid; - float perimeterRad; - - cv::Mat rVec; - cv::Mat tVec; - - float poseMat[16]; // 4x4 matrix with model-view-transformation -// glm::mat4 poseMat; // 4x4 matrix with model-view-transformation -}; - -} - -#endif \ No newline at end of file diff --git a/common/tools.cpp b/common/tools.cpp deleted file mode 100644 index 0781793..0000000 --- a/common/tools.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "tools.h" - -using namespace ocv_ar; - -float Tools::distSquared(cv::Point2f p1, cv::Point2f p2) { - const float dX = p1.x - p2.x; - const float dY = p1.y - p2.y; - - return dX * dX + dY * dY; -} \ No newline at end of file diff --git a/common/tools.h b/common/tools.h deleted file mode 100644 index 77cd6cb..0000000 --- a/common/tools.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef OCV_AR_TOOLS_H -#define OCV_AR_TOOLS_H - -#include - -namespace ocv_ar { - -class Tools { -public: - static float distSquared(cv::Point2f p1, cv::Point2f p2); -}; - -} - -#endif \ No newline at end of file diff --git a/common/types.h b/common/types.h deleted file mode 100644 index 1145e93..0000000 --- a/common/types.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef OCV_AR_TYPES_H -#define OCV_AR_TYPES_H - -#include - -#include - -namespace ocv_ar { - typedef enum _FrameProcLevel { - DEFAULT = -1, - PREPROC, - THRESH, - CONTOURS, - POSS_MARKERS, // possible marker candidates - DETECTED_MARKERS - } FrameProcLevel; - - typedef enum _IdentificatorType { - NONE = -1, - CODE_7BIT, - CODE_8BIT, - TEMPLATE - } IdentificatorType; - - typedef std::vector PointVec; - typedef std::vector Point2fVec; - typedef std::vector Point3fVec; - typedef std::vector ContourVec; -} - -#endif \ No newline at end of file diff --git a/external/mob_gpgpu b/external/mob_gpgpu deleted file mode 160000 index ce48836..0000000 --- a/external/mob_gpgpu +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ce48836328fd809926ce868346322a11cfdff195 diff --git a/ocv_ar.h b/ocv_ar.h index fa17965..e69de29 100644 --- a/ocv_ar.h +++ b/ocv_ar.h @@ -1,10 +0,0 @@ -#ifndef OCV_AR -#define OCV_AR - -#include - -#include "common/conf.h" -#include "common/types.h" -#include "common/detect.h" - -#endif \ No newline at end of file