# AIImageTool **Repository Path**: lizhiLX/AITool ## Basic Information - **Project Name**: AIImageTool - **Description**: 本项目是一个基于Python 3.6+版本,使用Pyside6第三方库和腾讯云进行开发的智能图像处理应用程序。本项目的目的是通过Pyside6制作图形化界面方便用户操作和使用并调用腾讯云的AI云服务,实现对图像的处理。本项目的主要功能是卡片信息识别、人脸相似度检查、智能AI人像抠图 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2023-12-01 - **Last Updated**: 2025-03-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 项目说明 本项目是一个基于Python 3.6+版本,使用Pyside6第三方库和腾讯云进行开发的智能图像处理应用程序。本项目的目的是通过Pyside6制作图形化界面方便用户操作和使用并调用腾讯云的AI云服务,实现对图像的处理。本项目的主要功能是卡片信息识别、人脸相似度检查、智能AI人像抠图 **版权归属邯郸科技职业学院** **本项目用于参加2024年邯郸市职业院校学生创新创业大赛** 开源地址:[https://gitee.com/lizhiLX/AITool](https://gitee.com/lizhiLX/AITool) 预览: ![](./image/20231202121555.png) ![](./image/20231202121835.png) ![](./image/20231202122002.png) # 项目使用 * 根据[配置腾讯云身份凭证](#配置腾讯云身份凭证)获取相应的腾讯云身份凭证,并填入到key.json文件中 * 双击运行可执行文件,或者根据[环境搭建](#环境搭建)配置运行环境并运行本项目 # 环境搭建 **注意:请使用python3.6+版本!!** * 将项目拉取到本地 ```git git clone https://gitee.com/lizhiLX/AITool.git ``` 用pycharm或其它编辑器打开本项目 - 安装依赖 - 安装Pyside6依赖 ~~~pip pip install pyside6 -i https://pypi.tuna.tsinghua.edu.cn/simple ~~~ - 安装腾讯云SDK ```pip pip install tencentcloud-sdk-python -i https://pypi.tuna.tsinghua.edu.cn/simple ``` - 安装 Qt-Material ```pip pip install qt-material -i https://pypi.tuna.tsinghua.edu.cn/simple ``` - 配置Pycharm - 添加designer外部工具 1. 打开Pycharm->文件->设置->工具->外部工具 2. 点击加号 ![图片](./image/aa.png) 3. 填入必要参数 - 名称写入:Qt_designer - 程序写入:python安装的目录\\Lib\\site-packages\\PySide6\\designer.exe - 实参写入:`$FilePath$` - 工作目录写入:`$ProjectFileDir$` ![](./image/bb.png) 4. 点击确定 - 添加uic外部工具 1. 打开Pycharm->文件->设置->工具->外部工具 2. 点击加号 ![图片](./image/aa.png) 3. 填入必要参数 - 名称写入:Qt_uic - 程序写入:python安装的目录\\Scripts\\pyside6-uic.exe - 实参写入:`$FilePath$ -o $FileDir$\$FileNameWithoutExtension$.py` - 工作目录写入:`$ProjectFileDir$` ![](./image/cc.png) - 配置完成后双击.ui文件即可使用designer打开 ![](./image/dd.png) 右击 .ui文件 ->外部工具->Qt_uic即可编译ui文件为py文件 ![](./image/ee.png) # 配置腾讯云身份凭证 1. 访问[此链接](https://console.cloud.tencent.com/ocr/overview)登录腾讯云账号开通文字识别服务 2. 访问[此链接](https://console.cloud.tencent.com/aiface)登录腾讯云账号开通人脸比对服务 3. 访问[此链接](https://console.cloud.tencent.com/bda)登录腾讯云账号开通人体分割服务 4. 访问[此链接](https://console.cloud.tencent.com/cam/capi)点击新建密钥并下载保存csv文件 5. 打开下载的csv文件并查看 6. 将SecretId项填入工程key.json的SecretId中 7. 将SecretKey项填入工程key.json的SecretKey中 ![](./image/01.png) 8. **注意:千万不要泄露密钥的任何信息,否则后果自负** # 项目结构说明 - Components - ImageWidget.py - CardPage.py - FacePage.py - MaskPage.py - Forms - xx.ui - xx.ui - out - xx.jpg - xx.jpg - Utils - xx.py - main.py - MainWindow.py - key.json mian.py是程序的入口,运行此程序要从main.py开始运行 MainWindow.py是主窗口 key.json存放用户腾讯云秘钥 Forms用于存放自定义控件或窗口的ui文件 out用于存放生成的图片 Utils用于存放一些工具py文件 Components用于存放自定义控件 Components/ImageWidget.py为自定义图像框控件 Components/CardPage.py为卡片识别控件用于对身份证信息识别 Components/FacePage.py为人脸检查控件用于对人脸相似度检测 Components/MaskPage.py为智能抠图控件用与图片的一键抠图 # 代码分析 - main.py ```python import sys from PySide6.QtWidgets import QApplication from MainWindow import MainWindow if __name__ == '__main__': # 创建Qt应用实例 app = QApplication([]) # 创建主窗口 w = MainWindow() # 显示主窗口 w.show() # 监听用户操作(鼠标点击 键盘点击) sys.exit(app.exec()) ``` main.py的主要作用就是导入主窗口类并创建主窗口实例且显示主窗口,同时main.py是程序的入口程序执行要先从main.py开始执行 *** - MainWindow(主窗口类) ```python from PySide6.QtWidgets import QMainWindow from Forms.MainWindow import Ui_MainWindow from Components.CardPage import CardPage from Components.FacePage import FacePage from Components.MaskPage import MaskPage class MainWindow(QMainWindow): def __init__(self): # 对父类构造 super().__init__() # 加载主窗口的ui文件 self.ui = Ui_MainWindow() # 装载主窗口的ui self.ui.setupUi(self) # 创建新标签页标题设置为"卡片识别",并将CardPage实例添加到新标签页中 self.ui.tabWidget.addTab(CardPage(), '卡片识别') # 创建新标签页标题设置为"人脸相似度检测",并将FacePage实例添加到新标签页中 self.ui.tabWidget.addTab(FacePage(), '人脸相似度检测') # 创建新标签页标题设置为"AI人像抠图",并将MaskPage实例添加到新标签页中 self.ui.tabWidget.addTab(MaskPage(), 'AI人像抠图') ``` 主窗口MainWindow继承QMainWindow当主窗口被创建时开始加载主窗口的ui文件,并且把ui装载到主窗口中,为了实现分页的效果在主窗口中的ui文件中添加了QtabWidget控件,调用此控件的addTab方法可以添加标签页 ![](./image/20231202122326.png) 在本项目中需要添加三个标签页,分别为“卡片识别”、“人脸相似度检测”、“AI人像抠图”,这三个标签页分别对应CardPage、FacePage、MaskPage这三个自定义控件 *** - ImageWidget(图像框类) ```python from PySide6.QtWidgets import QWidget from PySide6.QtGui import QPaintEvent, QPixmap, QPainter from PySide6.QtCore import Qt class ImageWidget(QWidget): def __init__(self, parent=None): super().__init__() if parent is not None: self.setParent(parent) # 图片路径 self.image_path = '' # 设置图片路径 def setImagePath(self, path): # 设置要加载图片的路径 self.image_path = path # 更新窗口(会自动调用绘图事件) self.update() # 重写父类的绘图事件 def paintEvent(self, event: QPaintEvent) -> None: # 实例化一个画笔 painter = QPainter(self) # 如果图片路径不存在则终止绘制 if self.image_path == '': return # 根据图片路径加载图片 pixmap = QPixmap(self.image_path) # 设置图片的缩放 pixmap = pixmap.scaled(self.size(), Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation) # 设置画笔的抗锯齿 painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) # 使画笔开始绘制图片 painter.drawPixmap(0, 0, pixmap) ``` 因为在Pyside6中没有提供专门用于展示图片的控件,但是在CardPage、FacePage、MaskPage这三个自定义控件中都需要展示图片,所以需要自己定义一个图像框控件来展示图片。 实现思路:自定义一个类ImageWidget使其继承QWidget类,并重写paintEvent事件方法来达到图相框的效果。并且定义一个setImagePath方法可以供外部调用来设置图像路径。 在绘图事件方法中,需要实例化一个画笔对象来绘制图片。在绘制时要先判断一下图片路径是否存在,如果不存在则终止绘制,如果存在则使用QPixmap加载图片,加载完成后返回一个QPixmap对象,通过操作QPixmap对象设置图片的缩放来保证图片的大小不超过图相框的大小,最后设置画笔的抗锯齿效果,并让画笔把QPixmap加载的图片绘制出来 *** - CardPage(卡片识别控件类) ```python import base64 import json import os from PySide6.QtWidgets import QWidget, QFileDialog, QTableWidgetItem from Forms.CardPage import Ui_Form from Utils.AiCloud import cardOrc class CardPage(QWidget): def __init__(self, parent=None): super().__init__() if parent is not None: self.setParent(parent) # 加载CardPage的ui文件 self.ui = Ui_Form() # 装载ui到本对象 self.ui.setupUi(self) # 设置表格列为2列 self.ui.tableWidget.setColumnCount(2) # 设置表格的表头标题为“字段”和“信息” self.ui.tableWidget.setHorizontalHeaderLabels(['字段', '信息']) # 添加imageBase64属性用于存储IDCard图片的base64编码 self.imageBase64 = '' # 初始化所有的信号槽连接 self.initConnect() # 调用此方法将会初始化所有的信号槽的连接 def initConnect(self): # 连接“选择图片按钮”的clicked信号与selectImage方法的信号槽 self.ui.selectButton.clicked.connect(self.selectImage) # 连接“识别按钮”的clicked信号与createInfo方法的信号槽 self.ui.createButton.clicked.connect(self.createInfo) # 选择图片方法,此方法用于选择图片 def selectImage(self): # 创建一个打开文件对话框 file = QFileDialog() file.exec() # 把选择的路径赋值给path变量 path = file.selectedFiles()[0] # 设置图像框的图片路径 self.ui.ImageWidget.setImagePath(path) # 把选择的图片进行base64编码并存储在imageBase64属性中 with open(path, 'rb') as image: self.imageBase64 = base64.b64encode(image.read()).decode('utf-8') # 识别图片信息方法 def createInfo(self): # 判断图片base64编码是否存在,如果不存在则终止识别 if self.imageBase64 == '': return # 将图片的base64数据封装成字典,方便调用API传参 params = { "ImageBase64": self.imageBase64 } # 调用信息识别服务并拿到json格式的字符串将其转换成字典赋值给res变量 res = json.loads(cardOrc(params)) # 调用设置表格信息方法并把res作为参数传递,将数据渲染到表格中 self.setInfo(res) # 设置表格信息方法 def setInfo(self, res): pass ``` 当此控件被创建的时候会自动触发构造方法,在构造方法中会加载此控件的ui文件,并且会装载ui,装载完成后会初始化表格将其设置为两列表格,表头为“字段”和“信息”。同时添加一个imageBase64属性,此属性用于存放图片的base64编码,之后会调用initConnect方法初始化所有的信号槽连接 在initConnect方法中将”选择图片按钮“的点击信号连接到 selectImage 方法,将“识别按钮”的点击信号连接到 createInfo 方法中,这样当点击”选择图片按钮“时,就会执行 selectImage 方法来选择图片,当点击“识别按钮”时,就会调用 createInfo 方法来识别信息并渲染到表格中。 在createInfo方法中首先判断imageBase64是不是一个空字符串,如果是一个空字符串就终止识别,如果不是空字符串则继续执行。之后将imageBase64封装到字典中并调用卡片识别服务将字典作为参数传递进去拿到响应结果并将其转换成字典类型赋值给res变量,最后调用setInfo方法将res变量作为参数传递进去渲染响应数据 *** - FacePage(人脸检测控件类) ```python import base64 import json from PySide6.QtWidgets import QWidget, QFileDialog from Forms.FacePage import Ui_Form from Utils.AiCloud import FaceTest class FacePage(QWidget): def __init__(self, parent=None): super().__init__() if parent is not None: self.setParent(self) # 加载FacePage的ui文件 self.ui = Ui_Form() # 装载ui到本对象 self.ui.setupUi(self) # 添加imageABase64属性用于存储A图片的base64编码 self.imageABase64 = '' # 添加imageBBase64属性用于存储B图片的base64编码 self.imageBBase64 = '' # 初始化所有的信号槽连接 self.initConnect() # 调用此方法将会初始化所有的信号槽的连接 def initConnect(self): # 连接“选择图片按钮”的clicked信号与selectImageA方法的信号槽 self.ui.selectButtonA.clicked.connect(self.selectImageA) # 连接“选择图片按钮”的clicked信号与selectImageB方法的信号槽 self.ui.selectButtonB.clicked.connect(self.selectImageB) # 连接“检测按钮”的clicked信号与checkAB方法的信号槽 self.ui.checkButton.clicked.connect(self.checkAB) # 选择图片方法,此方法用于选择图片A def selectImageA(self): # 创建一个打开文件对话框 file = QFileDialog() file.exec() # 把选择的路径赋值给path变量 path = file.selectedFiles()[0] # 设置图像框A的图片路径 self.ui.ImageWidgetA.setImagePath(path) # 把选择的图片进行base64编码并存储在imageABase64属性中 with open(path, 'rb') as image: self.imageABase64 = base64.b64encode(image.read()).decode('utf-8') # 选择图片方法,此方法用于选择图片B def selectImageB(self): # 创建一个打开文件对话框 file = QFileDialog() file.exec() # 把选择的路径赋值给path变量 path = file.selectedFiles()[0] print(path) # 设置图像框B的图片路径 self.ui.ImageWidgetB.setImagePath(path) # 把选择的图片进行base64编码并存储在imageBBase64属性中 with open(path, 'rb') as image: self.imageBBase64 = base64.b64encode(image.read()).decode('utf-8') # 人脸相似度检测方法 def checkAB(self): # 判断imageABase64和imageBBase64是否为空字符串,如果是则终止检测 if self.imageABase64 == '' or self.imageBBase64 == '': return # 将imageABase64和imageBBase64封装到字典中,方便传参 params = { "ImageA": self.imageABase64, "ImageB": self.imageBBase64, "NeedRotateDetection": 1 } # 调用人脸检测服务并将params传递进去拿到响应结果转换成字典赋值给res res = json.loads(FaceTest(params)) # 更新label控件的显示的文本 self.ui.label.setText('相似度:{0}%'.format(res['Score'])) ``` 当此控件被创建的时候会自动触发构造方法,在构造方法中会加载此控件的ui文件,并且会装载ui,装载完成创建imageABase64和imageBBase64属性,这两个属性分别用于存放A图片与B图片的base64编码,之后会调用initConnect方法初始化所有的信号槽连接。 在initConnect方法中将”选择图片按钮“(A)的点击信号连接到 selectImageA 方法,将”选择图片按钮“(B)的点击信号连接到 selectImageB 方法,将“识别按钮”的点击信号连接到checkAB方法,这样当点击选择图片按钮A时就会调用 selectImageA方法选择图片并对选择的图片进行base64编码存放在imageABase64属性中,当点击选择图片按钮B时就会调用 selectImageB方法选择图片并对选择的图片进行base64编码存放在imageBBase64属性中,当点击识别按钮时会调用checkAB方法来检查两张图片人脸的相似度。 在checkAB方法中,首先判断imageABase64与imageBBase64是否为空字符串,如果是空字符则终止识别,如果不是则继续执行。将imageABase64与imageBBase64封装在字典中,之后调用人脸检测服务并将字典作为参数传递进去之后拿到json字符串格式的响应结果并转换成字典赋值给res变量,最后刷新label控件中的文本重新渲染响应数据 *** - MaskPage(智能抠图控件类) ```python import base64 import json import os import uuid from PySide6.QtWidgets import QWidget, QFileDialog from Forms.MaskPage import Ui_Form from Utils.AiCloud import MaskImage class MaskPage(QWidget): def __init__(self, parent=None): super().__init__() if parent is not None: self.setParent(parent) # 加载FacePage的ui文件 self.ui = Ui_Form() # 装载ui到本对象 self.ui.setupUi(self) # 添加imageBase64属性用于存储图片的base64编码 self.imageBase64 = '' # 初始化所有的信号槽连接 self.initConnect() # 调用此方法将会初始化所有的信号槽的连接 def initConnect(self): # 连接“选择图片按钮”的clicked信号与selectImage方法的信号槽 self.ui.selectButton.clicked.connect(self.selectImage) # 连接“抠图按钮”的clicked信号与selectImage方法的信号槽 self.ui.createButton.clicked.connect(self.createImage) def selectImage(self): # 创建一个打开文件对话框 file = QFileDialog() file.exec() # 把选择的路径赋值给path变量 path = file.selectedFiles()[0] # 设置图像框的图片路径 self.ui.originImage.setImagePath(path) # 把选择的图片进行base64编码并存储在imageBase64属性中 with open(path, 'rb') as image: self.imageBase64 = base64.b64encode(image.read()).decode('utf-8') def createImage(self): # 获取当前工作目录 current_directory = os.getcwd() # 判断out文件夹是否存在 if not os.path.exists(os.path.join(current_directory, 'out')): # 如果out文件夹不存在,则创建 os.makedirs(os.path.join(current_directory, 'out')) # 判断imageBase64是否为空字符串如果是则终止生成 if self.imageBase64 == '': return # 将图片的base64数据封装成字典,方便调用API传参 params = { "Image": self.imageBase64 } # 调用智能抠图服务并将params传递进去拿到响应结果转换成字典赋值给res res = json.loads(MaskImage(params)) # 将响应数据中的ResultImage键对应的值进行base64解码,拿到图片的二进制数据 image = base64.b64decode(res['ResultImage']) # 生成一个uuid作为图片的名字,保证图片名的唯一性防止输出图片时出现图片覆盖的情况 fileName = str(uuid.uuid4()) + '.png' # 将图片的二进制数据写入到out目录下 with open('./out/' + fileName, mode='wb') as file: file.write(image) # 设置图像框的图像路径,来显示生成的图像 self.ui.maskImage.setImagePath('./out/' + fileName) ``` 当此控件被创建的时候会自动触发构造方法,在构造方法中会加载此控件的ui文件,并且会装载ui,装载完成后添加imageBase64属性用于存储图片的base64编码,之后调用initConnect方法初始化所有的信号槽连接。 在initConnect方法中将”选择图片按钮“的点击信号连接到 selectImage 方法,将“抠图按钮”的点击信号连接到 createImage 方法中,这样当点击”选择图片按钮“时,就会执行 selectImage 方法来选择图片,并对图片进行base64编码保存到imageBase64属性中,当点击“识别按钮”时,就会调用 createImage 方法来对选择的图片进行AI抠图处理 在createImage方法中会首先判断是否存在out文件夹,如果不存在则创建out文件,之后判断imageBase64是否为空字符串如果为空字符串则终止抠图,如果不为空则继续,之后将imageBase64封装到字典中,之后调用智能抠图服务并将字典作为参数传递进去之后拿到json字符串格式的响应结果并将其转换成字典赋值给res变量。随后对响应结果ResultImage键对应的值进行base64解码拿到图片的二进制数据,并生成一个uuid作为图片名,防止输出图片时重名出现覆盖的情况,将二进制数据写入到out目录下,并设置图像框的图片路径来显示生成的图像