1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > VS+Qt+Halcon——显示图片 实现鼠标缩放 移动图片

VS+Qt+Halcon——显示图片 实现鼠标缩放 移动图片

时间:2023-03-09 16:22:08

相关推荐

VS+Qt+Halcon——显示图片 实现鼠标缩放 移动图片

摘要

本篇博文记录一下,用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_OBJECTpublic: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.0Mylabel::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_OBJECTpublic:BrowsePic(QWidget *parent = Q_NULLPTR);~BrowsePic();//初始化void init();//显示图像void showImg();int currentIndex;//显示图像的控件idHTuple 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");

三,项目打包

详细过程可参考我的博文:QT从入门到入土(八)——项目打包和发布 - 唯有自己强大 - 博客园 ()

需要注意一点的是:对于halcon库的引用需要:

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。