PyQT5实现图像处理应用(含Windows7下完整打包方案)

news/2024/5/19 21:31:34 标签: qt, 图像处理, pyqt5, windows7部署, pyinstaller

目录

  • 1、任务概述
  • 2、环境安装
    • 2.1 创建虚拟环境
    • 2.2 安装依赖库
  • 3、程序开发
  • 4、打包部署
  • 5、小结

1、任务概述

本篇博文将通过PyQT5来实现一个简单的图像处理应用,并完成打包部署。

本文开发平台:Windows10 64位系统。部署平台:Windows7 64位系统

具体实现效果如下:
在这里插入图片描述
由于PyQT依赖Python,因此在学习下面的章节前,请先安装好Python。本教程使用的Python版本为3.8.0(由于部署平台为Windows7,因此不能使用Python3.8以上版本)。

2、环境安装

2.1 创建虚拟环境

为方便后面打包部署,我们将相关Python的依赖库存放到虚拟环境中,因此需要先创建一个虚拟环境。

Windows平台下的虚拟环境需要使用第三方工具virtualenv来创建,打开命令终端,输入下面的命令即可完成安装:

pip install virtualenv -i https://mirror.baidu.com/pypi/simple

创建一个项目文件夹demo,我们现在的目标就是在这个demo项目中创建python虚拟环境,这个虚拟环境是专门为demo项目成立的。在命令行终端中通过cd命令进入项目目录中(假设demo文件夹位于D:\code目录下):

输入下面的命令用来创建名为venv的虚拟环境:

virtualenv env

这样我们就在demo文件夹下有了一个名为env的子文件夹,它保存了一个全新的虚拟环境,其中有一个私有的Python解释器位于demo/env/Scripts,在该虚拟环境中安装的python包会存放在demo/env/Lib路径下。

最后,在Windows平台下激活并使用该虚拟环境:

env\Scripts\activate

如下图所示:
在这里插入图片描述
成功激活之后,虚拟环境解释器的路径就被加入PATH中,但这种改变不是永久的,他只会影响当前的命令行终端。

2.2 安装依赖库

在虚拟环境中安装pyqt5和opencv:

pip install pyqt5 opencv-python -i https://mirror.baidu.com/pypi/simple

其中pyqt5用于开发界面程序,而opencv用于图像处理算法操作。

3、程序开发

3.1 框架搭建

在demo文件夹下面创建一个名为main.py的脚本,内容如下:

# -*- coding:utf-8 -*-
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QLabel, QFileDialog
from PyQt5.QtCore import QRect,QCoreApplication,Qt
from PyQt5.QtGui import QPixmap,QImage

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        # 调整窗体
        self.resize(500, 300)  # 主窗体宽高设置
        self.setWindowTitle("示例程序")  # 主窗体名称
        # 创建2个图像标签
        self.preImgLabel = QLabel("", self)
        self.preImgLabel.setGeometry(QRect(30, 30, 200, 200))
        self.preImgLabel.setStyleSheet("background-color: rgb(232, 232, 232);")
        self.preImgLabel.setScaledContents(True)
        self.aftImgLabel = QLabel("", self)
        self.aftImgLabel.setGeometry(QRect(270, 30, 200, 200))
        self.aftImgLabel.setStyleSheet("background-color: rgb(232, 232, 232);")
        self.aftImgLabel.setScaledContents(True)
        # 创建2个按钮组件
        self.chooseBtn = QPushButton("选择图片", self)
        self.chooseBtn.clicked.connect(self.choosePic)
        self.chooseBtn.setGeometry(QRect(170, 250, 60, 30))
        self.processBtn = QPushButton("图片处理", self)
        self.processBtn.clicked.connect(self.imgProcess)
        self.processBtn.setGeometry(QRect(270, 250, 60, 30))
        
        self.imgName = ''

    def choosePic(self):
        """选择图片"""
        pass
        
    def imgProcess(self):
        """图片处理"""
        pass
        self.aftImgLabel.setStyleSheet("border: 2px solid red")

