Pyqt5实现图像数据增强、图像分割、修改分割结果

这个软件是毕设课题,本科生的水平,大佬可以忽略了,但做毕设的时候觉得pyqt5相关的资料太少了,所以分享一下

主要功能

  1. 数据增强 HE,CLAHE,依赖skimage;
  2. 图像分割 阈值分割:OTSU,double threshold,依赖skimage;基于深度学习的分割方法:U-Net
  3. 修改分割结果 单图 双图;

界面设计

主界面的设计是用Qt Creator可视化设计后再用pyrcc转成py文件,业务逻辑运用了信号与槽,主要是自动关联的槽函数,模仿了labelme的设计,图像显示部分central widget,在QWidget上放了一个QLabel后,把QWidget手动改成QLabel,实现两个label的叠放,完成了遮罩,工具栏和菜单按钮的使能根据图片的状态自适应,如图片数量、原图是否修改、是否进行分割、分割后是否保存,这些都通过建立字典来实现

双图和单图修正因为需要在工具栏中添加显示颜色的label小方块,显示缩放值的文本框,所以没有使用可视化设计,重写了工具栏,把布局调好后用toolbar里的addwidget

进度条窗体可以用progressdialog,我用的对话框,QThread类,值的改变通过在不同的地方发信号,类的初始化里面有信号,调用类的时候就要把槽函数传进去,在类里连接,QT里没有让线程停下来的方法,要设置一个标志变量,放到耗时较长的循环前,每次循环前检测这一变量,不符合条件时停下

遮罩

分割图会以遮罩覆盖在原图上
底层的QLabel,setpixmap为原始图片
生成分割图后,将图像由nd.array转为QImage,改成ARGB32格式,再遍历分割图,黑色的像素点置为透明,白色的点设置为用户选取的颜色和透明度,在初始文件config.txt可以读取
setting里可以修改网络参数和遮罩参数,点击save对参数合法性进行检测,全部合法后保存到文件中,用之前先读取config拿到用户最新设置的参数
CLAHE

人工修正

打开人工修正窗口,主界面关闭,人工修正窗口关闭,主界面再重新打开
图片的显示利用drawevent,单图是先draw原图再draw分割图,双图是两边分别显示原图和分割图,打开时默认是浏览模式,按住鼠标移动相当于滑动滑动条,双击左键或右键进入编辑模式,编辑模式下左键按下编辑前景,右键按下编辑背景
图片传递考虑了多种情况,如果原图已经增强,将增强后的原图以QImage类型传递,如果图像已经分割,如果没有保存将分割图以QImage传递,如果已经保存则传递保存路径,对分割图的修改也要保存到同一路径
没有编辑痕迹时save不可用,包括没有编辑和编辑痕迹全部被撤销,在主界面中没有保存的分割结果可以在人工修正中保存,保存后发射信号,改变图片的状态

错误提醒

错误提醒窗体采用QMessagebox,根据不同的提醒类型选择information/warning/about,所以错误提醒窗体,包括进度条都设置了setWindowModality(Qt.ApplicationModal),在这些窗体打开时不能进行其他操作

导出与导入

导出

另存原图和分割图时会自动生成文件名,原图再原文件名后加_enhance,分割图加_label,输出格式固定为png。数据增强后的原图转化为灰度图后再保存,便于对增强后的原图分割,同时将原图的保存路径添加到字典中,方便在多图处理时找到保存的原图,工具栏上的save对二者都进行保存,先判断图片状态,如只修改原图就指保存原图

导入

open打开单张图片,open dir打开同级目录下的图片,不包括子文件夹,如果有满足_label命名的图片,默认为标注图,将其以遮罩显示在对应的原图上,文件名并不加入文件列表,在文件列表中已经存在同名文件时会有提醒,同时必须满足png jpg jpeg bmp这四种后缀名,没有时也会报错

github地址:https://github.com/Tianns/imageseg.git
欢迎大家fork我,unet的模型参数涉密 暂时没有上传

下面是一个简单的PyQt5界面实现U2Net图像分割的例子,使用PyTorch实现。 ``` import sys import os import numpy as np from PIL import Image from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QFileDialog from PyQt5.QtGui import QPixmap import torch import torchvision.transforms as transforms from model.u2net import U2NET class MainWindow(QMainWindow): def __init__(self): super().__init__() # 创建UI界面 self.initUI() # 加载模型 self.model = U2NET() self.model.load_state_dict(torch.load("u2net.pth", map_location=torch.device('cpu'))) self.model.eval() def initUI(self): # 设置窗口标题和大小 self.setWindowTitle("U2Net Image Segmentation") self.setGeometry(100, 100, 800, 600) # 创建标签和按钮 self.label = QLabel(self) self.label.setGeometry(25, 50, 750, 450) self.label.setStyleSheet("border: 1px solid black;") self.button = QPushButton("Select Image", self) self.button.setGeometry(25, 525, 150, 50) self.button.clicked.connect(self.selectImage) self.button2 = QPushButton("Segment Image", self) self.button2.setGeometry(200, 525, 150, 50) self.button2.clicked.connect(self.segmentImage) def selectImage(self): # 打开文件对话框,选择要处理的图像 options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName(self,"QFileDialog.getOpenFileName()", "","All Files (*);;Images (*.png *.jpg *.jpeg)", options=options) if fileName: # 加载图像并显示在标签上 pixmap = QPixmap(fileName) pixmap = pixmap.scaled(750, 450) self.label.setPixmap(pixmap) # 将图像转换为PyTorch tensor格式 self.input_image = Image.open(fileName).convert("RGB") self.transform = transforms.Compose([transforms.Resize((320, 320)), transforms.ToTensor(), transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))]) self.input_tensor = self.transform(self.input_image).unsqueeze(0) def segmentImage(self): # 对选择的图像进行分割 with torch.no_grad(): output_tensor = self.model(self.input_tensor) # 将输出转换为PIL Image格式 output_tensor = output_tensor.squeeze().numpy() output_tensor = np.where(output_tensor > 0.5, 1.0, 0.0) output_image = Image.fromarray((output_tensor * 255).astype(np.uint8)).convert("L") # 显示分割结果 output_pixmap = QPixmap.fromImage(ImageQt(output_image)) output_pixmap = output_pixmap.scaled(750, 450) self.label.setPixmap(output_pixmap) if __name__ == "__main__": # 创建应用程序和主窗口 app = QApplication(sys.argv) mainWindow = MainWindow() mainWindow.show() sys.exit(app.exec_()) ``` 在上面的代码中,我们首先创建了一个`MainWindow`类,它继承自`QMainWindow`类,并重写了`initUI`方法来创建UI界面。在`initUI`方法中,我们创建了一个标签和两个按钮,其中一个用于选择图像,另一个用于对图像进行分割。 在选择图像按钮的回调函数`selectImage`中,我们使用`QFileDialog`打开一个文件对话框,让用户选择要处理的图像。然后,我们使用`PIL`库来加载图像,并将其转换为PyTorch tensor格式。在转换过程中,我们使用了`transforms`模块来对图像进行缩放、标准化等预处理操作。 在对图像进行分割的按钮回调函数`segmentImage`中,我们将输入张量传递给已加载的U2Net模型,并得到输出张量。然后,我们将输出张量转换为PIL Image格式,并将其显示在标签上。在转换过程中,我们使用了NumPy来将输出张量转换为二值图像,使用`PIL`库将其转换为灰度图像,并使用`QPixmap`将其转换为Qt图像格式。 最后,我们在`__main__`函数中创建了应用程序和主窗口,并调用`show`方法来显示窗口。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值