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

简介: <Example_MarkerBasedAR>中Marker.cpp的源码与详细中文注释
/*****************************************************************************
 *   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转id
int 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;
}

20170612165847061.gif

目录
相关文章
|
6月前
【latex】参考文献排版前移,在最前面引用\usepackage{url}
【latex】参考文献排版前移,在最前面引用\usepackage{url}
182 0
|
C++
Visual Studio Code 设置 doxygen 格式注释
vs code 使用 cschlosser.doxdocgen 插件,设置 doxygen 注释格式
1009 0
Visual Studio Code 设置 doxygen 格式注释
|
Android开发
eclipse文档注释设置、文件(Files)注释标签、类型(Types)注释标签(类的注释)、字段(Fields)注释标签、构造函数(Constructor)标签
设置注释模板的入口Window->Preference->Java->CodeStyle->CodeTemplate然后展开Comments节点就是所有需设置注释的元素。本文将每一个元素逐一给大家介绍一下。方法(Methods)标签、覆盖方法(Overriding Methods)标签、代理方法(Delegate Methods)标签、getter方法标签、setter方法标签.........
152 1
eclipse文档注释设置、文件(Files)注释标签、类型(Types)注释标签(类的注释)、字段(Fields)注释标签、构造函数(Constructor)标签
|
机器学习/深度学习 Shell Python
[oeasy]python0022_框架标题的制作_banner_结尾字符串_end
[oeasy]python0022_框架标题的制作_banner_结尾字符串_end
110 0
[oeasy]python0022_框架标题的制作_banner_结尾字符串_end
|
JavaScript
js 高级注释(模块注释,class注释,函数注释等)
js 高级注释(模块注释,class注释,函数注释等)
208 0
|
PHP 开发工具 git
VsCode 添加文件头部注释和函数注释[koroFileHeader]
koroFileHeader 在vscode中用于生成文件头部注释和函数注释的插件,经过多版迭代后,插件:支持所有主流语言,灵活方便,文档齐全,食用简单!觉得插件不错的话,就给个Star⭐️吧~ 文件头部添加注释: 在文件开头添加注释,记录文件信息/文件的传参/出参等 支持用户高度自定义注释选项, 适配各种需求和注释。 保存文件的时候,自动更新最后的编辑时间和编辑人 快捷键:window:ctrl+alt+i,mac:ctrl+cmd+i
3379 0
VsCode 添加文件头部注释和函数注释[koroFileHeader]
phpstorm设置文件和函数头部注释
phpstorm设置文件和函数头部注释
359 0
phpstorm设置文件和函数头部注释
|
计算机视觉
Coherence-Enhancing Shock Filters 代码及详细注释【OpenCV】
Coherence-Enhancing Shock Filters 代码及详细注释【OpenCV】
294 0
Coherence-Enhancing Shock Filters 代码及详细注释【OpenCV】
《Example_MarkerBasedAR》中MarkerDetector.cpp源码及详细中文注释
《Example_MarkerBasedAR》中MarkerDetector.cpp源码及详细中文注释
92 0
解决Editor.md通过代码块原样输出Emoji被强制解析问题
Editor.md是一款优秀的开源Markdown 编辑器,在使用中遇到的一些问题和功能改进分享给需要的伙伴。 项目地址 https://github.com/pandao/editor.md 问题 在Editor.md中,如果要输出表情,我们只需要通过代码 :smiley: 就可以输出 。
1549 0