新西兰服务器

VS+Qt+Halcon显示图片之如何实现鼠标缩放、移动图片


VS+Qt+Halcon显示图片之如何实现鼠标缩放、移动图片

发布时间:2021-08-26 11:47:43 来源:高防服务器网 阅读:85 作者:小新 栏目:开发技术

小编给大家分享一下VS+Qt+Halcon显示图片之如何实现鼠标缩放、移动图片,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

先来看一下动态效果图:

主要控件:

  • 添加一个Label控件,对象名设为label,用于显示图片,并将背景设为黑色,设置方法为:选中Label控件,在属性编辑器中找到styleSheet属性,在其后的值中输入background-color:black即可;

  • 添加四个Push Button控件,如上图所示从左至右,对象名依次为:btn_prePic、btn_openPic、btn_nextPic,btn_resetPic,用于打开图片和前后浏览,以及恢复原图;

  • 添加一个Label,对象名设为label_status,用于实时显示坐标和灰度值;

  • 将label_show控件提升为CMyLabel类,用于接收鼠标事件。

代码例程

在Visual Studio中新建一个Qt GUI项目,名称设为BrowsePic,并新建Mylabel类(继承自QLabel)用于label控件的提升。

Mylabel.h

#pragma once  #include "qlabel.h"  #include"QWheelEvent"  #include<HalconCpp.h>  using namespace HalconCpp;    class Mylabel :      public QLabel  {      Q_OBJECT    public:      Mylabel(QWidget* parent = Q_NULLPTR);      ~Mylabel();      //设置Halcon图像和Halcon窗口句柄,用户响应鼠标事件后实时更新图像      void setHalconWnd(HObject img, HTuple hHalconID, QLabel* label);      //鼠标滚轮缩放事件      void wheelEvent(QWheelEvent* ev);      //鼠标按下事件      void mousePressEvent(QMouseEvent* ev);      //鼠标释放事件      void mouseReleaseEvent(QMouseEvent* ev);      //鼠标移动事件      void mouseMoveEvent(QMouseEvent* ev);  public:      HTuple m_labelID;            //Qt标签句柄      HTuple m_hHalconID;            //Halcon窗口句柄      HObject m_currentImg;        //当前的图像      //主界面显示坐标的标签      QLabel* m_label;      //鼠标按下的位置       HTuple m_tMouseDownRow;      HTuple m_tMouseDownCol;      bool m_bIsMove;                //是否移动图像标识  };

Mylabel.cpp

