本文是在上一篇文章乐视三合一体感摄像头Astra pro开发记录1(深度图、彩色图及点云简单显示)的基础上写的。在开学之前终于把界面的基础功能做完了,估计还有一些bug,也没时间继续调了。开学之后得憋论文了。
界面的主要功能还是Astra pro相机的彩色图、深度图以及点云显示。在之前的基础上,完善了一些比如图像和点云的保存、读取,相机的打开、关闭以及参数设置等功能。由于只是追求基本功能的实现,整个项目文件代码量算上注释也就一千行左右。依赖的第三方库有OpenCV(图像处理)、OpenNI(深度图)、PCL(点云处理)和VTK(点云显示),下面放代码:

/***@file camera_settings.h*@brief 相机设置头文件*/#ifndef CAMERA_SETTINGS_H
#define CAMERA_SETTINGS_H#include <QDialog>
#include <QString>namespace Ui {class Camera_Settings;
}/*** @brief The Camera_Settings class*/
class Camera_Settings : public QDialog
{Q_OBJECTpublic:Camera_Settings(QWidget *parent = 0);~Camera_Settings();/*** @brief color_index 彩色摄像头编号*/static int color_index;/*** @brief color_resolution 彩色摄像头分辨率*/static QString color_resolution;/*** @brief color_fps 彩色摄像头帧率*/static QString color_fps;/*** @brief depth_resolution 深度摄像头分辨率*/static QString depth_resolution;/*** @brief depth_fps 深度摄像头帧率*/static QString depth_fps;/*** @brief flag_applied 相机设置应用标志*/static bool flag_applied;private slots:/*** @brief on_pushButton_apply_clicked 应用相机设置*/void on_pushButton_apply_clicked();private:Ui::Camera_Settings *ui;
};#endif // CAMERA_SETTINGS_H
/***@file cloud_generate.h*@brief 点云生成头文件*/#ifndef CLOUD_GENERATE_H
#define CLOUD_GENERATE_H#include "mainwindow.h"/*** @brief The Cloud_Generate class*/
class Cloud_Generate : public QThread
{private:/*** @brief run 重写QThread的run方法*/void run();
};#endif // CLOUD_GENERATE_H
/***@file mainwindow.h*@brief 主窗口头文件*/#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QVTKWidget.h>
#include <QMessageBox>
#include <QAbstractButton>
#include <QTimer>
#include <QThread>
#include <QString>
#include <QFileDialog>#include <iostream>
#include <opencv2/opencv.hpp>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <OpenNI.h>
#include <vtkAutoInit.h>
#include <vtkRenderWindow.h>#include "blockingconcurrentqueue.h"
#include "camera_settings.h"
#include "cloud_generate.h"VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
typedef pcl::PointCloud<pcl::PointXYZRGB> PointCloudRGB;QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
using namespace moodycamel;
QT_END_NAMESPACE/*** @brief The Astra class*/
class Astra : public QMainWindow
{Q_OBJECTpublic:explicit Astra(QWidget *parent = 0);~Astra();Ui::MainWindow *ui;private slots:/*** @brief save_color_image 保存彩色图*/void save_color_image();/*** @brief save_depth_image 保存深度图*/void save_depth_image();/*** @brief save_point_cloud 保存点云*/void save_point_cloud();/*** @brief open_color_image 打开彩色图*/void open_color_image();/*** @brief open_depth_image 打开深度图*/void open_depth_image();/*** @brief open_point_cloud 打开点云*/void open_point_cloud();/*** @brief close_all 关闭所有文件*/void close_all();/*** @brief open_camera 打开相机*/void open_camera();/*** @brief close_camera 关闭相机*/void close_camera();//void set_camera();/*** @brief show_color_image 显示彩色图*/void show_color_image();/*** @brief show_depth_image 显示深度图*/void show_depth_image();/*** @brief show_point_cloud 显示点云*/void show_point_cloud();/*** @brief help_guide 使用说明*/void help_guide();/*** @brief help_about 关于AstraGUI*/void help_about();private:/*** @brief camera_settings 相机设置界面类指针*/Camera_Settings *camera_settings;/*** @brief capture 彩色摄像头*/cv::VideoCapture capture;/*** @brief device 深度摄像头*/openni::Device device;/*** @brief depthStream 深度流*/openni::VideoStream depthStream;/*** @brief depthMode 深度模式*/openni::VideoMode depthMode;/*** @brief viewer pclviewer窗口*/boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;/*** @brief timerColor 彩色图像显示定时器*/QTimer *timerColor;/*** @brief timerDepth 深度图像显示定时器*/QTimer *timerDepth;/*** @brief timerCloud 点云显示定时器*/QTimer *timerCloud;/*** @brief colorMat 彩色图像*/cv::Mat colorMat;/*** @brief depthMat 深度图像*/cv::Mat depthMat;/*** @brief flag_depth 深度图采集标志*/bool flag_depth = false;/*** @brief flag_cloud 点云生成标志*/bool flag_cloud =false;
};#endif // MAINWINDOW_H
/***@file camera_settings.cpp*@brief 相机设置源文件*/#include "camera_settings.h"
#include "mainwindow.h"
#include "ui_camera_settings.h"
#include "ui_mainwindow.h"
#include <QDebug>int Camera_Settings::color_index = 0;
QString Camera_Settings::color_resolution = "640*480";
QString Camera_Settings::color_fps= "30fps";
QString Camera_Settings::depth_resolution = "640*480";
QString Camera_Settings::depth_fps = "30fps";
bool Camera_Settings::flag_applied = false;Camera_Settings::Camera_Settings(QWidget *parent) :QDialog(parent),ui(new Ui::Camera_Settings)
{ui->setupUi(this);
}Camera_Settings::~Camera_Settings()
{delete ui;
}void Camera_Settings::on_pushButton_apply_clicked()
{Astra *ptr = (Astra*)parentWidget(); //指向父窗口的指针color_index = ui->comboBox_color_index->currentIndex();color_resolution = ui->comboBox_color_resolution->currentText();depth_resolution = ui->comboBox_depth_resolution->currentText();if(color_resolution=="640*480" && depth_resolution=="640*480"){ptr->ui->stackedWidget->setCurrentIndex(0);}else if(color_resolution=="320*240" && depth_resolution=="320*240"){ptr->ui->stackedWidget->setCurrentIndex(1);}else if(color_resolution == "1280*720"){ptr->ui->stackedWidget->setCurrentIndex(2);}else{QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("分辨率设置错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}color_fps = ui->comboBox_color_fps->currentText();depth_fps = ui->comboBox_depth_fps->currentText();if(color_resolution != "1280*720" && color_fps != depth_fps){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("帧率设置错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}flag_applied = true;this->close(); //点击应用后相机设置窗口关闭
}
/***@file cloud_generate.cpp*@brief 点云生成源文件*/#include "cloud_generate.h"extern PointCloud::Ptr cloud;
extern PointCloudRGB::Ptr cloudRGB;extern BlockingConcurrentQueue<cv::Mat> bcq_colorMat;
extern BlockingConcurrentQueue<cv::Mat> bcq_depthMat;
extern BlockingConcurrentQueue<PointCloud::Ptr> bcq_cloud;
extern BlockingConcurrentQueue<PointCloudRGB::Ptr> bcq_cloudRGB;void Cloud_Generate::run()
{float camera_factor, camera_cx, camera_cy, camera_fx, camera_fy; //相机内参cv::Mat colorMat, depthMat;while(true){if(bcq_depthMat.try_dequeue(depthMat)){if(Camera_Settings::depth_resolution == "640*480"){camera_factor = 1;camera_cx = 311.0;camera_cy = 244.0;camera_fx = 593.0;camera_fy = 588.0;}else if(Camera_Settings::depth_resolution == "320*240"){camera_factor = 1;camera_cx = 311.0*0.5;camera_cy = 244.0*0.5;camera_fx = 593.0*0.5;camera_fy = 588.0*0.5;}if(bcq_colorMat.try_dequeue(colorMat)){cloudRGB->clear(); //重置点云为空//遍历深度图for (int i = 0; i < depthMat.rows; ++i){uchar* depthData = depthMat.data + i*depthMat.step;uchar* colorData = colorMat.data + i*colorMat.step;for (int j = 0; j < depthMat.cols; ++j){if (depthData == 0)continue;pcl::PointXYZRGB point;//计算点的空间坐标point.z = double(*(depthData++)) / camera_factor;point.x = (j - camera_cx) * point.z / camera_fx;point.y = -(i - camera_cy) * point.z / camera_fy;//从彩色图像中获取该点的颜色point.b = *(colorData++);point.g = *(colorData++);point.r = *(colorData++);//把该点加入到点云中cloudRGB->points.push_back(point);}}bcq_cloudRGB.enqueue(cloudRGB);}else{cloud->clear(); //重置点云为空//遍历深度图for (int i = 0; i < depthMat.rows; ++i){uchar* depthData = depthMat.data + i*depthMat.step;for (int j = 0; j < depthMat.cols; ++j){if (depthData == 0)continue;pcl::PointXYZ point;//计算点的空间坐标point.z = double(*(depthData++)) / camera_factor;point.x = (j - camera_cx) * point.z / camera_fx;point.y = -(i - camera_cy) * point.z / camera_fy;//把该点加入到点云中cloud->points.push_back(point);}}bcq_cloud.enqueue(cloud);}}}
}
/***@file main.cpp*@brief 主函数源文件*/#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Astra *w = new Astra;w->show();return a.exec();
}
/***@file mainwindow.cpp*@brief 主窗口源文件*/#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>/*** @brief cloud 无色点云*/
PointCloud::Ptr cloud(new PointCloud);/*** @brief cloudRGB 彩色点云*/
PointCloudRGB::Ptr cloudRGB(new PointCloudRGB);/*** @brief bcq_colorMat colorMat阻塞队列*/
BlockingConcurrentQueue<cv::Mat> bcq_colorMat;/*** @brief bcq_depthMat depthMat阻塞队列*/
BlockingConcurrentQueue<cv::Mat> bcq_depthMat;/*** @brief bcq_cloud cloud阻塞队列*/
BlockingConcurrentQueue<PointCloud::Ptr> bcq_cloud;/*** @brief bcq_cloudRGB cloudRGB阻塞队列*/
BlockingConcurrentQueue<PointCloudRGB::Ptr> bcq_cloudRGB;Astra::Astra(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);connect(ui->action_save_colorMat, &QAction::triggered, [=]{this->save_color_image();});connect(ui->action_save_depthMat, &QAction::triggered, [=]{this->save_depth_image();});connect(ui->action_save_pointcloud, &QAction::triggered, [=]{this->save_point_cloud();});connect(ui->action_open_colorMat, &QAction::triggered, [=]{this->open_color_image();});connect(ui->action_open_depthMat, &QAction::triggered, [=]{this->open_depth_image();});connect(ui->action_open_pointcloud, &QAction::triggered, [=]{this->open_point_cloud();});connect(ui->action_close_all, &QAction::triggered, [=]{this->close_all();});connect(ui->action_exit, &QAction::triggered, [=]{this->close();});connect(ui->action_open_camera, &QAction::triggered, [=]{this->open_camera();});connect(ui->action_close_camera, &QAction::triggered, [=]{this->close_camera();});//connect(ui->action_set_camera, &QAction::triggered, [=]{this->set_camera();});connect(ui->action_help_guide, &QAction::triggered, [=]{this->help_guide();});connect(ui->action_help_about, &QAction::triggered, [=]{this->help_about();});openni::OpenNI::initialize();
}Astra::~Astra()
{delete ui;openni::OpenNI::shutdown();
}void Astra::save_color_image()
{//选择路径QString fileName = QFileDialog::getSaveFileName(this,QString::fromLocal8Bit("保存彩色图")," ",tr(" (*.bmp *.jpg *.png)"));//文件名为空if (fileName.isEmpty()){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("文件名为空!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//彩色图像为空if (colorMat.empty()){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("彩色图保存错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}std::string filename(fileName.toLocal8Bit().data()); //支持带中文路径的读取cv::imwrite(filename, colorMat); //将彩色图像写入磁盘
}void Astra::save_depth_image()
{//选择路径QString fileName = QFileDialog::getSaveFileName(this,QString::fromLocal8Bit("保存深度图")," ",tr(" (*.bmp *.jpg *.png)"));//文件名为空if (fileName.isEmpty()){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("文件名为空!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//深度图为空if (depthMat.empty()){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("深度图保存错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}std::string filename(fileName.toLocal8Bit().data()); //支持带中文路径的读取cv::imwrite(filename, depthMat); //将深度图像写入磁盘
}void Astra::save_point_cloud()
{//选择路径QString fileName = QFileDialog::getSaveFileName(this,QString::fromLocal8Bit("保存点云")," ",tr(" (*.pcd)"));//文件名为空if (fileName.isEmpty()){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("文件名为空!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//点云数据为空if (cloudRGB->size()==0 && cloud->size()==0){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("点云保存错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}std::string filename(fileName.toLocal8Bit().data()); //支持带中文路径的读取if(flag_cloud)pcl::io::savePCDFileBinary(filename,*cloud); //将无色点云写入磁盘elsepcl::io::savePCDFileBinary(filename,*cloudRGB); //将彩色点云写入磁盘
}void Astra::open_color_image()
{ui->stackedWidget->setCurrentIndex(0);//选择路径QString fileName  = QFileDialog::getOpenFileName(this,QString::fromLocal8Bit("打开彩色图"),"home",tr("(*.bmp *.jpg *.png )"));//文件名为空if (fileName.isEmpty()){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("文件名为空!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}std::string filename(fileName.toLocal8Bit().data()); //支持带中文路径的读取cv::Mat colorMat = cv::imread(filename,-1); //-1表示读取原始数据//彩色图像为空或通道数不为3if(colorMat.empty() || colorMat.channels()!=3){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("彩色图打开错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//缩放图像使其适应窗口大小cv::resize(colorMat,colorMat,cv::Size(ui->label_color_1->width(),ui->label_color_1->height()));//cv::Mat转QImageQImage image_color = QImage((const uchar*)colorMat.data,colorMat.cols,colorMat.rows,QImage::Format_RGB888).rgbSwapped();//更新uiui->label_color_1->clear();ui->label_color_1->setPixmap(QPixmap::fromImage(image_color));
}void Astra::open_depth_image()
{ui->stackedWidget->setCurrentIndex(0);//选择路径QString fileName  = QFileDialog::getOpenFileName(this,QString::fromLocal8Bit("打开深度图"),"home",tr("(*.bmp *.jpg *.png )"));//文件名为空if (fileName.isEmpty()){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("文件名为空!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}std::string filename(fileName.toLocal8Bit().data()); //支持带中文路径的读取cv::Mat depthMat = cv::imread(filename,-1); //-1表示读取原始数据//深度图像为空或通道数不为1if(depthMat.empty() || depthMat.channels()!=1){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("深度图打开错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//缩放图像使其适应窗口大小cv::resize(depthMat,depthMat,cv::Size(ui->label_depth_1->width(),ui->label_depth_1->height()));//cv::Mat转QImageQImage image_depth = QImage((const uchar*)depthMat.data,depthMat.cols,depthMat.rows,QImage::Format_Grayscale8).rgbSwapped();//更新uiui->label_depth_1->clear();ui->label_depth_1->setPixmap(QPixmap::fromImage(image_depth));}void Astra::open_point_cloud()
{ui->stackedWidget->setCurrentIndex(0);//选择路径QString fileName = QFileDialog::getOpenFileName(this,QString::fromLocal8Bit("打开点云"),"home",tr("(*.pcd)"));//文件名为空if (fileName.isEmpty()){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("文件名为空!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}std::string filename(fileName.toLocal8Bit().data()); //支持带中文路径的读取//    PointCloud::Ptr cloud(new PointCloud);
//    PointCloudRGB::Ptr cloudRGB(new PointCloudRGB);//点云加载失败if(pcl::io::loadPCDFile(filename,*cloudRGB)==-1){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("点云打开错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//判断点云是否带有rgb信息if(cloudRGB->points[0].r){viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));viewer->addPointCloud(cloudRGB);ui->qvtkWidget_1->SetRenderWindow(viewer->getRenderWindow());ui->qvtkWidget_1->update();}else{pcl::io::loadPCDFile(filename,*cloud);viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));viewer->addPointCloud(cloud);ui->qvtkWidget_1->SetRenderWindow(viewer->getRenderWindow());ui->qvtkWidget_1->update();}
}void Astra::close_all()
{//清除彩色图像显示ui->label_color_1->clear();ui->label_color_2->clear();ui->label_color_3->clear();//清除深度图像显示ui->label_depth_1->clear();ui->label_depth_2->clear();if(cloud->points.size()||cloudRGB->points.size()){//移除viewer中的点云viewer->removeAllPointClouds();//清除点云显示ui->qvtkWidget_1->update();ui->qvtkWidget_2->update();}
}void Astra::open_camera()
{  //弹出相机设置界面Camera_Settings camera_settings(this);camera_settings.setWindowTitle(QString::fromLocal8Bit("相机设置"));camera_settings.exec();//如果没有点击相机设置界面中的应用按钮则什么都不做if(!Camera_Settings::flag_applied){return;}//彩色摄像头或深度摄像头已被打开if(capture.isOpened() || flag_depth){close_camera(); //先调用关闭相机的函数QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("摄像头打开出错!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//如果彩色图分辨率不为1280*720则开启深度摄像头if(Camera_Settings::color_resolution != "1280*720"){if (device.open(openni::ANY_DEVICE) != openni::STATUS_OK){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("深度摄像头打开出错!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();goto color;}//创建深度流depthStream.create(device, openni::SENSOR_DEPTH);//配置深度流的模式std::string depth_resolution = Camera_Settings::depth_resolution.toStdString();int DEPTH_COLS = std::stoi(depth_resolution.substr(0,depth_resolution.size()-4));int DEPTH_ROWS = std::stoi(depth_resolution.substr(depth_resolution.size()-3));std::string depth_fps = Camera_Settings::depth_fps.toStdString();int DEPTH_FPS = std::stoi(depth_fps.substr(0,depth_fps.size()-3));depthMode.setResolution(DEPTH_COLS, DEPTH_ROWS);depthMode.setPixelFormat(openni::PIXEL_FORMAT_DEPTH_1_MM);depthMode.setFps(DEPTH_FPS);depthStream.setVideoMode(depthMode);//打开深度流depthStream.start();//设置深度图像采集标志位flag_depth = true;//创建并开启深度图像显示定时器timerDepth = new QTimer(this);timerDepth-> setTimerType(Qt::PreciseTimer);connect(timerDepth, SIGNAL(timeout()), this, SLOT(show_depth_image()));timerDepth->start(100);}//打开彩色摄像头
color://彩色摄像头打开失败if(capture.open(Camera_Settings::color_index) != true){QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("彩色摄像打开出错!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//配置rgb流的模式std::string color_resolution = Camera_Settings::color_resolution.toStdString();int COLOR_COLS = std::stoi(color_resolution.substr(0,color_resolution.size()-4));int COLOR_ROWS = std::stoi(color_resolution.substr(color_resolution.size()-3));std::string color_fps = Camera_Settings::color_fps.toStdString();int COLOR_FPS = std::stoi(color_fps.substr(0,color_fps.size()-3));capture.set(cv::CAP_PROP_FRAME_WIDTH, COLOR_COLS);//宽度capture.set(cv::CAP_PROP_FRAME_HEIGHT, COLOR_ROWS);//高度capture.set(cv::CAP_PROP_FPS, COLOR_FPS);//帧率 帧/秒//创建并开启彩色图像显示定时器timerColor = new QTimer(this);timerColor-> setTimerType(Qt::PreciseTimer);connect(timerColor, SIGNAL(timeout()), this, SLOT(show_color_image()));timerColor->start(100);//创建并开启点云显示定时器if(flag_depth){timerCloud = new QTimer(this);timerCloud-> setTimerType(Qt::PreciseTimer);connect(timerCloud, SIGNAL(timeout()), this, SLOT(show_point_cloud()));timerCloud->start(100);}//启动点云生成线程Cloud_Generate *task = new Cloud_Generate;task->start();
}void Astra::close_camera()
{//如果相机未开启则直接返回if(!capture.isOpened()){return;}//关闭彩色图像显示定时器timerColor->stop();//关闭彩色摄像头capture.release();//清除彩色图像显示ui->label_color_1->clear();ui->label_color_2->clear();ui->label_color_3->clear();if(Camera_Settings::color_resolution != "1280*720" && flag_depth){//关闭深度图像显示定时器timerDepth->stop();//关闭点云显示定时器timerCloud->stop();//关闭深度流depthStream.stop();depthStream.destroy();//关闭深度摄像头device.close();//清除深度图像显示ui->label_depth_1->clear();ui->label_depth_2->clear();//清除点云cloud->clear();cloudRGB->clear();//移除viewer中的点云viewer->removeAllPointClouds();//清除点云显示ui->qvtkWidget_1->update();ui->qvtkWidget_2->update();//设置深度图像采集标志flag_depth = false;}//设置相机设置应用标志位Camera_Settings::flag_applied = false;
}//void Astra::set_camera()
//{    camera_settings = new Camera_Settings(this);
    camera_settings->setWindowTitle(QString::fromLocal8Bit("相机设置"));
    camera_settings->show();
//    Camera_Settings camera_settings(this);
//    camera_settings.setWindowTitle(QString::fromLocal8Bit("相机设置"));
//    camera_settings.exec();
//}void Astra::show_color_image()
{capture >> colorMat;//彩色图像采集为空if(colorMat.empty()){timerColor->stop();QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("彩色图采集错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//彩色图和深度图呈镜像关系,所以要翻转一下cv::flip(colorMat, colorMat, 1);//cv::Mat转QImageQImage image_color = QImage((const uchar*)colorMat.data, colorMat.cols, colorMat.rows, QImage::Format_RGB888).rgbSwapped();//依据不同分辨率显示不同大小的彩色图像if(Camera_Settings::color_resolution == "640*480"){ui->label_color_1->clear();ui->label_color_1->setPixmap(QPixmap::fromImage(image_color));}else if(Camera_Settings::color_resolution == "320*240"){ui->label_color_2->clear();ui->label_color_2->setPixmap(QPixmap::fromImage(image_color));}else if(Camera_Settings::color_resolution == "1280*720"){ui->label_color_3->clear();ui->label_color_3->setPixmap(QPixmap::fromImage(image_color));}bcq_colorMat.enqueue(colorMat);cv::waitKey(10); //防止程序卡住
}void Astra::show_depth_image()
{openni::VideoFrameRef depth_frame;int iMaxDepth = depthStream.getMaxPixelValue();openni::VideoStream* pstream = &depthStream;int changedStreamDummy;openni::Status ops = openni::OpenNI::waitForAnyStream(&pstream, 1, &changedStreamDummy, 50); //等待一帧ops = depthStream.readFrame(&depth_frame);if (ops != openni::STATUS_OK){timerDepth->stop();return;}//获取深度帧数据auto depth = depth_frame.getData();auto depthWidth = depth_frame.getWidth();auto depthHeight = depth_frame.getHeight();//处理并渲染深度帧数据cv::Mat rawMat(depthHeight, depthWidth, CV_16UC1, (void*)depth);rawMat.convertTo(depthMat, CV_8UC1, 255.0 / iMaxDepth);//深度图采集为空if(depthMat.empty()){timerDepth->stop();QMessageBox *box = new QMessageBox(QMessageBox::Warning,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("深度图采集错误!"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}QTimer::singleShot(3000,box,SLOT(accept()));box->exec();return;}//cv::Mat转QImageQImage image_depth = QImage((const uchar*)depthMat.data, depthMat.cols,depthMat.rows, QImage::Format_Grayscale8).rgbSwapped();//依据不同分辨率显示不同大小的深度图像if(Camera_Settings::depth_resolution == "640*480"){ui->label_depth_1->clear();ui->label_depth_1->setPixmap(QPixmap::fromImage(image_depth));}else if(Camera_Settings::depth_resolution == "320*240"){ui->label_depth_2->clear();ui->label_depth_2->setPixmap(QPixmap::fromImage(image_depth));}bcq_depthMat.enqueue(depthMat);cv::waitKey(10); //防止程序卡住
}void Astra::show_point_cloud()
{if(bcq_cloudRGB.try_dequeue(cloudRGB)){viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));viewer->addPointCloud(cloudRGB);flag_cloud = false;}else if(bcq_cloud.try_dequeue(cloud)){viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));viewer->addPointCloud(cloud);flag_cloud = true;}//依据不同分辨率显示点云if(Camera_Settings::depth_resolution == "640*480"){ui->qvtkWidget_1->SetRenderWindow(viewer->getRenderWindow());ui->qvtkWidget_1->update();}else if(Camera_Settings::depth_resolution == "320*240"){ui->qvtkWidget_2->SetRenderWindow(viewer->getRenderWindow());ui->qvtkWidget_2->update();}
}void Astra::help_guide()
{QMessageBox *box = new QMessageBox(QMessageBox::Information, QString::fromLocal8Bit("使用说明"),QString::fromLocal8Bit(" 本软件提供了Astra相机的深度图,\n 彩色图以及点云显示和保存功能。\n\n"" 由于开发周期短和本人能力有限,\n 其他功能还尚未完善,敬请谅解。"),QMessageBox::Ok);if(NULL!=box->button(QMessageBox::Ok)){box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));}box->setStyleSheet("QLabel{min-width: 240px;min-height: 180px;}");box->exec();
}void Astra::help_about()
{QMessageBox::about(NULL, QString::fromLocal8Bit("关于AstraGUI"), "by taify");
}

