若该文为原创文章,转载请注明原文出处
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79556106
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)
合作案例专栏:案例分享(体验Demo可下载,只定制)
需求
高性能图像拼接服务器由于在存在误差,需要使用标定软件获取计算后的每个位置图片进行像素标定(校准),将人工校准的图像相关信息以指令形式发送给服务器端,服务器的每次拼接将依赖此标定参数。
标定80幅图,10台服务器,每台服务器8路1080p摄像头。
Demo
下载地址:https://download.csdn.net/download/qq21497936/10286573
效果图
原理
打开文件拼接,按照范围1-80的顺序打开图像文件,加载到软件里面,每图片的5个像素作为一个实际坐标像素,记录每个图片相对于坐标第一张图片的左上角x,y的坐标,以及他们的宽度和高度,组成单幅图像的拼接参数。
功能
可加载任意多的图片,对一个图片进行移动,包括上下左右,校准完后点击制作,将会把所有图片指令以指令格式组成协议包发往拼接服务器,拼接服务器各自记录自己部分的拼接参数,以便运行时使用。
关键代码
打开文件图片文件代码(打开“按钮”)
void MainWindow::on_pushButton_locaPics_clicked() { QStringList filePaths = QFileDialog::getOpenFileNames(this, tr("添加图片"), "./", tr("Images (*.png *.bmp *.jpg)")); if(!filePaths.size()) { QMessageBox::information(this, tr("提示"), tr("您未选择图片")); return; } ui->pushButton_moveXLess->setEnabled(true); ui->pushButton_moveXMore->setEnabled(true); ui->pushButton_moveUp->setEnabled(true); ui->pushButton_moveDown->setEnabled(true); ui->pushButton_make->setEnabled(true); for(int index = 0; index < _listPixmapButton.size(); index++) { delete _listPixmapButton.at(index); } _listPixmapButton.clear(); for(int index = 0; index < _listLabel.size(); index++) { delete _listLabel.at(index); } _listLabel.clear(); for(int index = 0; index < filePaths.size(); index++) { PixmapButton * pPixmapButton = new PixmapButton(ui->frame); pPixmapButton->setStyleSheet(""); pPixmapButton->setPosWidth(_picWidth); pPixmapButton->setPosHeight(_picHeight); pPixmapButton->resize(_picWidth, _picHeight); pPixmapButton->setStyleSheet(QString("border-image: url(%1);").arg(filePaths.at(index))); connect(pPixmapButton, SIGNAL(updateChecked(PixmapButton*,bool)), this, SLOT(updateChecked(PixmapButton*,bool))); _listPixmapButton.push_back(pPixmapButton); } for(int index = 0; index < _listPixmapButton.size()-1; index++) { QLabel *pLabel = new QLabel(ui->frame); pLabel->setFixedWidth(100); pLabel->setText("0 pixel"); _listLabel.push_back(pLabel); } _init = false; updateFrame(); }
对于每个图像使用QPusuButton,贴上图片作为一个图片单元,QPushButton存在两套x,y,width和height,一套是QPushButton实际的,一套是对应于左边第一张图片的x,y,width,height(方便制作协议)
pixmapbutton.h
#ifndef PIXMAPBUTTON_H #define PIXMAPBUTTON_H /**************************************************\ * Demo: 图像块 * 描述: 图像大小 * 作者: 红模仿 QQ: 21497936 博客地址:http://blog.csdn.net/qq21497936/ * 备注:作者提供各种技术相关服务,如开发、调试、IT集成服务等等 * 版本信息: 版本号 日期 描述 * v1.0 2018年1月31日 基础版本 \**************************************************/ #include <QWidget> #include <QPushButton> #include <QPaintEvent> #include <QColor> class PixmapButton : public QPushButton { Q_OBJECT public: explicit PixmapButton(QWidget *parent = nullptr); public: inline void setCheckedOne(bool checkedOne) { _checkedOne = checkedOne; } inline void setPosX(int x) { _x = x; } inline void setPosY(int y) { _y = y; } inline int getPosX() { return _x; } inline int getPosY() { return _y; } inline void setPosWidth(int width) { _width = width; } inline int getPosWidth() { return _width; } inline void setPosHeight(int height) { _height = height; } inline int getPosHeight() { return _height; } inline void setPos(int x, int y) { _x = x; _y = y; } inline void setPos(int x, int y, int width, int height) { _x = x; _y = y; _width = width; _height = height; } inline void getPos(int &x, int &y, int &width, int &height) { x = _x; y = _y; width = _width; height = _height; } signals: void updateChecked(PixmapButton * pPixmapButton, bool checked); public slots: void slotCheck(bool checked); protected: void paintEvent(QPaintEvent *event) override; private: int _x; int _y; int _width; int _height; QColor _color; bool _checkedOne; }; #endif // PIXMAPBUTTON_H
pixmapbutton.cpp
#include "pixmapbutton.h" #include "mainwindow.h" #include <QPainter> #include <QDebug> PixmapButton::PixmapButton(QWidget *parent) : QPushButton(parent), _color(QColor(41,19,244)), _checkedOne(false) { setCheckable(true); resize(400,200); _width = 400; _height = 200; connect(this, SIGNAL(clicked(bool)), this, SLOT(slotCheck(bool))); } void PixmapButton::slotCheck(bool checked) { emit updateChecked(this, checked); emit updateChecked(this, checked); emit updateChecked(this, checked); } void PixmapButton::paintEvent(QPaintEvent *event) { QPushButton::paintEvent(event); }
更新显示图片的代码
void MainWindow::updateFrame() { int x, y, width; ui->frame->resize(ui->scrollArea->width(), ui->scrollArea->height()); if(!_init) { for(int index = 0; index < _listPixmapButton.size(); index++) { if(index == 0) { x = 0; width = _listPixmapButton.at(index)->width(); y = (ui->frame->height() - _listPixmapButton.at(index)->height()) / 2.0f; } x += SPACER; _listPixmapButton.at(index)->move(x,y); _listPixmapButton.at(index)->setPosX(x); _listPixmapButton.at(index)->setPosY(y); _listPixmapButton.at(index)->show(); _listPixmapButton.at(index)->update(); x += _listPixmapButton.at(index)->width(); if(index == _listPixmapButton.size() - 1) { ui->frame->setFixedWidth(x+SPACER); } if(_listPixmapButton.at(index)->isChecked()) { int x,y,width,height; _listPixmapButton.at(index)->getPos(x, y, width, height); ui->label_arrow->move((x+(width-ui->label_arrow->width())/2), y+height+_arrowSpace+_dy); ui->label_arrow->setVisible(true); } } _init = true; }else{ for(int index = 0; index < _listPixmapButton.size(); index++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index); pPixmapButton->move(pPixmapButton->getPosX(), pPixmapButton->getPosY()+_dy); if(pPixmapButton->isChecked()) { int x,y,width,height; pPixmapButton->getPos(x, y, width, height); ui->label_arrow->move((x+(width-ui->label_arrow->width())/2), y+height+_arrowSpace+_dy); ui->label_arrow->setVisible(true); } } } for(int index = 0; index < _listPixmapButton.size(); index++) { if(index == 0) continue; int interval = _listPixmapButton.at(index)->getPosX()-(_listPixmapButton.at(index-1)->getPosX()+_listPixmapButton.at(index-1)->getPosWidth()); _listLabel.at(index-1)->setText(QString("%1 pixel").arg(interval*_scale)); _listLabel.at(index-1)->move(_listPixmapButton.at(index)->getPosX(), _listPixmapButton.at(index)->getPosY()-_pixelSpace+_dy); _listLabel.at(index-1)->setVisible(true); } }
左移代码
void MainWindow::on_pushButton_moveXLess_clicked() { bool isChecked = false; for(int index = 0; index < _listPixmapButton.size(); index++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index); if(pPixmapButton->isChecked()) { isChecked = true; if(pPixmapButton->getPosX() - _xStep < 0) { break; }else{ if(index > 0) { // 当右边的图片的x与左边的图片x相差小于_minXSapce时,从右边到最后边的所有图片将不会做x移动 if(_listPixmapButton.at(index)->getPosX() - _listPixmapButton.at(index-1)->getPosX() < _minXSapce) { break; } } for(int index2 = index; index2 < _listPixmapButton.size(); index2++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index2); pPixmapButton->setPosX(pPixmapButton->getPosX()-_xStep); } break; } } } if(!isChecked) { int start; for(int index = 0; index < _listPixmapButton.size(); index++) { if(index > 0) { // 当右边的图片的x与左边的图片x相差小于_minXSapce时,从右边到最后边的所有图片将不会做x移动 if(_listPixmapButton.at(index)->getPosX() - _listPixmapButton.at(index-1)->getPosX() < _minXSapce) { break; } } PixmapButton *pPixmapButton = _listPixmapButton.at(index); if(pPixmapButton->getPosX()-_xStep < 0) { start = index; continue; }else { pPixmapButton->setPosX(pPixmapButton->getPosX()-(index-start)*_xStep); } if(index == _listPixmapButton.size() - 1) { // ui->frame->setFixedWidth(_listPixmapButton.at(index)->x()+_listPixmapButton.at(index)->width()); } } } updateFrame(); }
左移代码
void MainWindow::on_pushButton_moveXMore_clicked() { bool isChecked = false; for(int index = 0; index < _listPixmapButton.size(); index++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index); if(pPixmapButton->isChecked()) { isChecked = true; if(index == 0) break; for(int index2 = index; index2 < _listPixmapButton.size(); index2++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index2); pPixmapButton->setPosX(pPixmapButton->getPosX()+_xStep); if(index2 == _listPixmapButton.size() - 1) { if(ui->frame->width() < _listPixmapButton.at(index2)->x()+_listPixmapButton.at(index2)->width()) ui->frame->setFixedWidth(_listPixmapButton.at(index2)->x()+_listPixmapButton.at(index2)->width()); } } break; } } if(!isChecked) { for(int index = 0; index < _listPixmapButton.size(); index++) { if(index == 0) continue; PixmapButton *pPixmapButton = _listPixmapButton.at(index); pPixmapButton->setPosX(pPixmapButton->getPosX()+index*_xStep); if(index == _listPixmapButton.size() - 1) { if(ui->frame->width() < _listPixmapButton.at(index)->x()+_listPixmapButton.at(index)->width()) ui->frame->setFixedWidth(_listPixmapButton.at(index)->x()+_listPixmapButton.at(index)->width()); } } } updateFrame(); }
上移代码
void MainWindow::on_pushButton_moveUp_clicked() { bool isChecked = false; for(int index = 0; index < _listPixmapButton.size(); index++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index); if(pPixmapButton->isChecked()) { isChecked = true; if(index >= 1) { if(pPixmapButton->getPosY()+pPixmapButton->height()-_listPixmapButton.at(index-1)->getPosY() <= _minXSapce) break; } if(index < _listPixmapButton.size()-1) { if(pPixmapButton->getPosY()+pPixmapButton->height()-_listPixmapButton.at(index+1)->getPosY() <= _minXSapce) break; } pPixmapButton->setPosY(pPixmapButton->getPosY()-_yStep); break; } } if(!isChecked) { for(int index = 0; index < _listPixmapButton.size(); index++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index); pPixmapButton->setPosY(pPixmapButton->getPosY()-_yStep); } } updateFrame(); }
下移代码
void MainWindow::on_pushButton_moveDown_clicked() { bool isChecked = false; for(int index = 0; index < _listPixmapButton.size(); index++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index); if(pPixmapButton->isChecked()) { isChecked = true; if(index >= 1) { if(pPixmapButton->getPosY() - (_listPixmapButton.at(index-1)->getPosY() + _listPixmapButton.at(index-1)->getPosHeight()) >= -_minYSapce) break; } if(index < _listPixmapButton.size()-1) { if(pPixmapButton->getPosY() - (_listPixmapButton.at(index+1)->getPosY() + _listPixmapButton.at(index+1)->getPosHeight()) >= -_minYSapce) break; } pPixmapButton->setPosY(pPixmapButton->getPosY()+_yStep); break; } } if(!isChecked) { for(int index = 0; index < _listPixmapButton.size(); index++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index); pPixmapButton->setPosY(pPixmapButton->getPosY()+_yStep); } } updateFrame(); }
快捷键代码
void MainWindow::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_W: if(ui->pushButton_moveUp->isEnabled()) { on_pushButton_moveUp_clicked(); } break; case Qt::Key_S: if(ui->pushButton_moveDown->isEnabled()) { on_pushButton_moveDown_clicked(); } break; case Qt::Key_A: if(ui->pushButton_moveXLess->isEnabled()) { on_pushButton_moveXLess_clicked(); } break; case Qt::Key_D: if(ui->pushButton_moveXMore->isEnabled()) { on_pushButton_moveXMore_clicked(); } break; case Qt::Key_O: on_pushButton_locaPics_clicked(); break; default: break; } }
制作标定协议代码
void MainWindow::on_pushButton_make_clicked() { QList<PicInfo> listPicInfo; for(int index = 0; index < _listPixmapButton.size(); index++) { PixmapButton *pPixmapButton = _listPixmapButton.at(index); PicInfo info; info.index = index+1; info.x = pPixmapButton->getPosX()*_scale; info.y = pPixmapButton->getPosY()*_scale; info.width = pPixmapButton->getPosWidth()*_scale; info.height = pPixmapButton->getPosHeight()*_scale; listPicInfo.push_back(info); } // show data qDebug() << "*******************************************************"; for(int index = 0; index < listPicInfo.size(); index++) { qDebug() << "index :" << listPicInfo.at(index).index << " " << "x :" << listPicInfo.at(index).x << " " << "y :" << listPicInfo.at(index).y << " " << "width :" << listPicInfo.at(index).width << " " << "height :" << listPicInfo.at(index).height; } qDebug() << "*******************************************************"; }
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79556106