增强现实代码+注释解析(一)

注释:

1、书名:Mastering OpenCV with Practical Computer Vision Projects

2、章节:Chapter 3:Marker-less Augmented Reality

3、书中源代码的最新更新可以参考网址:https://github.com/MasteringOpenCV/code

 

我想整理一下思路,很想,很想,很想。所以,来排坑吧。233~

增强现实是一个什么样的过程?

  两步走,第一步图像匹配,第二步图像上叠加三维物体。嗯,就是这样。读取一张标记图的关键信息(特征点),通过对摄像头采集的图片进行分析提取,得到实时图片的关键信息(特征点),关键信息进行匹配检测。经过优化处理排除两幅图片之间大小,方向,模糊程度,倾斜角度等的差别,我们就知道了标记图在现实世界中的位置,同时也知道了实时的图片在虚拟世界的位置,于是把虚拟的三维模型数据放在正确的位置,即我们看到了屏幕上目标位置上的虚拟物体。

增强现实实现是怎么做到的?

  我们来结合代码一步一步看吧。

  读入一张标记图;

  

Mat patternImage = imread("33.jpg"); //读入标记图

 

  标记图传入processVideo中;  

processVideo(patternImage, calibration, VideoCapture(0));

   摄像头处理函数,把标记图patternImage传入ARPipeline中;

//摄像头处理的函数声明
void processVideo(const Mat &patternImage, CameraCalibration &calibration, VideoCapture &capture)
{
    ARPipeline pipeline(patternImage, calibration);  //构造对象其实就是把ARPipline中的m_pattern中的图片用他的特征向量把匹配器训练好
}

  在ARPipeline类中,把标记图patternImage建立为模式对象m_pattern;

ARPipeline::ARPipeline(const Mat&patternImage, const CameraCalibration &calibration) :m_calibration(calibration)
{
    m_patternDetector.buildPatternFromImage(patternImage, m_pattern); //用patternImage的数据填充m_pattern的图像对象
    m_patternDetector.train(m_pattern); //开始训练图像
}

  这里可以查看一下模式Pattern的类,Pattern m_pattern,在pattern模式对象中构造了图像的基本信息;

struct Pattern  //模式结构体包含图像的大小关键点,特征描述2d3d点
{
    Size    size;  //大小
    Mat        frame;  //图像
    Mat        grayImg; //灰度图
    vector<KeyPoint>    keypoints; //关键点
    Mat descriptors; //特征向量描述
    vector<Point2f> points2d;  //二维点,即图片的长宽坐标
    vector<Point3f> points3d;  //三维点,即图片的三维坐标
};

  接下来就是通过一些方法对模式对象进行计算;

//从标记图片中填充ARPipline对象中m_pattern的大小图像数据
void PatternDetector::buildPatternFromImage(const Mat &image, Pattern &pattern)const
{
    pattern.size = Size(image.cols, image.rows);  //模式的大小
    pattern.frame = image.clone();
    getGray(image, pattern.grayImg);

    pattern.points2d.resize(4);  //模式点
    pattern.points3d.resize(4);
    const float w = image.cols;      const float h = image.rows;
    const float maxSize = max(w, h);  //计算归一化的图像宽高  
    const float unitW = w / maxSize;
    const float unitH = h / maxSize;

    pattern.points2d[0] = Point2f(0, 0);  //填充m_pattern对象的2d坐标
    pattern.points2d[1] = Point2f(w, 0);
    pattern.points2d[2] = Point2f(w, h);
    pattern.points2d[3] = Point2f(0, h);

    pattern.points3d[0] = Point3f(-unitW, -unitH, 0);  //归一化后的3d坐标
    pattern.points3d[0] = Point3f(unitW, -unitH, 0);
    pattern.points3d[0] = Point3f(unitW, unitH, 0);
    pattern.points3d[0] = Point3f(-unitW, unitH, 0);
    //提取图片的关键点和特征描述
    extractFeatures(pattern.grayImg, pattern.keypoints, pattern.descriptors);
}

  上边引出我们图像处理中的关键步骤,对图像的ORB特征提取和FREAK特征描述,这里没有使用ORB描述算子,为什么;

bool PatternDetector::extractFeatures(const Mat& image, vector<KeyPoint>&keypoints, Mat &descriptors)const
{
    assert(!image.empty());  //如果不为空继续执行
    assert(image.channels() == 1);  //如果通道为1继续执行,通道等于1表示灰度图,减少计算量
    m_detector->detect(image, keypoints);  //提取关键点
    if (keypoints.empty())
        return false;
    m_extractor->compute(image, keypoints, descriptors);  //计算特征向量
    if (descriptors.empty())
        return false;
}

  到这里我们已经可以把标记图即模式对象填充出来了,后面介绍的是面对这些对象我们又需要做什么样的处理。那么,临时定义为第二部分:主要是在PatternDetector类里面设计了特征提取器,特征描述器,特征匹配器。

  匹配优化和单应性计算坐标提取为第三部分吧。分开阐述一下:

 

posted @ 2017-10-25 15:32  Alip  阅读(1420)  评论(0编辑  收藏  举报