if __name__ == "__main__":
    """程序主入口"""
    QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) # 设置屏幕分辨率自适应
    app = QApplication(sys.argv)  # 创建应用
    main = MainWindow()  # 创建主窗体
    main.show()          # 显示主窗体
    sys.exit(app.exec()) # 进入主窗体生命周期

上述脚本创建了一个主窗体,包括2个label组件、2个按钮组件,同时对两个按钮组件创建了对应的槽函数choosePic和imgProcess。

运行该脚本,效果如下图所示:
在这里插入图片描述
可以看到,使用PySide6来开发界面程序非常简单,代码量很少。

3.2 读取图像

下面完善main.py文件的代码,单击选择图片按钮可以浏览本地计算机里的图像,并且将图像显示到左侧图像面板中。

具体的,只需要修改choosePic函数即可:

def choosePic(self):
    """选择图片"""
    self.imgName, _ = QFileDialog.getOpenFileName(self, "打开图片", "", "*.jpg;;*.png;;All Files(*)")
    if self.imgName == '':
        return
    pix = QPixmap(self.imgName)
    self.preImgLabel.setPixmap(pix)
    self.preImgLabel.setStyleSheet("border: 2px solid blue")

3.3 图像处理

这里我们将使用opencv完成图像gamma矫正,提升图像整体亮度,完整代码如下:

# -*- coding:utf-8 -*-
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QLabel, QFileDialog
from PyQt5.QtCore import QRect,QCoreApplication,Qt
from PyQt5.QtGui import QPixmap,QImage
import cv2
import numpy as np


def adjust_gamma(image, gamma=1.0):
    '''gamma矫正'''
    invGamma = 1.0 / gamma
    table = np.array(
        [((i / 255.0) ** invGamma) * 255 for i in np.arange(0, 256)]
    ).astype("uint8")
    return cv2.LUT(image, table)


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        # 调整窗体
        self.resize(500, 300)  # 主窗体宽高设置
        self.setWindowTitle("示例程序")  # 主窗体名称
        # 创建2个图像标签
        self.preImgLabel = QLabel("", self)
        self.preImgLabel.setGeometry(QRect(30, 30, 200, 200))
        self.preImgLabel.setStyleSheet("background-color: rgb(232, 232, 232);")
        self.preImgLabel.setScaledContents(True)
        self.aftImgLabel = QLabel("", self)
        self.aftImgLabel.setGeometry(QRect(270, 30, 200, 200))
        self.aftImgLabel.setStyleSheet("background-color: rgb(232, 232, 232);")
        self.aftImgLabel.setScaledContents(True)
        # 创建2个按钮组件
        self.chooseBtn = QPushButton("选择图片", self)
        self.chooseBtn.clicked.connect(self.choosePic)
        self.chooseBtn.setGeometry(QRect(170, 250, 60, 30))
        self.processBtn = QPushButton("图片处理", self)
        self.processBtn.clicked.connect(self.imgProcess)
        self.processBtn.setGeometry(QRect(270, 250, 60, 30))
        
        self.imgName = ''

    def choosePic(self):
        """选择图片"""
        self.imgName, _ = QFileDialog.getOpenFileName(self, "打开图片", "", "*.jpg;;*.png;;All Files(*)")
        if self.imgName == '':
            return
        pix = QPixmap(self.imgName)
        self.preImgLabel.setPixmap(pix)
        self.preImgLabel.setStyleSheet("border: 2px solid blue")
        

    def imgProcess(self):
        """图片处理"""
        # 读取图像
        img = cv2.imread(self.imgName)  # OpenCV 读取图像
        if img is None:
            print('图像读取失败')
            return
        # gamma矫正
        img = adjust_gamma(img, gamma=1.8)
        # 转qt格式
        qtImg = QImage(img.data, img.shape[1], img.shape[0], QImage.Format_RGB888).rgbSwapped() 
        self.aftImgLabel.setPixmap((QPixmap.fromImage(qtImg)))  
        self.aftImgLabel.setStyleSheet("border: 2px solid red")


