空草子·如何利用QT和opengl进入幻想乡

  一个优秀的程序员可以赋予人无尽的幻想与深思,也让人们难以抑制从内心深处迸发的感动。
        他们制造着幻想与华鸟风月之美,制造着只有那里才有的误会、和解与真实。
        虚幻的东西反而带给人们真实的五感,恐怕这便是二次元存在的意义吧。
        如果硬要说的话,手机、电脑和程序倒也成了二次元的产物呢。
        每天对着二维屏幕上的十几行代码傻傻发笑的不正是我们自己吗?
        因此,那些批判什么二次元三次元,还总说别人活在自己的世界里的人,倒是应该照照镜子才对。
        更何况,你所看不到的是,在那些碎月与华丽的背后的造幻想之人的痛苦努力。

        我们正视这些幻想,这也是对他人努力成果的一种认可与尊重,难道不是吗?

 好,今天利用QT和opengl和opencv带大家进入幻想乡,确切的说是把幻想乡带到现实中来。我们先上效果

其实是利用opengl与opencv完成增强现实。
        虚拟现实是带人走入虚拟世界,例如3D头盔、立体眼镜等;而增强现实则是把虚幻的东西带到现实中来,就像初音未来的全息演唱会。
        废话说完了,教你怎么做。原文的连接放到这里了。上面只给出了部分代码,经过完善之后被我实现了,还是很有趣的。
        http://blog.csdn.net/WAmani/article/details/52717844
我们先看一下这个类,需要注意的是继承。这里继承的是QGLWidget而不是public QOpenGLWidget,和protected QOpenGLFunctions
在QGLWidget中,initializeOpenGLFunctions()方法是没有的,也不需要。而在QOpenGLWideget中必须要用initializeOpenGLFunctions方法来初始化,paintGL()后面也必须调用update函数来防止卡帧。相比较下,QGLWidget却可以用updateGL();来进行界面刷新。
        这个类中没有使用外部的opengl库函数,全部由opengl内部封装。
#ifndef QSCARLETGLAUGMENTEDREALITY_H
#define QSCARLETGLAUGMENTEDREALITY_H
#include<QOpenGLWidget>
#include<QOpenGLFunctions>
#include<QOpenGLShaderProgram>
#include<QOpenGLBuffer>
#include<QGLWidget>
#include<QPoint>
#include<Eigen/Core>
#include<Eigen/Dense>
#include<QTimer>
#include<vector>
#include<QtOpenGL/QtOpenGL>
#include<opencv.hpp>
using namespace cv;
using namespace std;
//=================绘制增强现实类===============
#define MIN_LENGTH 35
#define IMAGE_WIDTH 640
#define IMAGE_HEIGHT 480
class QScarletGLAugmentedReality :public QGLWidget//,protected QOpenGLFunctions
{
    //================需要注意的是,继承方式的不同会导致代码有很大差别
    Q_OBJECT
public:
    explicit QScarletGLAugmentedReality(QWidget* parent =0);
    ~QScarletGLAugmentedReality();//析构函数
protected:
    //三个重载函数
    void initializeGL();
    void initWidget();
    void paintGL();
    void resizeGL(int ,int );
    void loadGLTextures();//加载纹理
    void mousePressEvent(QMouseEvent *);//鼠标单机事件三态
private:
    //void start();//开始
    //绘制增强现实
    void imageProcess(Mat);
    void initialize_AugmentReality();
    void paint_AugmentReality();
    void resize_AugmentReality(int ,int );

    Mat frame;
    VideoCapture cam,video;
    vector<Point3f> Xworld;
    vector<Point2f> Ximage;
    GLfloat projection_matrix[16];
    vector<GLdouble> rotMatrix;//某一个标记的变换矩阵
    GLdouble rotMat[16];//为了对应opengl函数格式定义的数组
    //GLdouble *rotMatrix = new GLdouble(16);
    vector<vector<GLdouble> >  RotationMatrix;//将所有的变换矩阵保存同一渲染
    Mat cameraMatrix = Mat(3,3,CV_64FC1,1);
    Mat distCoeffs   = Mat(1,4,CV_64FC1,1);
    //opengl
    QTimer clk;
    //GLfloat m_x, m_y, m_z;
    //GLfloat xx;
    float WINDOW_SIZE;
    //float Z_JUST;
    //int WINDOW_SIZE;
    GLuint m_texture[3];
    GLuint texturImage;
    GLuint texturFrame;

    //鼠标响应
    Mat warpMat;
    Point2f dstRect[4];
    Point2f srcRect[4];
    char number;
    Mat dobotPos = Mat(3, 1, CV_64FC1, Scalar(0, 0, 0));
    Mat dobotTargetPos;
    Point2f dobotFinalTargetPos;//归一化后位置

private slots:
    void updateWindow();
    //void updateParams(int);
};

然后我们看一下类的实现。我就只粘贴核心代码了,源码之后会分享给各位。
 void QScarletGLAugmentedReality::updateWindow()
{
    //qDebug()<<"updateWindow";
    //获取摄像头图像并进行格式转换
    cam >> frame;
    //cv::imshow("frame",frame);
    //cv::waitKey();
    cvtColor(frame, frame, CV_BGR2RGB);
    for (char i = 0; i < 4; i++)
    {
        circle(frame, srcRect[i], 8, Scalar(255, 0, 0), -1, 8, 0);
    }
    circle(frame, Point(dobotPos.at<double>(0, 0), dobotPos.at<double>(1, 0)), 5, Scalar(0, 255, 255), -1, 8);
    imageProcess(frame);//这个函数主要是对图像处理,对二维码进行识别。
    QImage buf, tex;
    //将Mat类型转换成QImage
    buf = QImage((const unsigned char*)frame.data, frame.cols, frame.rows, frame.cols * frame.channels(), QImage::Format_RGB888);
    tex = QGLWidget::convertToGLFormat(buf);
    glGenTextures(1, &texturFrame);//对应图片的纹理定义
    glBindTexture(GL_TEXTURE_2D, texturFrame);//进行纹理绑定
    //纹理创建
    glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
        GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    updateGL();
}
当然,这只是很少一部分代码,但是它可以帮我们理清思路。
        首先利用opencv摄像头读取影像,转化为opengl所用的色彩格式,然后进行图像中的二维码识别,进行座标转换,最后用opengl进行绘制。爱我次奥不得不说原文的博主真是忒tm强悍了。顺带说一句,二维码长成这个样子。事实上,opencv3.2的contrib模块中有对这种二维码进行识别的模块。也不是很复杂,主要是结合sovePnp函数进行位姿估计。

附上h文件和cpp文件的源码连接:
http://download.csdn.net/download/qq_30547073/9967390

最后再给大家展示一下本人最新画作。
没错,我想说的是,对某件事物的执着一定可以带给你力量,它可以让你获得忍受一切痛苦与屈辱的能力。
总有一天,你所坚持的事物会像金子一样闪闪发光。
那时你会被称为神明,因为你做到了其他人永远做不到的事情。

发布了41 篇原创文章 · 获赞 62 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章