<Example_MarkerBasedAR>中Marker.cpp的源码与详细中文注释

来源:互联网 发布:80端口开启 编辑:程序博客网 时间:2024/06/01 14:18
/***************************************************************************** *   Marker.cpp *   Example_MarkerBasedAR ****************************************************************************** *   by Khvedchenia Ievgen, 5th Dec 2012 *   http://computer-vision-talks.com ****************************************************************************** *   Ch2 of the book "Mastering OpenCV with Practical Computer Vision Projects" *   Copyright Packt Publishing 2012. *   http://www.packtpub.com/cool-projects-with-opencv/book *****************************************************************************/#include "Marker.hpp"#include "DebugHelpers.hpp"Marker::Marker(): id(-1)// id初始化为-1{}// 重载了‘<’运算符bool operator<(const Marker &M1,const Marker&M2){    return M1.id<M2.id;}// 顺时针旋转标记矩阵cv::Mat Marker::rotate(cv::Mat in){    cv::Mat out;    in.copyTo(out);    for (int i=0;i<in.rows;i++)    {        for (int j=0;j<in.cols;j++)        {            out.at<uchar>(i,j)=in.at<uchar>(in.cols-j-1,i);        }    }    return out;}// 计算标记矩阵的海明距离int Marker::hammDistMarker(cv::Mat bits){    // bits中的每一行,都要与ids中的所有行进行比较    int ids[4][5]=    {        // id的顺序无所谓        {1,0,0,0,0},        {1,0,1,1,1},        {0,1,0,0,1},        {0,1,1,1,0}    };        int dist=0;        // rows    for (int y=0;y<5;y++)    {        int minSum=1e5; // hamming distance to each possible word                for (int p=0;p<4;p++)        {            int sum=0;            // 统计海明距离            // cols            for (int x=0;x<5;x++)            {                sum += (bits.at<uchar>(y,x) == ids[p][x]) ? 0 : 1;            }            // 求bits中第y行与ids中第p行的最小距离            if (minSum>sum)                minSum=sum;        }                // 计算bits中所有行的总距离        dist += minSum;    }        return dist;}// mat转idint Marker::mat2id(const cv::Mat &bits){    int val=0;    for (int y=0;y<5;y++)    {        val<<=1;// val=val<<1        // 只有1和3位是有用的,其他3位(0 2 4)是校验位        if ( bits.at<uchar>(y,1)) val|=1;        val<<=1;        if ( bits.at<uchar>(y,3)) val|=1;    }    return val;}int Marker::getMarkerId(cv::Mat &markerImage,int &nRotations){    assert(markerImage.rows == markerImage.cols);    assert(markerImage.type() == CV_8UC1);        cv::Mat grey = markerImage;        // Threshold image    cv::threshold(grey, grey, 125, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);    #ifdef SHOW_DEBUG_IMAGES    cv::showAndSave("Binary marker", grey);#endif        //Markers  are divided in 7x7 regions, of which the inner 5x5 belongs to marker info    //the external border should be entirely black    // 检测是否是标记的边界    int cellSize = markerImage.rows / 7;        for (int y=0;y<7;y++)    {        int inc=6;                if (y==0 || y==6) inc=1; //for first and last row, check the whole border                for (int x=0;x<7;x+=inc)        {            int cellX = x * cellSize;            int cellY = y * cellSize;            // 在grey矩阵中取ROI矩阵            cv::Mat cell = grey(cv::Rect(cellX,cellY,cellSize,cellSize));                        int nZ = cv::countNonZero(cell);                        if (nZ > (cellSize*cellSize) / 2)            {                return -1;//can not be a marker because the border element is not black!            }        }    }        cv::Mat bitMatrix = cv::Mat::zeros(5,5,CV_8UC1);        //get information(for each inner square, determine if it is  black or white)    // 根据5*5的黑白格子元素来设置bitMatrix矩阵:白色=1 黑色=0    for (int y=0;y<5;y++)    {        for (int x=0;x<5;x++)        {   // 从5*5的第一个格子开始            int cellX = (x+1)*cellSize;            int cellY = (y+1)*cellSize;            // 在grey矩阵中取ROI矩阵            cv::Mat cell = grey(cv::Rect(cellX,cellY,cellSize,cellSize));                        int nZ = cv::countNonZero(cell);            if (nZ> (cellSize*cellSize) /2)                bitMatrix.at<uchar>(y,x) = 1;        }    }        //check all possible rotations    cv::Mat rotations[4];    int distances[4];        rotations[0] = bitMatrix;    distances[0] = hammDistMarker(rotations[0]);    // 将第一个标记的海明距离作为最小距离    // 键值对里存的时 1.最小距离 2.对应标记的索引    std::pair<int,int> minDist(distances[0],0);        for (int i=1; i<4; i++)    {        //get the hamming distance to the nearest possible word        // 将其余的三种旋转可能标记的海明距离与最小距离进行比较ß        rotations[i] = rotate(rotations[i-1]);        distances[i] = hammDistMarker(rotations[i]);        if (distances[i] < minDist.first)        {            minDist.first  = distances[i];            minDist.second = i;        }    }    // 保存识别出的标记的索引    nRotations = minDist.second;    if (minDist.first == 0)    {        return mat2id(rotations[minDist.second]);    }        return -1;}void Marker::drawContour(cv::Mat& image, cv::Scalar color) const{    float thickness = 2;        cv::line(image, points[0], points[1], color, thickness, CV_AA);    cv::line(image, points[1], points[2], color, thickness, CV_AA);    cv::line(image, points[2], points[3], color, thickness, CV_AA);    cv::line(image, points[3], points[0], color, thickness, CV_AA);}


另附上TinyLA.cpp中的相关注释:

bool isInto(cv::Mat &contour, std::vector<cv::Point2f> &b){  for (size_t i=0;i<b.size();i++)  {      // 检查指定的点和指定的多边形的相对位置关系(在多边形内、外、边上或顶点上)      // 返回值:该点和多边形上最近的一条边有符号的距离(>0表示在内部,<0表示在外部,=0表示在边上)      // 当最后一个参数值为0的时候,返回的距离只会是100或-100.      if (cv::pointPolygonTest( contour,b[i],false)>0) return true;  }  return false;}









原创粉丝点击