概述
全景影像是一种特殊的影像,它有360度的视角,但是在二维平面上观察时,其更像一个“拉开的拉链”,为了更好的显示全景影像,我们需要将其还原到球坐标系下,从而完成其360度的正常显示。
由于工作关系,需要在Qt平台下完成全景影像360度视角显示,经过研究,结合QOpenGLWidget + OpenGL可以实现,这里之所以不使用QGLWidget,是因为该控件已被Qt废弃;其次,Qt平台虽然已经支持了openGL的相关API(QGLFunctions),但是由于发现需要使用的部分API在Qt中找不到(猜测可能是由于OpenGL的版本问题),所以还是使用了Windows系统下的OpenGL,关于这一方面我们不要担心电脑不支持OpenGL(应该不存在Windows系统没有自带OpenGL吧),但是应该考虑到不同电脑下OpenGL版本不同而可能导致兼容性问题。下面贴出我的部分预研代码。
/***********************pro文件*****************************/
#-------------------------------------------------
#
# Project created by QtCreator 2020-12-07T15:26:37
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = 3Ddemo
TEMPLATE = app
LIBS += $$PWD/libs/OpenGL32.lib
$$PWD/libs/glu32.lib
# opencv
include($$PWD/../../LiDARToolkit/libs/opencv/opencv.pri)
INCLUDEPATH += C:/Program Files (x86)/Windows Kits/8.1/Include/um/gl
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES +=
main.cpp
OpenGLWid.cpp
HEADERS +=
OpenGLWid.h
/***********************OpenGLWid.h*****************************/
#ifndef OPENGLWID_H
#define OPENGLWID_H
#include <QOpenGLWidget>
class OpenGLWid : public QOpenGLWidget
{
Q_OBJECT
public:
OpenGLWid(QWidget *parent = nullptr);
private:
void initializeGL() override;
void resizeGL(int w,int h) override;
void paintGL() override;
bool loadJPGToTexture(const char *pszFilename);
void initializeDisplayList();
private:
GLdouble m_ardTranslation[ 3 ];
GLdouble m_ardRotation[ 3 ];
bool m_bNeedUpdate;
unsigned char* m_pBGRUTexture;
};
#endif // OPENGLWID_H
/***********************OpenGLWid.cpp*****************************/
#include "OpenGLWid.h"
#include <gl/GL.h>
#include <gl/GLU.h>
#include <QDebug>
#include <QTimer>
#define _DISPLAY_LIST 1
#define _GRID_SIZE 128
OpenGLWid::OpenGLWid(QWidget *parent)
: QOpenGLWidget(parent)
,m_bNeedUpdate(false)
{
loadJPGToTexture("D:\data\1126\img\2020_1126_080300_871_789.jpg");
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(50); //以10ms为一个计时周期旋转全景
}
void OpenGLWid::initializeGL()
{
m_ardTranslation[ 0 ] = 0.0;
m_ardTranslation[ 1 ] = 0.0;
m_ardTranslation[ 2 ] = 0.0;
m_ardRotation[ 0 ] = -90.0;
m_ardRotation[ 1 ] = 0.0;
m_ardRotation[ 2 ] = 0.0;
::glClearColor( 0.0, 0.0, 0.0, 0.0 );
::glShadeModel( GL_FLAT );
::glTexImage2D(
GL_PROXY_TEXTURE_2D,
0,
GL_RGBA8,
8192,
4096,
0,
GL_BGRA_EXT,
GL_UNSIGNED_BYTE,
NULL );
GLint iWidth;
GLint iHeight;
::glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &iWidth );
::glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &iHeight );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
::glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA8,
8192,
4096,
0,
GL_BGRA_EXT,
GL_UNSIGNED_BYTE,
m_pBGRUTexture );
::glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
::glEnable( GL_TEXTURE_2D );
initializeDisplayList( );
}
void OpenGLWid::resizeGL(int w, int h)
{
int iX = width();
int iY = height();
qDebug() << "ix = " << iX << "iy = " << iY;
GLdouble gldAspect = (GLdouble)iX / (GLdouble)iY;
glMatrixMode( GL_PROJECTION );
::glLoadIdentity();
gluPerspective( 45.0, gldAspect, 0.01, 10 );
glViewport( 0, 0, iX, iY );
}
void OpenGLWid::paintGL()
{
if(m_bNeedUpdate)
{
initializeGL();
m_bNeedUpdate = false;
}
::glClear( GL_COLOR_BUFFER_BIT );
::glMatrixMode( GL_MODELVIEW );
::glLoadIdentity();
::glTranslated(
m_ardTranslation[ 0 ],
m_ardTranslation[ 1 ],
m_ardTranslation[ 2 ] );
::glRotated( m_ardRotation[ 0 ], 1, 0, 0 );
::glRotated( m_ardRotation[ 1 ], 0, 1, 0 );
::glRotated( m_ardRotation[ 2 ], 0, 0, 1 );
m_ardRotation[ 2 ] += 1;
::glCallList( _DISPLAY_LIST );
}
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
bool OpenGLWid::loadJPGToTexture(const char* pszFilename)
{
int m_uiImageCols = 8192;
int m_uiImageRows = 4096;
int m_uiTextureCols =
(unsigned int)(pow(2, ceil(log((double)m_uiImageCols) / log((double)2))));
int m_uiTextureRows =
(unsigned int)(pow(2, ceil(log((double)m_uiImageRows) / log((double)2))));
m_pBGRUTexture = new unsigned char[m_uiTextureCols * m_uiTextureRows * 4];
unsigned char* pDest = m_pBGRUTexture;
unsigned char* pSrc = nullptr;
Mat mat = imread(pszFilename, CV_LOAD_IMAGE_COLOR);
int rows = mat.rows;
int cols = mat.cols;
for (unsigned row = 0; row < m_uiImageRows; row++)
{
pDest = m_pBGRUTexture + (m_uiTextureCols * 4 * row);
pSrc = mat.data + (cols * 3 * row);
for (unsigned col = 0; col < m_uiImageCols; col++)
{
*(pDest + 2) = *(pSrc + 2);
*(pDest + 1) = *(pSrc + 1);
*(pDest + 0) = *(pSrc + 0);
pDest += 4;
pSrc += 3;
}
}
qDebug() << "read finished!";
return true;
}
void
OpenGLWid::initializeDisplayList( )
{
GLUquadricObj* pobj = ::gluNewQuadric();
::gluQuadricDrawStyle( pobj, GLU_FILL);
::gluQuadricOrientation( pobj, GLU_OUTSIDE );
::gluQuadricTexture( pobj, GL_TRUE );
::glNewList( _DISPLAY_LIST, GL_COMPILE );
::glMatrixMode( GL_MODELVIEW );
::glScaled( 1.0, -1.0, -1.0 );
::glMatrixMode( GL_TEXTURE );
::glLoadIdentity();
double dXTexScaling =
(double)( 8192 ) / (double)( 8192 );
double dYTexScaling =
(double)( 4096 ) / (double)( 4096 );
::glScaled( dXTexScaling, dYTexScaling, 1.0 );
::gluSphere( pobj, 5.0, _GRID_SIZE, _GRID_SIZE );
::glEndList();
::gluDeleteQuadric( pobj );
}
/***********************main.cpp*****************************/
#include "mainwindow.h"
#include <QApplication>
#include <OpenGLWid.h>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSurfaceFormat format;
format.setSamples(16);
OpenGLWid window;
window.setFormat(format);
window.resize(1240, 1000);
window.show();
return app.exec();
}
上述代码实现的基本思路是:生成一个球体,然后将全景影像生成的二维纹理映射到球面上,从而完成全景影像的显示,经过测试,可以完美完成全景影像的360度的显示功能。
最后
以上就是粗暴白昼为你收集整理的全景影像的3D显示的全部内容,希望文章能够帮你解决全景影像的3D显示所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复