由于ZED提供的SDK获取的都是其自己定义的视频格式SVO,不便于进行开发。按导师要求整了一个可编辑的显示框架。
VS2015使用Qt模块不予赘述,参考资料很多。新建工程建Qt工程即可,双击ui进行界面设计就完事儿了。
主界面如图一:
在groundBox中添加了两个GraphicsView,为了实现放大缩小功能需要继承QGraphicsView写一个新类。具体内容参考了以下这篇博客:
https://blog.csdn.net/kunyxu/article/details/78864587
按照以上教程新建好类以后,需要将两个GraphicsView控件提升,注意提升使用的头文件名一定要和新建的类一致。
我在新建MyGraphicsView时在c++的新建类界面选择基类QGraphicsView会提示找不到这个类,但是没关系,继续建,在新建的类中添加头文件即可 #include
由于ZED部分基于OpenCV,Qt控件显示每一帧图像用到QImage类型。因此需要将Mat转为QImage。这部分函数参考了:
https://blog.csdn.net/dong_zhihong/article/details/54583466
只用了博主一个函数
QImage cvMat2QImage(const cv::Mat& mat)
{
// 8-bits unsigned, NO. OF CHANNELS = 1
if(mat.type() == CV_8UC1)
{
QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
// Set the color table (used to translate colour indexes to qRgb values)
image.setColorCount(256);
for(int i = 0; i < 256; i++)
{
image.setColor(i, qRgb(i, i, i));
}
// Copy input Mat
uchar *pSrc = mat.data;
for(int row = 0; row < mat.rows; row ++)
{
uchar *pDest = image.scanLine(row);
memcpy(pDest, pSrc, mat.cols);
pSrc += mat.step;
}
return image;
}
// 8-bits unsigned, NO. OF CHANNELS = 3
else if(mat.type() == CV_8UC3)
{
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return image.rgbSwapped();
}
else if(mat.type() == CV_8UC4)
{
qDebug() << "CV_8UC4";
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
return image.copy();
}
else
{
qDebug() << "ERROR: Mat could not be converted to QImage.";
return QImage();
}
}
附上主窗口程序:
ZED_Video.h
#pragma once
#include
#include "ui_ZED_Video.h"
#include
#include
#include
#include
#include "QTimer"
class ZED_Video : public QMainWindow
{
Q_OBJECT
public:
ZED_Video(QWidget *parent = Q_NULLPTR);
private slots:
void on_btnOpen_clicked();
void on_btnStop_clicked();
void GetFrameFromCamera();
public:
//ZED
sl::Camera zed;
std::string svo_input_path;
sl::InitParameters initParameters;
cv::Mat L_img_cv;
cv::Mat R_img_cv;
sl::Resolution image_size;
int width;
int height;
public:
QImage cvMat2QImage(const cv::Mat& mat);
private:
Ui::ZED_VideoClass ui;
int svo_position = 0;
//static bool exit_app;
bool VideoOpen;
QTimer *timer;
};
ZED_Video.cpp
#include "ZED_Video.h"
#include
#include
#include
#include "utils.hpp"
#include
#include
#include
ZED_Video::ZED_Video(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
timer = new QTimer(this);
VideoOpen = false;
initParameters.camera_resolution = sl::RESOLUTION_HD1080;
initParameters.camera_fps = 60;
initParameters.sdk_verbose = false;
connect(timer, SIGNAL(timeout()), this, SLOT(GetFrameFromCamera()));
connect(ui.btnOpen, SIGNAL(clicked()), this, SLOT(on_btnOpen_clicked()));
connect(ui.btnStop, SIGNAL(clicked()), this, SLOT(on_btnStop_clicked()));//打开摄像头
}
void ZED_Video::on_btnOpen_clicked()
{
//if (!VideoOpen)
//{
// QString curPath = QDir::homePath();//获取系统当前目录
// QString dlgTitle = QString::fromLocal8Bit("选择视频文件"); //对话框标题
// QString filter = QString::fromLocal8Bit("svo文件(*.svo);;所有文件(*.*)"); //文件过滤器,wmv文件(*.wmv);;mp4文件(*.mp4);;所有文件(*.*)
// QString aFile = QFileDialog::getOpenFileName(this, dlgTitle, curPath, filter);
// if (aFile.isEmpty())
// return;
// svo_input_path = aFile.toStdString();
// initParameters.svo_input_filename.set(svo_input_path.c_str());
// initParameters.coordinate_units = sl::UNIT_MILLIMETER;
// // Open the SVO file specified as a parameter
// sl::ERROR_CODE err = zed.open(initParameters);
// if (err != sl::SUCCESS) {
// //std::cout << toString(err) << std::endl;
// sl::String err_str = toString(err);
// QMessageBox::information(NULL, "Error", err_str.c_str(), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
// zed.close();
// return; // Quit if an error occurred
// }
// VideoOpen = true;
//}
//// Get image size
//image_size = zed.getResolution();
//width = image_size.width;
//height = image_size.height;
////width_sbs = image_size.width * 2;
//QString videoPath = QString::fromStdString(svo_input_path);
////ui.LabCurMedia->setText(videoPath);
////获得每一帧图像并显示
//GetFrameFromCamera();
if (VideoOpen)
{
QMessageBox::information(NULL, "Error", "Camera is on", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
return;
}
//timer->killTimer;
sl::ERROR_CODE err = zed.open(initParameters);
if (err != sl::SUCCESS)
{
QMessageBox::information(NULL, "Error", "Camera failed!", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
zed.close();
return;
}
//获取图像大小
width = (int)zed.getResolution().width;
height = (int)zed.getResolution().height;
//获取标定参数
sl::CalibrationParameters calibration_params = zed.getCameraInformation().calibration_parameters;
timer->start(15);
VideoOpen = true;
//GetFrameFromCamera();
}
void ZED_Video::on_btnStop_clicked()
{
timer->stop();//关闭定时器
zed.close();
VideoOpen = false;
return;
}
void ZED_Video::GetFrameFromCamera()
{
//sl::Mat left_image(width, height, sl::MAT_TYPE_8U_C4);
//cv::Mat left_image_ocv = slMat2cvMat(left_image);
//sl::Mat right_image(width, height, sl::MAT_TYPE_8U_C4);
//cv::Mat right_image_ocv = slMat2cvMat(right_image);
////sl::Mat depth_image(width, height, sl::MAT_TYPE_32F_C1);
////cv::Mat depth_image_ocv = slMat2cvMat(depth_image);
//sl::RuntimeParameters rt_param;
//rt_param.sensing_mode = sl::SENSING_MODE_FILL;
//int nb_frames = zed.getSVONumberOfFrames();
//QImage Qt_imgL;
//QImage Qt_imgR;
////SetCtrlHandler();
//while (!exit_app)
//{
// if (zed.grab() == sl::SUCCESS)
// {
// svo_position = zed.getSVOPosition();
// // Retrieve SVO images,get L & R img
// zed.retrieveImage(left_image, sl::VIEW_LEFT);
// zed.retrieveImage(right_image, sl::VIEW_RIGHT);
// //cv::imshow("View", left_image_ocv);
// //cv::waitKey(2);
// //深拷贝?
// L_img_cv = left_image_ocv.clone();
// R_img_cv = right_image_ocv.clone();
// //cv::imshow("View", L_img_cv);
// //cv::waitKey(2);
// Qt_imgL = cvMat2QImage(&L_img_cv);
// Qt_imgR = cvMat2QImage(&R_img_cv);
// ui.graphicsView_L->getResult(Qt_imgL);
// std::ostringstream filename1;
// //filename1 << std::setw(6) << svo_position << ".jpg";
// //std::string fn = filename1.str();
// //QString imgfn = QString::fromStdString(fn);
// //Qt_imgL.save(imgfn, "JPG");
// //ui.graphicsView_L->fitInView(Qt_imgL);
// ui.graphicsView_R->getResult(Qt_imgR);
// //timer->start(15);
// }
// if (svo_position >= (nb_frames - 1))
// { // End of SVO
// qDebug() << "\nSVO end has been reached. Exiting now.\n";
// exit_app = true;
// }
//}
sl::Mat left_image(width, height, sl::MAT_TYPE_8U_C4);
cv::Mat left_image_ocv = slMat2cvMat(left_image);
sl::Mat right_image(width, height, sl::MAT_TYPE_8U_C4);
cv::Mat right_image_ocv = slMat2cvMat(right_image);
QImage Qt_imgL;
QImage Qt_imgR;
if (zed.grab() == sl::SUCCESS)
{
svo_position = zed.getSVOPosition();
// Retrieve SVO images,get L & R img
zed.retrieveImage(left_image, sl::VIEW_LEFT);
zed.retrieveImage(right_image, sl::VIEW_RIGHT);
L_img_cv = left_image_ocv.clone();
R_img_cv = right_image_ocv.clone();
Qt_imgL = cvMat2QImage(L_img_cv);
Qt_imgR = cvMat2QImage(R_img_cv);
ui.graphicsView_L->getResult(Qt_imgL);
ui.graphicsView_R->getResult(Qt_imgR);
//cv::imshow("View", L_img_cv);
//cv::waitKey(2);
}
}
QImage ZED_Video::cvMat2QImage(const cv::Mat& mat)
{
// 8-bits unsigned, NO. OF CHANNELS = 1
if (mat.type() == CV_8UC1)
{
QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
// Set the color table (used to translate colour indexes to qRgb values)
image.setColorCount(256);
for (int i = 0; i < 256; i++)
{
image.setColor(i, qRgb(i, i, i));
}
// Copy input Mat
uchar *pSrc = mat.data;
for (int row = 0; row < mat.rows; row++)
{
uchar *pDest = image.scanLine(row);
memcpy(pDest, pSrc, mat.cols);
pSrc += mat.step;
}
return image;
}
// 8-bits unsigned, NO. OF CHANNELS = 3
else if (mat.type() == CV_8UC3)
{
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return image.rgbSwapped();
}
else if (mat.type() == CV_8UC4)
{
//qDebug() << "CV_8UC4";
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
return image.copy();
}
else
{
qDebug() << "ERROR: Mat could not be converted to QImage.";
return QImage();
}
}
运行测试: