zoukankan      html  css  js  c++  java
  • 增强现实代码+注释解析(一)

    注释:

    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类里面设计了特征提取器,特征描述器,特征匹配器。

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

  • 相关阅读:
    Python configparser模块
    Python OS,shutil模块
    一、操作系统基础
    Python 序列化
    Python 验证码生产程序和进度条程序
    SaltStack 实践课程二 PHP+NGINX
    Android攻城狮数据存储之文件存储
    Android攻城狮数据存储之SQLite数据库简介
    Android攻城狮数据存储之SharedPreferences
    Android攻城狮读取了JSON实现图文混排
  • 原文地址:https://www.cnblogs.com/Alip/p/7677309.html
Copyright © 2011-2022 走看看