news 2026/6/10 17:14:50

【基于 PyQt6 的红外与可见光图像配准工具开发实战】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【基于 PyQt6 的红外与可见光图像配准工具开发实战】

前言

图像配准是计算机视觉中的重要技术,特别是在多模态图像融合领域。本文将介绍如何使用 Python 和 PyQt6 开发一个功能完善的红外与可见光图像配准工具,支持手动调整、批量处理和游戏化键盘控制。

项目背景

在实际应用中,我们经常需要将红外图像与可见光图像进行配准,以便进行图像融合、目标检测等后续处理。传统的配准工具往往操作复杂、学习成本高,因此我们开发了一个直观易用的配准工具。

技术栈

  • Python 3.11: 主要开发语言
  • PyQt6: GUI 框架
  • OpenCV: 图像处理
  • NumPy: 数值计算
  • PyInstaller: 打包工具

核心功能

1. 双模式配准

全局模式(Global Mode)
  • 使用统一的配准参数
  • 适用于批量处理
  • 快速预览效果
手动模式(Manual Mode)
  • 为每张图像单独调整参数
  • 精确控制配准效果
  • 参数自动保存

2. 游戏化键盘控制

这是本工具的一大亮点,采用类似游戏的键盘控制方式:

defkeyPressEvent(self,event):key=event.key()ifkeynotinself.pressed_keys:self.pressed_keys.add(key)iflen(self.pressed_keys)==1:self.key_repeat_timer.start(self.key_repeat_interval)

特性

  • 方向键移动图像
  • W/E 控制水平缩放
  • A/D 控制垂直缩放
  • 支持长按连续移动
  • 支持多键同时按下(斜向移动)
  • 50ms 重复间隔,流畅如游戏

3. 可视化控制面板

除了键盘控制,还提供了可视化的方向键面板:

keyboard_group=QGroupBox("移动控制")keyboard_layout=QGridLayout()self.key_up_btn=QPushButton("↑")self.key_up_btn.pressed.connect(lambda:self.simulate_key_press(Qt.Key.Key_Up))self.key_up_btn.released.connect(lambda:self.simulate_key_release(Qt.Key.Key_Up))

布局如下:

↑ ← ↓ →

4. 自动参数管理

自动保存
  • 切换图像时自动保存当前参数
  • 静默保存,不弹窗干扰
  • 参数保存到results目录
参数加载
  • 加载图像时自动读取已保存的参数
  • 自动恢复到上次配准状态
  • 支持 JSON 格式存储

5. 批量导出功能

defexport_images(self):# 统计已配准图像params_count=0forir_fileinself.ir_files:json_file=self.result_dir/f"{ir_file.stem}.json"ifjson_file.exists():params_count+=1# 只导出已配准的图像fori,ir_fileinenumerate(self.ir_files):json_file=self.result_dir/f"{ir_file.stem}.json"ifnotjson_file.exists():skip_count+=1continue# 读取参数并应用withopen(json_file,'r',encoding='utf-8')asf:params=json.load(f)dx=params.get('dx',0)dy=params.get('dy',0)angle=params.get('angle',0.0)scale_x=params.get('scale_x',1.0)scale_y=params.get('scale_y',1.0)

特性

  • 使用results目录下的参数
  • 只导出已配准的图像
  • 显示详细的导出统计

6. 长按快速切换

"下一张"按钮支持长按功能:

defnext_btn_pressed(self):self.next_btn_is_long_press=Falseself.next_btn_timer=QTimer()self.next_btn_timer.setSingleShot(True)self.next_btn_timer.timeout.connect(self.on_next_btn_long_press)self.next_btn_timer.start(500)# 500ms 长按阈值defon_next_btn_long_press(self):self.next_btn_is_long_press=Trueself.next_image()self.start_auto_switch()# 每 300ms 自动切换

核心实现

1. 图像显示与变换

classImageCanvas(QWidget):defupdate_transformed_image(self):h,w=self.ir_image.shape[:2]center=(w//2,h//2)# 创建变换矩阵M=cv2.getRotationMatrix2D(center,self.angle,1.0)M[0,0]*=self.scale_x M[1,1]*=self.scale_y M[0,2]+=self.dx M[1,2]+=self.dy# 应用变换self.transformed_image=cv2.warpAffine(self.ir_image,M,(w,h))# 混合显示self.blended_image=cv2.addWeighted(self.vis_image,1-self.alpha,self.transformed_image,self.alpha,0)self.update()

2. 信号与槽机制

classImageCanvas(QWidget):parameters_changed=pyqtSignal(int,int,float,float,float)defmouseMoveEvent(self,event):ifself.dragging:dx=int(event.position().x()-self.last_pos.x())dy=int(event.position().y()-self.last_pos.y())self.dx+=dx self.dy+=dy self.last_pos=event.position()self.update_transformed_image()self.parameters_changed.emit(self.dx,self.dy,self.scale_x,self.scale_y,self.angle)classImageRegistrationWindow(QMainWindow):def__init__(self):self.image_canvas=ImageCanvas(self)self.image_canvas.parameters_changed.connect(self.update_parameter_labels)

3. 参数同步

defupdate_parameter_labels(self,dx=None,dy=None,scale_x=None,scale_y=None,angle=None):ifdxisNoneordyisNoneorscale_xisNoneorscale_yisNoneorangleisNone:dx,dy,scale_x,scale_y,angle,alpha=\ self.image_canvas.get_parameters()self.dx_spin.setValue(dx)self.dy_spin.setValue(dy)self.scale_x_slider.setValue(int(scale_x*100))self.scale_y_slider.setValue(int(scale_y*100))self.angle_slider.setValue(int(angle))self.scale_x_label.setText(f"ScaleX:{scale_x:.2f}")self.scale_y_label.setText(f"ScaleY:{scale_y:.2f}")self.angle_label.setText(f"Angle:{angle:.1f}°")

打包发布

使用 PyInstaller 将程序打包为独立的 exe 文件:

spec 文件配置

a=Analysis(['image_registration_tool.py'],pathex=[],binaries=[],datas=[],hiddenimports=['cv2','numpy','PyQt6','PyQt6.QtCore','PyQt6.QtGui','PyQt6.QtWidgets',],hookspath=[],hooksconfig={},runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False,)exe=EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='ImageRegistrationTool',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,console=False,# 无控制台窗口icon=None,)

打包命令

pyinstaller image_registration_tool.spec

打包后生成dist/ImageRegistrationTool.exe,文件大小约 84 MB,包含所有依赖库,可在任何 Windows 机器上直接运行。

使用指南

1. 准备数据

创建以下目录结构:

JZ_data/ ├── images/ # 可见光图像 ├── imagesIR/ # 红外图像 └── results/ # 配准参数(自动创建)

2. 运行程序

python image_registration_tool.py

或直接运行打包后的 exe:

ImageRegistrationTool.exe

3. 加载图像

  1. 点击"加载红外目录",选择红外图像文件夹
  2. 点击"加载可见光目录",选择可见光图像文件夹
  3. 程序会自动匹配同名图像

4. 配准图像

方法一:键盘控制
  • 方向键:移动图像
  • W/E:水平缩放
  • A/D:垂直缩放
  • +/-:调整混合比例
方法二:鼠标控制
  • 直接拖拽图像进行移动
  • 使用右侧滑块调整参数
方法三:可视化按钮
  • 点击方向按钮移动图像

5. 保存参数

  • 按 S 键保存
  • 或点击"保存参数"按钮
  • 切换图像时自动保存

6. 批量导出

  1. 完成所有图像的配准
  2. 点击"批量导出"
  3. 选择输出目录
  4. 等待导出完成

项目亮点

  1. 游戏化操作体验:键盘控制流畅自然,学习成本低
  2. 自动参数管理:切换图像时自动保存,无需手动操作
  3. 批量处理能力:支持一键导出所有已配准图像
  4. 可视化控制:提供多种控制方式,满足不同用户习惯
  5. 独立可执行:打包为 exe,无需 Python 环境

完整代码

完整代码已上传至 GitHub:

https://github.com/xy200303/image_registration_tool.git

包含以下文件:

  • image_registration_tool.py- 主程序
  • requirements.txt- 依赖列表
  • image_registration_tool.spec- 打包配置
  • build.bat- 自动打包脚本
  • README.md- 项目说明

总结

本文介绍了一个基于 PyQt6 的红外与可见光图像配准工具的开发过程。通过游戏化的键盘控制、自动参数管理和批量处理功能,大大提升了配准效率。该工具已成功打包为独立 exe 文件,可在任何 Windows 机器上直接运行。

参考资料

  • PyQt6 官方文档
  • OpenCV 官方文档
  • PyInstaller 文档

作者: xy200303
GitHub: https://github.com/xy200303/image_registration_tool.git
日期: 2026-01-23

如果觉得这篇文章对你有帮助,欢迎点赞、收藏和转发!有任何问题欢迎在评论区讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 17:26:20

Node.js 用 process.cpuUsage 监控CPU使用率

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 Node.js CPU监控的深度实践:超越process.cpuUsage的陷阱与创新目录Node.js CPU监控的深度实践:超越proce…

作者头像 李华
网站建设 2026/6/10 13:48:57

【课程设计/毕业设计】基于JavaWeb寝室管理系统Web的学生宿舍管理系统【附源码、数据库、万字文档】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/6/10 2:13:37

树状数组

lc2659树状数组统计已删除元素&#xff0c;按数值升序遍历元素位置分前后段计算每次删除的移动步数并累加&#xff0c;求解清空数组的总操作数。// 树状数组模板 class BIT {vector<int> tree; public:BIT(int n) : tree(n) {}// 将下标 i 上的数加一void inc(int i) {wh…

作者头像 李华
网站建设 2026/5/30 12:24:15

一道“找数”的题,为什么能成为算法世界的常青树?

一道“找数”的题,为什么能成为算法世界的常青树? 从 Missing Number 说起 一、引子:这题你肯定见过,但你真的“理解”了吗? 很多人第一次见到这道题,心里都会冒出一句话: “这也叫算法题?小学数学吧?” 题目很简单: 给你一个包含 0 ~ n 中 n 个不同数字 的数组, …

作者头像 李华
网站建设 2026/5/29 16:59:53

.nvue页面实现画笔绘制功能,用原生html导入nvue页面使用还可以截图(画笔 清空 橡皮擦 改颜色 禁用画笔 截图-是视频画面加绘制合成一张图片截图)-我花80块钱找淘宝都没弄出来,自己写的

功能 安卓app上面nvue 视频上方绘制&#xff08;vue2&#xff09;①新建一个draw.html文件&#xff08;里面功能有画笔 清空 橡皮擦 改颜色 禁用画笔 截图-是视频画面加绘制合成一张图片截图&#xff09;②webViewUrl: /static/draw.html,③<!-- 画布 绘制层 --><web-…

作者头像 李华