全景影像的3D显示

  全景影像是一种特殊的影像,它有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度的显示功能。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值