#include "Mylabel.h"  //定义单步放大倍率  #define ZOOMRATIO 2.0    Mylabel::Mylabel(QWidget* parent)      : QLabel(parent)  {      m_bIsMove = false;      this->setMouseTracking(true);        }  Mylabel::~Mylabel()  {    }    //设置Halcon图像和Halcon窗口句柄,用户响应鼠标事件后实时更新图像  void Mylabel::setHalconWnd(HObject img, HTuple hHalconID, QLabel* label)  {      m_hHalconID = hHalconID;      m_currentImg = img;      m_label = label;  }    //鼠标滚轮缩放事件,用于缩放图像  void Mylabel::wheelEvent(QWheelEvent* ev)  {      double Zoom;   //放大或缩小倍率      HTuple  mouseRow, mouseCol, Button;      HTuple startRowBf, startColBf, endRowBf, endColBf, Ht, Wt, startRowAft, startColAft, endRowAft, endColAft;      //滚轮前滑,放大      if (ev->delta()>0)      {          Zoom = ZOOMRATIO;      }      else//否则缩小      {          Zoom = 1 / ZOOMRATIO;      }      //获取光标在原图上的位置,注意是原图坐标,不是Label下的坐标      HTuple  hv_Exception, hv_ErrMsg;       try       {           GetMposition(m_hHalconID, &mouseRow, &mouseCol, &Button);         }       catch (HException& HDevExpDefaultException)       {           return;       }       //获取原图显示的部分,注意也是原图坐标       GetPart(m_hHalconID, &startRowBf, &startColBf, &endRowBf, &endColBf);       //缩放前显示的图像宽高       Ht = endRowBf - startRowBf;       Wt = endColBf - startColBf;       //普通版halcon能处理的图像最大尺寸是32K*32K。如果无限缩小原图像,导致显示的图像超出限制,则会造成程序崩溃       if (Ht*Wt<20000*20000||Zoom==ZOOMRATIO)       {           //计算缩放后的图像区域           startRowAft = mouseRow - ((mouseRow - startRowBf) / Zoom);           startColAft = mouseCol - ((mouseCol - startColBf) / Zoom);           endRowAft = startRowAft + (Ht / Zoom);           endColAft = startColAft + (Wt / Zoom);           //如果放大过大,则返回           if (endRowAft - startRowAft < 2)           {               return;           }             if (m_hHalconID != NULL)           {               //如果有图像,则先清空图像               DetachBackgroundFromWindow(m_hHalconID);           }           SetPart(m_hHalconID, startRowAft, startColAft, endRowAft, endColAft);           AttachBackgroundToWindow(m_currentImg, m_hHalconID);           }  }    void Mylabel::mousePressEvent(QMouseEvent* ev)  {      HTuple mouseRow, mouseCol, Button;      try      {          GetMposition(m_hHalconID, &mouseRow, &mouseCol, &Button);        }      catch (HException)      {          return;      }      //鼠标按下时的行列坐标      m_tMouseDownRow = mouseRow;      m_tMouseDownCol = mouseCol;      m_bIsMove = true;  }  //鼠标释放事件  void Mylabel::mouseReleaseEvent(QMouseEvent* ev)  {      m_bIsMove = false;  }  //鼠标移动事件  void Mylabel::mouseMoveEvent(QMouseEvent* ev)  {      HTuple startRowBf, startColBf, endRowBf, endColBf, mouseRow, mouseCol, Button;      try      {          GetMposition(m_hHalconID, &mouseRow, &mouseCol, &Button);        }      catch (HException)      {          return;      }      //鼠标按下并移动时,移动图像,否则只显示坐标      if (m_bIsMove)      {          //计算移动值          double RowMove = mouseRow[0].D() - m_tMouseDownRow[0].D();          double ColMove = mouseCol[0].D() - m_tMouseDownCol[0].D();          //得到当前的窗口坐标          GetPart(m_hHalconID, &startRowBf, &startColBf, &endRowBf, &endColBf);          //移动图像          if (m_hHalconID!=NULL)          {              //如果有图像,则先清空图像              DetachBackgroundFromWindow(m_hHalconID);          }          SetPart(m_hHalconID, startRowBf - RowMove, startColBf - ColMove, endRowBf - RowMove, endColBf - ColMove);          AttachBackgroundToWindow(m_currentImg, m_hHalconID);      }      //获取灰度值      HTuple pointGray;      try      {          GetGrayval(m_currentImg, mouseRow, mouseCol, &pointGray);      }      catch (HException)      {          m_label->setText(QString::fromLocal8Bit("X坐标:-    Y坐标:-    灰度值:-"));            return;      }      //设置坐标      m_label->setText(QString::fromLocal8Bit("X坐标:%1    Y坐标:%2    灰度值:%3").arg(mouseCol[0].D()).arg(mouseRow[0].D()).arg(pointGray[0].D()));  }

BrowsePic.h

#pragma once    #include <QtWidgets/QWidget>  #include "ui_BrowsePic.h"  #include<HalconCpp.h>  #include"qtoolbar.h"  using namespace HalconCpp;  #pragma execution_character_set("utf-8");    class BrowsePic : public QWidget  {      Q_OBJECT    public:      BrowsePic(QWidget *parent = Q_NULLPTR);      ~BrowsePic();      //初始化      void init();        //显示图像      void showImg();      int currentIndex;      //显示图像的控件id      HTuple m_hLabelID;            //QLabel控件句柄      HTuple m_hHalconID;            //Halcon显示窗口句柄        //原始图像的尺寸      HTuple m_imgWidth, m_imgHeight;        //图片路径列表      HTuple m_imgFiles;        //当前图像      HObject m_hCurrentImg;      //缩放后的图像      HObject m_hResizedImg;      //缩放系数      HTuple m_hvScaledRate;      //缩放后图像的大小      HTuple m_scaledHeight, m_scaledWidth;      QToolBar* m_toolBar;  public slots:        //打开图片      void on_btn_openPic_clicked();        //浏览前一张      void on_btn_prePic_clicked();        //浏览后一张      void on_btn_nextPic_clicked();        //恢复图片      void on_btn_resetPic_clicked();  private:      Ui::BrowsePicClass ui;  };

BrowsePic.cpp

