摘要
本篇博文记录一下,用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
- #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();
- }
关键代码解释
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");

参考链接:
(4条消息) VS+Qt应用开发-使用Halcon算子实现从文件夹打开图片、前后浏览、缩放居中显示_羽士的博客-CSDN博客
到此这篇关于VS+Qt+Halcon 显示图片,实现鼠标缩放、移动图片的文章就介绍到这了,更多相关VS+Qt+Halcon鼠标缩放、移动图片内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!