案例分享:Qt用于服务器多图像拼接存在误差的标定工具(像素误差校准)

简介: 案例分享:Qt用于服务器多图像拼接存在误差的标定工具(像素误差校准)

若该文为原创文章,转载请注明原文出处

本文章博客地址: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


相关文章
|
1月前
|
监控 虚拟化 云计算
从物理到云:使用自动化工具简化服务器迁移流程
【10月更文挑战第4天】随着云计算的快速发展,越来越多的企业选择将物理服务器迁移到云环境以提高效率和降低成本。本文详细介绍了使用自动化工具简化从物理到云的服务器迁移流程的技术实现细节,并提供了代码示例。
111 6
|
25天前
|
监控 Java Linux
Linux系统之安装Ward服务器监控工具
【10月更文挑战第17天】Linux系统之安装Ward服务器监控工具
49 5
Linux系统之安装Ward服务器监控工具
|
4月前
|
网络协议
Qt中的网络编程(Tcp和Udp)运用详解以及简单示范案例
Tcp和Udp是我们学习网络编程中经常接触到的两个通讯协议,在Qt也被Qt封装成了自己的库供我们调用,对于需要进行网络交互的项目中无疑是很重要的,希望这篇文章可以帮助到大家。 是关于Qt中TCP和UDP的基本使用和特点:
627 7
|
17天前
|
监控 Kubernetes 安全
如何设置一个有效的远程管理工具来简化服务器的维护工作?
如何设置一个有效的远程管理工具来简化服务器的维护工作?
|
1月前
|
SQL 分布式计算 关系型数据库
Hadoop-21 Sqoop 数据迁移工具 简介与环境配置 云服务器 ETL工具 MySQL与Hive数据互相迁移 导入导出
Hadoop-21 Sqoop 数据迁移工具 简介与环境配置 云服务器 ETL工具 MySQL与Hive数据互相迁移 导入导出
50 3
|
2月前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
53 4
|
2月前
|
监控 Kubernetes 安全
如何设置一个有效的远程管理工具来简化服务器的维护工作?
如何设置一个有效的远程管理工具来简化服务器的维护工作?
|
3月前
|
监控 网络安全 数据安全/隐私保护
Mac服务器ssh连接工具
Mac服务器ssh连接工具
107 2
|
3月前
|
缓存 NoSQL 网络安全
【Azure Redis 缓存】使用开源工具redis-copy时遇见6379端口无法连接到Redis服务器的问题
【Azure Redis 缓存】使用开源工具redis-copy时遇见6379端口无法连接到Redis服务器的问题
|
3月前
【qt】客户端连接到服务器
【qt】客户端连接到服务器
61 0

推荐镜像

更多