if __name__ == "__main__":
    """程序主入口"""
    QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) # 设置屏幕分辨率自适应
    app = QApplication(sys.argv)  # 创建应用
    main = MainWindow()  # 创建主窗体
    main.show()          # 显示主窗体
    sys.exit(app.exec()) # 进入主窗体生命周期

运行效果如本文开篇图片所示。

4、打包部署

我们最终希望交给用户是一个纯粹的exe可执行文件(可以包含一些dll之类的动态库或配置文件),用户不需要安装Python依赖,直接双击就可以运行展示。下面我们来实现最后的这个环节。

首选安装打包工具:

pip install pyinstaller auto-py-to-exe -i https://mirror.baidu.com/pypi/simple

在终端中运行:auto-py-to-exe,会自动打开浏览器,然后进入打包部署配置页面。对于本项目按照下图所示进行勾选即可:
在这里插入图片描述
最后单击执行即可。打包好的程序位于demo/output/main文件夹中,如下图所示:
在这里插入图片描述
其中main.exe就是最后的可执行程序,_internal就是该程序的依赖库。部署时将整个main文件夹拷贝到部署机器上运行即可。

部署运行时部分机器可能会出现下图所示错误:
在这里插入图片描述
这里只需要下载一个64位的api-ms-win-core-path-l1-1-0.dll文件然后将其拷贝到输出目录的main/_internal文件夹下面即可。

5、小结

使用PyQT开发界面程序可以充分利用python简洁易用的特性,开发效率较高。缺点就是部署文件夹比较大,并且代码的安全性(版权)要比C++等弱一些。


http://www.niftyadmin.cn/n/5306799.html

相关文章

JVM加载class文件的原理机制

1、JVM 简介 JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从“Hello World ”开始的,然后会写个复杂点class ,然后再找一些开源框架,比如Spring ,Hibernate 等等,再然后就开发…

java 音乐会售票平台系统Myeclipse开发mysql数据库struts2结构java编程计算机网页项目

一、源码特点 java 音乐会售票平台系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助struts2框架开发mvc模式,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发 环境为TOCAT7.0,Myeclipse8.5开发,数据…

关于kthread_stop的疑问(linux3.16)

线程一旦启动起来后,会一直运行,除非该线程主动调用do_exit函数,或者其他的进程调用kthread_stop函数,结束线程的运行。 之前找销毁内核线程的接口时,发现了kthread_stop这个接口。网上说这个函数能够销毁一个内核线程…

git本地创建分支并推送到远程关联起来

git本地创建分支并推送到远程关联起来 git本地基于当前分支创建个新的分支,然后推送到远程,并把本地新创建的分支和远程分支关联 在当前分支下,新建分支 git checkout -b test推送到远程仓库 git push origin test将本地分支和远程分支关联…

JS/JQ实现小程序/H5验证码页面

话不多说&#xff0c;先上效果图 核心代码 1、html/css关键代码 <div class"obtain-verification-code"><div class"obtain-verification-code-input-content"><input id"input-0" class"verification-code-input" m…

云计算复习笔记--期末

1、云计算的定义和本质&#xff1a; 云计算是一种按使用量付费的模式。云计算是分布式计算的一种。通过计算机网络&#xff08;多指因特网&#xff09;形成的计算能力极强的系统&#xff0c;可存储、集合相关资源并可按需配置&#xff0c;向用户提供个性化服务。 2、云计算服…

Open3D聚类算法

按照官网的例子使用聚类&#xff0c;发现结果是全黑的。 经过多次测试发现 eps3.3, min_points1这里是关键 min_points必须等于1否则无效果 import time import open3d as o3d; import numpy as np; import matplotlib.pyplot as plt#坐标 mesh_coord_frame o3d.geometry.Tria…

Python 中的==操作符 和 is关键字

Python是一种功能强大的通用编程语言&#xff0c;提供了各种比较值和对象的方法。其中包括操作符和is关键字&#xff0c;它们的用途不同&#xff0c;但由于它们有时可以达到相同的目的&#xff0c;所以经常会被混淆。在本文中&#xff0c;我们将深入研究和is之间的区别&#xf…