#include "browsepic.h"  #include"Mylabel.h"  #include <QFileDialog>  #include <QFileInfo>  BrowsePic::BrowsePic(QWidget *parent)      : QWidget(parent)  {      ui.setupUi(this);        init();    }  BrowsePic::~BrowsePic()  {    }    void BrowsePic::init()  {      //设置halcon的文件路径为utf8,解决中文乱码      SetSystem("filename_encoding", "utf8");      //生成空图像      GenEmptyObj(&m_hCurrentImg);      m_hHalconID = NULL;      m_hLabelID = (Hlong)ui.label->winId();      currentIndex = -1;  }  //显示图像  void BrowsePic::showImg()  {      if (m_hHalconID!=NULL)      {          //如果有图像,则先清空图像          DetachBackgroundFromWindow(m_hHalconID);                }      else      {          //打开窗口          OpenWindow(0, 0, ui.label->width(), ui.label->height(), m_hLabelID, "visible", "", &m_hHalconID);      }      ui.label-> setHalconWnd(m_hCurrentImg, m_hHalconID, ui.label_status);        //获取图像大小      GetImageSize(m_hCurrentImg, &m_imgWidth, &m_imgHeight);      //获取缩放系数      TupleMin2(1.0 * ui.label->width() / m_imgWidth, 1.0 * ui.label->height() / m_imgHeight, &m_hvScaledRate);      //缩放图像      ZoomImageFactor(m_hCurrentImg, &m_hResizedImg, m_hvScaledRate, m_hvScaledRate, "constant");      //获取缩放后的大小      GetImageSize(m_hResizedImg, &m_scaledWidth, &m_scaledHeight);      //打开窗口      if (1.0 * ui.label->width() / m_imgWidth < 1.0 * ui.label->height() / m_imgHeight)      {          SetWindowExtents(m_hHalconID, ui.label->height() / 2.0 - m_scaledHeight / 2.0, 0, ui.label->width(), m_scaledHeight);      }      else      {          SetWindowExtents(m_hHalconID, 0, ui.label->width() / 2.0 - m_scaledWidth / 2.0, m_scaledWidth, ui.label->height());        }      SetPart(m_hHalconID, 0, 0, m_imgHeight - 1, m_imgWidth - 1);      AttachBackgroundToWindow(m_hCurrentImg, m_hHalconID);  }    //打开图片  void BrowsePic::on_btn_openPic_clicked()  {      QString path = QFileDialog::getOpenFileName(this, "加载图像", "./", "图像文件(*.bmp *.png *.jpg)");      QFileInfo fileInfo(path);      QString dir = fileInfo.path();        if (!path.isEmpty())      {          ListFiles(dir.toStdString().c_str(), "files", &m_imgFiles);            TupleRegexpSelect(m_imgFiles, HTuple("\.bmp|png|jpg").Append("ignore_case"), &m_imgFiles);              for (int i = 0; i < m_imgFiles.Length(); i++)          {                QString currentPath = m_imgFiles[i];              currentPath.replace("\", "/");                if (currentPath == path)              {                  currentIndex = i;                  ReadImage(&m_hCurrentImg, m_imgFiles[i]);                  showImg();              }            }      }    }    //浏览前一张  void BrowsePic::on_btn_prePic_clicked()  {      if (currentIndex > 0)      {          currentIndex--;          ReadImage(&m_hCurrentImg, m_imgFiles[currentIndex]);          showImg();        }  }  //浏览后一张  void BrowsePic::on_btn_nextPic_clicked()  {      if (currentIndex >= 0 && currentIndex < m_imgFiles.Length() - 1)      {          currentIndex++;          ReadImage(&m_hCurrentImg, m_imgFiles[currentIndex]);          showImg();      }  }  //恢复图片  void BrowsePic::on_btn_resetPic_clicked()  {      showImg();  }

关键代码解释

1️、Qt函数与Halcon算子获取的文件路径字符串的区别

Halcon算子获取的文件路径格式

list_files()的原型如下:

第一个参数为路径,提取的文件路径格式与参数Directory的形式有关,在HDevelop中测试:

–Directory以"\"分隔时,即list_files ('E:\TEST', 'files', Files)

–Directory以“/”分隔时,即list_files ('E:/TEST', 'files', Files)

可以发现两种方式提取的文件路径字符串的区别。

Qt函数获取的文件路径格式

getOpenFileName()获得的路径:

如何将二者路径保持一致?

先读取halcon算子获取的路径:

 QString currentPath = m_imgFiles[i];

然后将" "全部换成" /":

 currentPath.replace("\", "/");

2️⃣在VS中使用Halcon时的编码及中文乱码问题

默认条件下,可使用以下C++语句获取Halcon的文件名编码:

HTuple codeType;  get_system("filename_encoding", &codeType);  QString strCodeType = codeType[0].S();

可以发现默认的编码是locale,此时用Halcon算子list_files获取的文件路径中如果包含中文,则会出现乱码

解决方法:将Halcon的文件名编码格式设置为utf8,代码如下:

set_system("filename_encoding", "utf8");

以上是“VS+Qt+Halcon显示图片之如何实现鼠标缩放、移动图片”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注高防服务器网行业资讯频道!

[微信提示:高防服务器能助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

[图文来源于网络,不代表本站立场,如有侵权,请联系高防服务器网删除]
[