代码写的比较糙,但功能基本上都实现了。本来想用cmake管理工程,但发现vtk库和pcl库写在CMakeLists里面不知道为啥似乎会有冲突,两个库单独用好像都可以,只好还是用Qt自带的.pro文件来配置了。完整工程文件已上传GitHub。
另外,我把win10下Release-x64编译打包的应用程序放到百度网盘链接(链接:https://pan.baidu.com/s/160MyTBiNr0N6WbSjNLUZpw提取码:oqv3 )里面了,在另外一台win10电脑上测试过了也能凑合着用。图像如果有读不出来的情况把相机拔下来重插一下就好了。

乐视三合一体感摄像头Astra pro开发记录2(Qt界面)相关推荐

  1. 乐视三合一体感摄像头Astra pro开发记录1(深度图、彩色图及点云简单显示)

    在某鱼上淘的乐视三合一体感摄像头,捡漏价九十几块,买来玩玩. 网上已经有一些关于此款摄像头的开发资料. 官方的开发资料:官网链接 按官方网站以及其他帖子,下载并安装相机的驱动和SDK,不难配置好相机. ...

  2. 全网最详细 Opencv + OpenNi + 奥比中光(Orbbec) Astra Pro /乐视三合一体感摄像头LeTMC-520 + linux 环境搭建

    本文参考 Using Orbbec Astra 3D cameras C++20学习:基于Ubuntu系统编译gcc10.2.0 linux下编译安装opencv生成opencv.pc 摄像头方案 / ...

  3. 奥比中光 astra 乐视三合一体感摄像头采集深度图彩色图并保存

    本文参考的文章: 目录 ROS下开发 运行ROS节点 查看相机的话题及画面 订阅画面并保存 Python环境下开发 调用摄像头并保存采集画面 C++环境下开发 C++环境配置 代码编译 ROS下开发 ...

  4. 乐视三合一体感摄像头LeTMC-520

    这款体感摄像头其实就是奥比中光摄像头(Orbbec Astra Pro)的乐视版 1. 介绍 乐视三合一体感摄像头的各个功能模组分部图,包括两个MIC麦克风,一个红外投影模组,一个面部接近感知模组,一 ...

  5. 乐视三合一体感摄像头--基本信息及windows下部分开发

    乐视三合一体感摄像头--基本信息及windows下部分开发 Introduction 基本信息 Windows下使用 安装驱动 使用openNI 使用imageJ 调用RGB图像 Q: 参考资料 In ...

  6. 乐视三合一体感摄像头--windows下的开发2

    乐视三合一体感摄像头--windows下的开发 Introduction 环境配置过程 参考资料 后言 Introduction 解决上篇教程乐视三合一体感摄像头–基本信息及windows下部分开发: ...

  7. 乐视三合一摄像头和kinect_乐视三合一体感摄像头开箱体验

    很高兴我能成为第一批乐视三合一体感摄像头使用乐迷,说起这款摄像头可以说是业内良心产品.深度分辨率:1280*1024.工作距离可以达到4米,独创体感识别.骨骼识别和拍照摄像头三合一休,可同时支持6人玩 ...

  8. 乐视三合一体感摄像头开发(捡漏)笔记——100块要啥自行车

    乐视三合一体感摄像头开发(捡漏)笔记 不久前在闲鱼上淘了一个乐视体感摄像头,这是乐视之前做的一款周边硬件,它当时是对标Kinect的,该有的结构一点不差,然而乐视凉凉之后,这个摄像头价格也从八九百降到 ...

  9. 乐视三合一摄像头和kinect_乐视三合一体感摄像头快评测,看看到底怎么玩?

    原标题:乐视三合一体感摄像头快评测,看看到底怎么玩? 说起"体感",也许很多人都不知道,即使知道也仅限于Kinect,其实乐视早就开始了这方面的探索.先是之前的3D体感摄像头,现在 ...

最新文章

  1. 004_Gson树模型
  2. Spring 面试问题 TOP 50,你会哪些?
  3. led透明屏生产厂家_如何实现LED双面透明显示屏,双面LED透明屏
  4. freertos 编译c++失败_FreeRTOS的初次见面
  5. 学会java基础能找工作吗?
  6. nginx经过多层代理后获取真实来源ip
  7. 图书管理系统(说明文档与相关代码)
  8. android对象关系映射框架ormlite学习之单表操作
  9. 【信息系统项目管理师】第9章-项目人力资源管理 知识点详细整理
  10. linux替换字符串 正则,Linux 字符串操作-裁剪和正则替换
  11. 老兵不死:Radionomy正式宣布收购Winamp
  12. python之作业--------购物车优化
  13. ios控制中心android版,IOS控制中心
  14. 计算机word制作成绩单,如何用word批量制作学生成绩单?
  15. 有关存储器容量的计算
  16. Google Borg论文
  17. 创业公社:亦庄分中心开业 借好创业东风
  18. unity添加天空盒的两种方式
  19. HtmlCss光标(插入符caret)透明隐藏光标 221106笔记
  20. FDC2214调试笔记(1)——为什么FDC2214输出的会是0x00000000或者0xffffffff?

热门文章

  1. Intellij IDEA 接口实现的快捷键
  2. 常见三维文件格式之IGES
  3. 航空发动机风扇叶片的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  4. mysql随机不连续数据_用MySQL里的Rand()生成 不连续重复 的随机数年龄以及随机姓名字符串...
  5. 自然语言处理4——TF-IDF及特征提取
  6. 了解一下Roguelike游戏和Roguelite游戏
  7. Zadig 玩转亚马逊云科技全家桶
  8. 推荐Win11系统自带包管理工具WinGet安装软件,Win10同样可用
  9. python3.8安装包下载,适用于win7,win10
  10. Termux安装数据库(手机安装数据库)...