经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C 语言 » 查看文章
VS+Qt+Halcon 显示图片,实现鼠标缩放、移动图片
来源:jb51  时间:2021/8/26 10:36:39  对本文有异议

摘要

本篇博文记录一下,用VS+Qt+Halcon实现对图片的读取以及鼠标缩放,移动(鼠标事件调用了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

  1. #pragma once
  2. #include "qlabel.h"
  3. #include"QWheelEvent"
  4. #include<HalconCpp.h>
  5. using namespace HalconCpp;
  6.  
  7. class Mylabel :
  8. public QLabel
  9. {
  10. Q_OBJECT
  11.  
  12. public:
  13. Mylabel(QWidget* parent = Q_NULLPTR);
  14. ~Mylabel();
  15. //设置Halcon图像和Halcon窗口句柄,用户响应鼠标事件后实时更新图像
  16. void setHalconWnd(HObject img, HTuple hHalconID, QLabel* label);
  17. //鼠标滚轮缩放事件
  18. void wheelEvent(QWheelEvent* ev);
  19. //鼠标按下事件
  20. void mousePressEvent(QMouseEvent* ev);
  21. //鼠标释放事件
  22. void mouseReleaseEvent(QMouseEvent* ev);
  23. //鼠标移动事件
  24. void mouseMoveEvent(QMouseEvent* ev);
  25. public:
  26. HTuple m_labelID; //Qt标签句柄
  27. HTuple m_hHalconID; //Halcon窗口句柄
  28. HObject m_currentImg; //当前的图像
  29. //主界面显示坐标的标签
  30. QLabel* m_label;
  31. //鼠标按下的位置
  32. HTuple m_tMouseDownRow;
  33. HTuple m_tMouseDownCol;
  34. bool m_bIsMove; //是否移动图像标识
  35. };

Mylabel.cpp

  1. #include "Mylabel.h"
  2. //定义单步放大倍率
  3. #define ZOOMRATIO 2.0
  4.  
  5. Mylabel::Mylabel(QWidget* parent)
  6. : QLabel(parent)
  7. {
  8. m_bIsMove = false;
  9. this->setMouseTracking(true);
  10. }
  11. Mylabel::~Mylabel()
  12. {
  13.  
  14. }
  15.  
  16. //设置Halcon图像和Halcon窗口句柄,用户响应鼠标事件后实时更新图像
  17. void Mylabel::setHalconWnd(HObject img, HTuple hHalconID, QLabel* label)
  18. {
  19. m_hHalconID = hHalconID;
  20. m_currentImg = img;
  21. m_label = label;
  22. }
  23.  
  24. //鼠标滚轮缩放事件,用于缩放图像
  25. void Mylabel::wheelEvent(QWheelEvent* ev)
  26. {
  27. double Zoom; //放大或缩小倍率
  28. HTuple mouseRow, mouseCol, Button;
  29. HTuple startRowBf, startColBf, endRowBf, endColBf, Ht, Wt, startRowAft, startColAft, endRowAft, endColAft;
  30. //滚轮前滑,放大
  31. if (ev->delta()>0)
  32. {
  33. Zoom = ZOOMRATIO;
  34. }
  35. else//否则缩小
  36. {
  37. Zoom = 1 / ZOOMRATIO;
  38. }
  39. //获取光标在原图上的位置,注意是原图坐标,不是Label下的坐标
  40. HTuple hv_Exception, hv_ErrMsg;
  41. try
  42. {
  43. GetMposition(m_hHalconID, &mouseRow, &mouseCol, &Button);
  44.  
  45. }
  46. catch (HException& HDevExpDefaultException)
  47. {
  48. return;
  49. }
  50. //获取原图显示的部分,注意也是原图坐标
  51. GetPart(m_hHalconID, &startRowBf, &startColBf, &endRowBf, &endColBf);
  52. //缩放前显示的图像宽高
  53. Ht = endRowBf - startRowBf;
  54. Wt = endColBf - startColBf;
  55. //普通版halcon能处理的图像最大尺寸是32K*32K。如果无限缩小原图像,导致显示的图像超出限制,则会造成程序崩溃
  56. if (Ht*Wt<20000*20000||Zoom==ZOOMRATIO)
  57. {
  58. //计算缩放后的图像区域
  59. startRowAft = mouseRow - ((mouseRow - startRowBf) / Zoom);
  60. startColAft = mouseCol - ((mouseCol - startColBf) / Zoom);
  61. endRowAft = startRowAft + (Ht / Zoom);
  62. endColAft = startColAft + (Wt / Zoom);
  63. //如果放大过大,则返回
  64. if (endRowAft - startRowAft < 2)
  65. {
  66. return;
  67. }
  68.  
  69. if (m_hHalconID != NULL)
  70. {
  71. //如果有图像,则先清空图像
  72. DetachBackgroundFromWindow(m_hHalconID);
  73. }
  74. SetPart(m_hHalconID, startRowAft, startColAft, endRowAft, endColAft);
  75. AttachBackgroundToWindow(m_currentImg, m_hHalconID);
  76. }
  77. }
  78.  
  79. void Mylabel::mousePressEvent(QMouseEvent* ev)
  80. {
  81. HTuple mouseRow, mouseCol, Button;
  82. try
  83. {
  84. GetMposition(m_hHalconID, &mouseRow, &mouseCol, &Button);
  85.  
  86. }
  87. catch (HException)
  88. {
  89. return;
  90. }
  91. //鼠标按下时的行列坐标
  92. m_tMouseDownRow = mouseRow;
  93. m_tMouseDownCol = mouseCol;
  94. m_bIsMove = true;
  95. }
  96. //鼠标释放事件
  97. void Mylabel::mouseReleaseEvent(QMouseEvent* ev)
  98. {
  99. m_bIsMove = false;
  100. }
  101. //鼠标移动事件
  102. void Mylabel::mouseMoveEvent(QMouseEvent* ev)
  103. {
  104. HTuple startRowBf, startColBf, endRowBf, endColBf, mouseRow, mouseCol, Button;
  105. try
  106. {
  107. GetMposition(m_hHalconID, &mouseRow, &mouseCol, &Button);
  108.  
  109. }
  110. catch (HException)
  111. {
  112. return;
  113. }
  114. //鼠标按下并移动时,移动图像,否则只显示坐标
  115. if (m_bIsMove)
  116. {
  117. //计算移动值
  118. double RowMove = mouseRow[0].D() - m_tMouseDownRow[0].D();
  119. double ColMove = mouseCol[0].D() - m_tMouseDownCol[0].D();
  120. //得到当前的窗口坐标
  121. GetPart(m_hHalconID, &startRowBf, &startColBf, &endRowBf, &endColBf);
  122. //移动图像
  123. if (m_hHalconID!=NULL)
  124. {
  125. //如果有图像,则先清空图像
  126. DetachBackgroundFromWindow(m_hHalconID);
  127. }
  128. SetPart(m_hHalconID, startRowBf - RowMove, startColBf - ColMove, endRowBf - RowMove, endColBf - ColMove);
  129. AttachBackgroundToWindow(m_currentImg, m_hHalconID);
  130. }
  131. //获取灰度值
  132. HTuple pointGray;
  133. try
  134. {
  135. GetGrayval(m_currentImg, mouseRow, mouseCol, &pointGray);
  136. }
  137. catch (HException)
  138. {
  139. m_label->setText(QString::fromLocal8Bit("X坐标:- Y坐标:- 灰度值:-"));
  140.  
  141. return;
  142. }
  143. //设置坐标
  144. m_label->setText(QString::fromLocal8Bit("X坐标:%1 Y坐标:%2 灰度值:%3").arg(mouseCol[0].D()).arg(mouseRow[0].D()).arg(pointGray[0].D()));
  145. }

BrowsePic.h

  1. #pragma once
  2.  
  3. #include <QtWidgets/QWidget>
  4. #include "ui_BrowsePic.h"
  5. #include<HalconCpp.h>
  6. #include"qtoolbar.h"
  7. using namespace HalconCpp;
  8. #pragma execution_character_set("utf-8");
  9.  
  10. class BrowsePic : public QWidget
  11. {
  12. Q_OBJECT
  13.  
  14. public:
  15. BrowsePic(QWidget *parent = Q_NULLPTR);
  16. ~BrowsePic();
  17. //初始化
  18. void init();
  19.  
  20. //显示图像
  21. void showImg();
  22. int currentIndex;
  23. //显示图像的控件id
  24. HTuple m_hLabelID; //QLabel控件句柄
  25. HTuple m_hHalconID; //Halcon显示窗口句柄
  26.  
  27. //原始图像的尺寸
  28. HTuple m_imgWidth, m_imgHeight;
  29.  
  30. //图片路径列表
  31. HTuple m_imgFiles;
  32.  
  33. //当前图像
  34. HObject m_hCurrentImg;
  35. //缩放后的图像
  36. HObject m_hResizedImg;
  37. //缩放系数
  38. HTuple m_hvScaledRate;
  39. //缩放后图像的大小
  40. HTuple m_scaledHeight, m_scaledWidth;
  41. QToolBar* m_toolBar;
  42. public slots:
  43.  
  44. //打开图片
  45. void on_btn_openPic_clicked();
  46.  
  47. //浏览前一张
  48. void on_btn_prePic_clicked();
  49.  
  50. //浏览后一张
  51. void on_btn_nextPic_clicked();
  52.  
  53. //恢复图片
  54. void on_btn_resetPic_clicked();
  55. private:
  56. Ui::BrowsePicClass ui;
  57. };

BrowsePic.cpp

  1. #include "browsepic.h"
  2. #include"Mylabel.h"
  3. #include <QFileDialog>
  4. #include <QFileInfo>
  5. BrowsePic::BrowsePic(QWidget *parent)
  6. : QWidget(parent)
  7. {
  8. ui.setupUi(this);
  9.  
  10. init();
  11.  
  12. }
  13. BrowsePic::~BrowsePic()
  14. {
  15.  
  16. }
  17.  
  18. void BrowsePic::init()
  19. {
  20. //设置halcon的文件路径为utf8,解决中文乱码
  21. SetSystem("filename_encoding", "utf8");
  22. //生成空图像
  23. GenEmptyObj(&m_hCurrentImg);
  24. m_hHalconID = NULL;
  25. m_hLabelID = (Hlong)ui.label->winId();
  26. currentIndex = -1;
  27. }
  28. //显示图像
  29. void BrowsePic::showImg()
  30. {
  31. if (m_hHalconID!=NULL)
  32. {
  33. //如果有图像,则先清空图像
  34. DetachBackgroundFromWindow(m_hHalconID);
  35. }
  36. else
  37. {
  38. //打开窗口
  39. OpenWindow(0, 0, ui.label->width(), ui.label->height(), m_hLabelID, "visible", "", &m_hHalconID);
  40. }
  41. ui.label-> setHalconWnd(m_hCurrentImg, m_hHalconID, ui.label_status);
  42.  
  43. //获取图像大小
  44. GetImageSize(m_hCurrentImg, &m_imgWidth, &m_imgHeight);
  45. //获取缩放系数
  46. TupleMin2(1.0 * ui.label->width() / m_imgWidth, 1.0 * ui.label->height() / m_imgHeight, &m_hvScaledRate);
  47. //缩放图像
  48. ZoomImageFactor(m_hCurrentImg, &m_hResizedImg, m_hvScaledRate, m_hvScaledRate, "constant");
  49. //获取缩放后的大小
  50. GetImageSize(m_hResizedImg, &m_scaledWidth, &m_scaledHeight);
  51. //打开窗口
  52. if (1.0 * ui.label->width() / m_imgWidth < 1.0 * ui.label->height() / m_imgHeight)
  53. {
  54. SetWindowExtents(m_hHalconID, ui.label->height() / 2.0 - m_scaledHeight / 2.0, 0, ui.label->width(), m_scaledHeight);
  55. }
  56. else
  57. {
  58. SetWindowExtents(m_hHalconID, 0, ui.label->width() / 2.0 - m_scaledWidth / 2.0, m_scaledWidth, ui.label->height());
  59.  
  60. }
  61. SetPart(m_hHalconID, 0, 0, m_imgHeight - 1, m_imgWidth - 1);
  62. AttachBackgroundToWindow(m_hCurrentImg, m_hHalconID);
  63. }
  64.  
  65. //打开图片
  66. void BrowsePic::on_btn_openPic_clicked()
  67. {
  68. QString path = QFileDialog::getOpenFileName(this, "加载图像", "./", "图像文件(*.bmp *.png *.jpg)");
  69. QFileInfo fileInfo(path);
  70. QString dir = fileInfo.path();
  71.  
  72. if (!path.isEmpty())
  73. {
  74. ListFiles(dir.toStdString().c_str(), "files", &m_imgFiles);
  75.  
  76. TupleRegexpSelect(m_imgFiles, HTuple("\\.bmp|png|jpg").Append("ignore_case"), &m_imgFiles);
  77.  
  78.  
  79. for (int i = 0; i < m_imgFiles.Length(); i++)
  80. {
  81.  
  82. QString currentPath = m_imgFiles[i];
  83. currentPath.replace("\\", "/");
  84.  
  85. if (currentPath == path)
  86. {
  87. currentIndex = i;
  88. ReadImage(&m_hCurrentImg, m_imgFiles[i]);
  89. showImg();
  90. }
  91.  
  92. }
  93. }
  94.  
  95. }
  96.  
  97. //浏览前一张
  98. void BrowsePic::on_btn_prePic_clicked()
  99. {
  100. if (currentIndex > 0)
  101. {
  102. currentIndex--;
  103. ReadImage(&m_hCurrentImg, m_imgFiles[currentIndex]);
  104. showImg();
  105.  
  106. }
  107. }
  108. //浏览后一张
  109. void BrowsePic::on_btn_nextPic_clicked()
  110. {
  111. if (currentIndex >= 0 && currentIndex < m_imgFiles.Length() - 1)
  112. {
  113. currentIndex++;
  114. ReadImage(&m_hCurrentImg, m_imgFiles[currentIndex]);
  115. showImg();
  116. }
  117. }
  118. //恢复图片
  119. void BrowsePic::on_btn_resetPic_clicked()
  120. {
  121. showImg();
  122. }

关键代码解释

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

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

list_files()的原型如下:

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

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

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

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

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

getOpenFileName()获得的路径:

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

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

  1. QString currentPath = m_imgFiles[i];

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

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

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

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

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

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

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

  1. set_system("filename_encoding", "utf8");

参考链接:

(4条消息) VS+Qt应用开发-使用Halcon算子实现从文件夹打开图片、前后浏览、缩放居中显示_羽士的博客-CSDN博客

到此这篇关于VS+Qt+Halcon 显示图片,实现鼠标缩放、移动图片的文章就介绍到这了,更多相关VS+Qt+Halcon鼠标缩放、移动图片内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号