diff --git a/Pwindow.py b/Pwindow.py deleted file mode 100644 index 51b2a5d..0000000 --- a/Pwindow.py +++ /dev/null @@ -1,969 +0,0 @@ -import cv2 -import numpy as np -import random -import tkinter -import tkinter as tk -import matplotlib.pyplot as plt -import albumentations as A -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg -from tkinter.messagebox import showinfo, showwarning -from tkinter import filedialog -from PIL import Image,ImageTk -from tkinter.filedialog import askopenfilename, askopenfilenames, asksaveasfilename, askdirectory - - -# ---------------------------------------------------------------------- -plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文 -plt.rcParams['axes.unicode_minus']=False #用来正常显示负号 -picSize=400 -img_open = None -img_result = None -img_empty = cv2.imread('data/image/OIP-C.jpg',0) - - -# ---------------------------------------------------------------------- -# 几何变化类 -# 水平翻转 -def filp_h(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - transform = A.HorizontalFlip(p=1) - - img_result = transform(image=np.array(img_open)) - img_result = img_result['image'] - placePic2(img_result,'水平翻转后') - -# 垂直翻转 -def flip_v(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - transform = A.VerticalFlip(p=1) - - img_result = transform(image=np.array(img_open)) - img_result = img_result['image'] - - placePic2(img_result,'垂直翻转后') - -# 缩放 -def resize(): - - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - paraLists = [["水平方向缩放后大小", 224], ["垂直方向缩放后大小", 224]] - paraW = paraWindow(root, "请设置水平和垂直方向的缩放尺寸", paraLists) - - h = int(paraW.paraLists[0][1]) - w = int(paraW.paraLists[1][1]) - - transform = A.Resize(h,w) - img_result = transform(image=np.array(img_open)) - img_result = img_result['image'] - - placePic2(img_result,'缩放后') - -# 旋转(可选择旋转角度) -def roate(): - - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - paraLists = [['请设置旋转角度',30]] - paraW = paraWindow(root, "旋转图片", paraLists) - - angle = int(paraW.paraLists[0][1]) - - transform = A.Rotate(angle) - img_result = transform(image=np.array(img_open),p=1) - img_result = img_result['image'] - - placePic2(img_result,'旋转后') - -# 裁剪(裁剪方式:centercrop、randomcrop和cutout) -def Centercrop(): - - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - paraLists = [["水平方向裁剪后大小", 224], ["垂直方向裁剪后大小", 224]] - paraW = paraWindow(root, "请设置水平和垂直方向的裁剪后尺寸", paraLists) - - h = int(paraW.paraLists[0][1]) - w = int(paraW.paraLists[1][1]) - - transform = A.CenterCrop(h, w,p=1) - img_result = transform(image=np.array(img_open)) - img_result = img_result['image'] - - placePic2(img_result,'中心裁剪后') - -def Randomcrop(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - paraLists = [["水平方向缩放后大小", 224], ["垂直方向缩放后大小", 224]] - paraW = paraWindow(root, "请设置水平和垂直方向的缩放尺寸", paraLists) - - h = int(paraW.paraLists[0][1]) - w = int(paraW.paraLists[1][1]) - - transform = A.RandomCrop(h, w,p=1) - img_result = transform(image=np.array(img_open)) - img_result = img_result['image'] - - placePic2(img_result,'随机裁剪后') - -# 反向裁剪(随机选择区域) -def cutout(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - h,w,c = img_open.shape - # 后续是原图和mask相乘,所以初始化为0 - # 不需要裁剪的区域就不变,裁剪的区域变成0 - mask = np.ones_like(img_open) - print(mask) - x = np.random.randint(0,w) - y = np.random.randint(0,h) - - paraLists = [['相对原图裁剪区域的大小', 0.2]] - paraW = paraWindow(root, "请设置具体参数", paraLists) - # p = int(paraW.paraLists[0][1]) - s = float(paraW.paraLists[0][1]) - - w_cut = int(s*w) - h_cut = int(s*h) - - x1 = max(x - w_cut // 2, 0) # 计算裁剪的左上角坐标 - x2 = min(x1 + w_cut, w) # 计算裁剪的右下角坐标 - y1 = max(y - h_cut // 2, 0) - y2 = min(y1 + h_cut, h) - mask[y1:y2, x1:x2, :] = 0 # 将裁剪区域内像素值置为 0 - - - img_result = img_open * mask # 与原始图像按元素相乘,得到 Cutout 后的图像 - print(img_result[y1:y2, x1:x2, :]) - placePic2(img_result,text2='反向随机裁剪后') - -# 对比度、饱和度、亮度、色调变化 -def ColorJitter(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - paraLists = [["亮度", 0], ["色调", 0],['对比度',0],['饱和度',0]] - paraW = paraWindow(root, "请设置具体参数", paraLists) - - - brightness = float(paraW.paraLists[0][1]) # 亮度 - hue = float(paraW.paraLists[1][1]) # 色调 - contrast = float(paraW.paraLists[2][1]) # 对比度 - saturation = float(paraW.paraLists[3][1]) # 饱和度 - - transform = A.ColorJitter(brightness=brightness,hue=hue,saturation=saturation,contrast=contrast,p=1) - img_result = transform(image=np.array(img_open)) - img_result = img_result['image'] - placePic2(img_result) - -# 转换成灰度图 -def ToGray(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - placePic2(img_gray,'灰度图') - -# 通道分离 -def split_channel(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - ''' 现在 的img_open 是RGB的''' - R,G,B = cv2.split(img_open) - paraLists = [['分离通道', 0]] - paraW = paraWindow(root, "012分别代表RGB", paraLists) - dict = {'0':R,'1':G,'2':B} - img_result = dict[str(int(paraW.paraLists[0][1]))] - placePic2(img_result,'分离通道后') - -# 随机模糊 -def Blur(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - paraLists = [['模糊的次数',3]] - paraW = paraWindow(root, "请设置具体参数", paraLists) - count = int(paraW.paraLists[0][1]) - transform = A.Blur(blur_limit=count,p=1) - img_result = transform(image=np.array(img_open)) - img_result = img_result['image'] - placePic2(img_result) - -# 高斯滤波 -def Gaussblur(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - paraLists = [['模糊的次数', 3]] - paraW = paraWindow(root, "请设置具体参数", paraLists) - count = int(paraW.paraLists[0][1]) - transform = A.GaussianBlur(blur_limit=count, p=1) - img_result = transform(image=np.array(img_open)) - img_result = img_result['image'] - placePic2(img_result,text2='经过高斯模糊后') - -# 中值滤波 -def Medianblur(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - paraLists = [['模糊的次数', 3]] - paraW = paraWindow(root, "请设置具体参数", paraLists) - count = int(paraW.paraLists[0][1]) - transform = A.MedianBlur(blur_limit=count, p=1) - img_result = transform(image=np.array(img_open)) - img_result = img_result['image'] - placePic2(img_result,text2='经过中值滤波后') - -# 添加高斯噪声 -def add_gaussian_noise(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - paraLists = [['请输入均值', 0],['请输入标准差',30]] - paraW = paraWindow(root, "请设置具体参数", paraLists) - mean = int(paraW.paraLists[0][1]) - sigma = int(paraW.paraLists[1][1]) - - # 生成高斯噪声矩阵 - row, col, ch = img_open.shape - gaussian = np.random.randn(row, col, ch) * sigma + mean - gaussian = gaussian.reshape(row, col, ch) - img_result = img_open + gaussian - # 转换数据类型为8位无符号整数类型 - img_result = cv2.convertScaleAbs(img_result) - placePic2(img_result,text2='添加高斯噪声后') - -# 添加椒盐噪声 -def add_salt_and_pepper_noise(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - paraLists = [['百分比', 0]] - paraW = paraWindow(root, "请设置具体参数", paraLists) - percentage = int(paraW.paraLists[0][1]) - - # 确保百分比在 0 到 100 之间 - if percentage < 0 or percentage > 100: - showwarning(title='警告', message='百分比必须在 0 到 100 之间!') - return - - # 生成椒盐噪声矩阵 - row, col, ch = img_open.shape - noise = np.zeros((row, col, ch), np.uint8) - for i in range(row): - for j in range(col): - rand = np.random.randint(0, 100) - if rand < percentage: - noise[i][j] = [0, 0, 0] - elif rand > 100 - percentage: - noise[i][j] = [255, 255, 255] - else: - noise[i][j] = img_open[i][j] - - # 将椒盐噪声矩阵添加到原始图像中 - img_result = cv2.add(img_open, noise) - - placePic2(img_result,text2='添加椒盐噪声后') - -# 添加均值噪声 -def add_mean_noise(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - paraLists = [['均值', 0], ['标准差', 30]] - paraW = paraWindow(root, "请设置具体参数", paraLists) - mean = int(paraW.paraLists[0][1]) - std_dev = int(paraW.paraLists[1][1]) - - # 生成均值噪声矩阵 - row, col, ch = img_open.shape - noise = np.random.normal(mean, std_dev, (row, col, ch)).astype(np.uint8) - - # 将均值噪声矩阵添加到原始图像中 - img_result = cv2.add(img_open, noise) - - placePic2(img_result,text2='添加均值噪声后') - -# 使用sobel算子进行锐化 -def sobel(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - kernelx1 = np.array([[-1,-2,-1],[0,0,0],[1,2,1]], dtype=int) - kernely1 = np.array([[-1,0,1],[-2,0,2],[-1,0,1]], dtype=int) - x1 = cv2.filter2D(img_gray, cv2.CV_16S, kernelx1) - y1 = cv2.filter2D(img_gray, cv2.CV_16S, kernely1) - absX1 = cv2.convertScaleAbs(x1) - absY1 = cv2.convertScaleAbs(y1) - img_result = cv2.addWeighted(absX1, 0.5, absY1, 0.5, 0) - placePic2(img_result) - -# 使用Prewitt算子进行锐化 -def Prewitt(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - kernelx1 = np.array([[-1,0,1],[-1,0,1],[-1,0,1]], dtype=int) - kernely1 = np.array([[-1,-1,1],[0,0,0],[1,1,1]], dtype=int) - x1 = cv2.filter2D(img_gray, cv2.CV_16S, kernelx1) - y1 = cv2.filter2D(img_gray, cv2.CV_16S, kernely1) - absX1 = cv2.convertScaleAbs(x1) - absY1 = cv2.convertScaleAbs(y1) - img_result = cv2.addWeighted(absX1, 0.5, absY1, 0.5, 0) - placePic2(img_result) - -# 使用robert算子进行锐化 -def robert(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - kernelx1 = np.array([[-1, 0], [0, 1]], dtype=int) - kernely1 = np.array([[0, -1], [1, 0]], dtype=int) - x1 = cv2.filter2D(img_gray, cv2.CV_16S, kernelx1) - y1 = cv2.filter2D(img_gray, cv2.CV_16S, kernely1) - absX1 = cv2.convertScaleAbs(x1) - absY1 = cv2.convertScaleAbs(y1) - img_result = cv2.addWeighted(absX1, 0.5, absY1, 0.5, 0) - placePic2(img_result) - -# 直方图均衡化 -def equalhist(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - # 说明是灰度图像 - if len(img_open)==2: - img_result = cv2.equalizeHist(img_open) - # RGB图像分别对每个通道都均衡化 然后在 合并 - else: - b,g,r = cv2.split(img_open) - b_eq = cv2.equalizeHist(b) - g_eq = cv2.equalizeHist(g) - r_eq = cv2.equalizeHist(r) - - img_result = cv2.merge([b_eq,g_eq,r_eq]) - placePic2(img_result) - -# 叠加图片操作 -def mixup(): - global img_open, img_gray, img_result - - if img_open is None: - showwarning(title='警告', message='请先在文件菜单下打开图片!') - return - - img_show1 = img_open - # 读取另一张图片 - path = askopenfilename(title='打开另一张图片') - - if path!=0 and path!='': - img_show2 = cv_imread(path) - - if img_show2 is not None: - placePic2(img_show2) - else: - placePic2(img_empty) - showwarning(title='警告',message='请打开第二张图片') - - # 下面进行mixup操作 - paraLists = [['请输入一张图片所占比列', 0.5]] - paraW = paraWindow(root, "请设置具体参数", paraLists) - - # 判断两张图片的shape 是否相同 不相同则都取小的那边 - if img_show1.shape[:-1]!=img_show2.shape[:-1]: - showwarning(title='警告',message='两张图片大小不一样,会自动做裁剪使大小相同') - if img_show1.shape[0] > img_show2.shape[0]: - h = img_show2.shape[0] - else: - h = img_show1.shape[0] - - if img_show1.shape[1] > img_show2.shape[1]: - w = img_show2.shape[1] - else: - w = img_show1.shape[1] - img_show1 = cv2.resize(img_show1,(h,w)) - img_show2 = cv2.resize(img_show2,(h,w)) - - # 判断图片的channel是否相同,如果不相同 在全部转换为 RGB的 - if len(img_show1)==2: - img_show1 = cv2.cvtColor(img_show1,cv2.COLOR_GRAY2RGB) - if len(img_show2)==2: - img_show2 = cv2.cvtColor(img_show1,cv2.COLOR_GRAY2RGB) - alpha = float(paraW.paraLists[0][1]) - print(alpha) - # 这个方法需要两张图片的大小相同 需要做个resize操作 - img_result = cv2.addWeighted(img_show1,alpha,img_show2,1-alpha,0) - cv_show('after mixup',img_result) - - -# ---------------------------------------------------------------------- -def cv_show(name,img): - - # 打开文件后会有img_open,img_gray的信息,img_result指进行操作后的可视化结果 - # 图片很大时需要进行resize - h,w = img.shape[:2] - if h>1000 or w>1000: - img = cv2.resize(img,dsize=None,fx=0.8,fy=0.8) - - cv2.imshow(name,img) - cv2.waitKey(0) - cv2.destroyAllWindows() - -def cv_imread(filename,colorMode=cv2.IMREAD_COLOR): - - # 读取文件路径中带汉字的图片,替代cv2.imread(filename) - # :param filename: 需要读取的文件 - # :param colorMode: 彩色模式 - # :return: 读取的图片 - - return cv2.imdecode(np.fromfile(filename, dtype=np.uint8), colorMode) - -def cv_imwrite(path, img): - - # 解决路径中有汉字的图片保存问题 - # :param path: 保存的路径 - # :param img: 保存的图片 - - cv2.imencode('.jpg', img)[1].tofile(path) - -def placePic1(img_show, text1="原始图像"): - - # 将打开的初始图像放置在左边窗格 - # :param img_show: 需要显示的图片 - # :param text1: 图片说明 - - global picSize - if img_show is None: - showwarning(title='警告', message='未打开图片!') - return - img = img_show.copy() - if len(img.shape) > 2: - img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) - height, width = img.shape[:2] - scaling = max(width, height) / picSize - newH = int(height / scaling) - newW = int(width / scaling) - img0 = Image.fromarray(img) # 由OpenCV图片转换为PIL图片格式 - img0 = img0.resize((newW, newH)) - img0 = ImageTk.PhotoImage(img0) - myWindow.originalText.set(text1) - myWindow.label3.config(image=img0) - myWindow.label3.image = img0 - myWindow.label3.place(relx=0.25, rely=0.40, width=picSize, height=picSize, anchor=tkinter.CENTER) # 设置绝对座标 - -def placePic2(img_show, text2="处理结果图", RGB=True): - - # 将处理结果图像放置在右边窗格 - # :param img_show: 需要显示的图像 - # :param text2: 图像文字说明 - # :param RGB: 是否转换成RGB,默认转换 - - global picSize, img_result - if img_show is None: - showwarning(title='警告', message='没有结果图片!') - return - img = img_show.copy() - if len(img.shape) > 2 and RGB: - img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) - height, width = img.shape[:2] - # img = PointProcessing.global_linear_transmation(img) - scaling = max(width, height) / picSize - newH = int(height / scaling) - newW = int(width / scaling) - img0 = Image.fromarray(img) # 由OpenCV图片转换为PIL图片格式 - img0 = img0.resize((newW, newH)) - img0 = ImageTk.PhotoImage(img0) - myWindow.resultText.set(text2) - myWindow.label4.config(image=img0) - myWindow.label4.image = img0 # 通过标签来显示图片,使用ImageTK把img转成tk可以接收的形式 - myWindow.label4.place(relx=0.75, rely=0.40, width=picSize, height=picSize, anchor=tkinter.CENTER) - -def Choosepic(): - # 打开文件选择对话框,并读取图片文件,存放在img_open全局变量中 - global picSize, path_, img_open, img_gray, img_empty - path_ = askopenfilename(title="打开需要处理的图片") - # path.set(path_) - if path_ != 0 and path_ != '': - img_open = cv_imread(path_) # 读取文件路径中有汉字的图片文件,读取的是RGB图像 - img_gray = cv2.cvtColor(img_open,cv2.COLOR_BGR2GRAY) - if img_open is not None: - placePic1(img_open) - else: - placePic1(img_empty) - showwarning(title='警告', message='无图片!') - else: - img_open = None - img_gray = None - placePic1(img_empty) - showwarning(title='警告', message='未选择图片!') - -def Savepic(): - # 打开文件对话框,将img_result图片保存到指定文件 - global img_result - if img_result is not None: - fname = asksaveasfilename(title='保存文件', defaultextension='default.jpg',filetypes=[("JPG", ".jpg")]) - if fname: - cv_imwrite(str(fname), img_result) - showinfo(title='提示', message='图片已保存!') - else: - showwarning(title='警告', message='请先输入文件名!') - else: - showwarning(title='警告', message='请先处理图片!') - -def initWindows(): - # 将系统界面恢复到初始界面,并不清除结果图片 - myWindow.setVisibleLeft() - myWindow.setVisibleRight0() - myWindow.hideFig0() - myWindow.hideFig1() - - if img_result is not None: - placePic2(img_result) - -class ImageApp: - global picSize - - def __init__(self, master): - self.master = master - self.master.title("图像多功能增强可视化窗口") - - # 界面布局 - self.init_menu(self.master) # 初始化菜单 - self.init_widget(self.master) # 初始化需要用的控件(两个画布) - self.setVisibleLeft() # 显示左窗格 - self.setVisibleRight0() # 显示右窗格 - - self.hideFig0() # 隐藏左窗格的画布myCanvas0 - self.hideFig1() # 隐藏右窗格的画布myCanvas1 - - def init_widget(self, master): - self.originalText = tkinter.StringVar() - self.label1 = tkinter.Label(master, textvariable=self.originalText, font=("song", 12)) - self.originalText.set("原始图像") - - self.label3 = tkinter.Label(master, bg='gray86') # 用于显示原始图像,背景颜色设置成灰色 - - self.resultText = tkinter.StringVar() - self.label2 = tkinter.Label(master, textvariable=self.resultText, font=("song", 12)) - self.resultText.set("处理结果图") - - self.label4 = tkinter.Label(master, bg='gray86') # 用于显示处理结果,背景颜色设置成灰色 - - self.explainText = tkinter.StringVar() - - self.myFig0 = plt.figure(figsize=(4, 4), facecolor='#dddddd') - self.myCanvas0 = FigureCanvasTkAgg(self.myFig0, master) - # myfig1在下边窗格的画布中显示多张包含图片的注释说明 - self.myFig1 = plt.figure(figsize=(9, 1.8), facecolor='lightgray') - # myfig2在下边窗格中显示说明与单张图片 - self.myFig2 = plt.figure(figsize=(4.5, 1.8), facecolor='lightgray') - self.myCanvas1 = FigureCanvasTkAgg(self.myFig1, master) - self.myCanvas2 = FigureCanvasTkAgg(self.myFig2, master) - - def init_menu(self,master): - - # 创建菜单和其内容 - menubar = tk.Menu(master) # 创建菜单对象 - - # 创建菜单内容 后面加command 可以创建子菜单 到时候看看需不需要 - fmenu_file = tk.Menu(master) # 文件 - fmenu_file.add_command(label='打开',command=Choosepic) - fmenu_file.add_command(label='保存处理结果', command=Savepic) - fmenu_file.add_separator() # 添加一条分隔线 - fmenu_file.add_command(label='退出',command=quit) - - # 几何变换 - fmenu_geo = tk.Menu(master) - fmenu_geo.add_command(label='水平翻转', command=filp_h) - fmenu_geo.add_command(label='垂直翻转', command=flip_v) - fmenu_geo.add_command(label='旋转', command=roate) - fmenu_geo.add_command(label='缩放', command=resize) - - # 给裁剪菜单再次创建子菜单 - submenu_crop = tk.Menu(fmenu_geo) - fmenu_geo.add_cascade(label='裁剪',menu=submenu_crop) - submenu_crop.add_command(label='中心裁剪',command=Centercrop) - submenu_crop.add_command(label='随机裁剪', command=Randomcrop) - submenu_crop.add_command(label='反向随机裁剪', command=cutout) - - # 颜色空间变换 - fmenu_sp = tk.Menu(master) - fmenu_sp.add_command(label='对比度变换',command=ColorJitter) - fmenu_sp.add_command(label='亮度变换', command=ColorJitter) - fmenu_sp.add_command(label='饱和度变换', command=ColorJitter) - fmenu_sp.add_command(label='色调',command=ColorJitter) - fmenu_sp.add_command(label='通道分离', command=split_channel) - fmenu_sp.add_command(label='灰度图', command=ToGray) - fmenu_sp.add_command(label='直方图均衡化', command=equalhist) - - # 像素点操作 - fmenu_pix = tk.Menu(master) # 创建像素点操作的主菜单 - submenu_blur = tk.Menu(fmenu_pix) # 模糊子菜单 - fmenu_pix.add_cascade(label='模糊',menu=submenu_blur) # 把模糊子菜单加到模糊下面 - # 给模糊子菜单加子菜单 - submenu_blur.add_command(label='高斯滤波',command=Gaussblur) - submenu_blur.add_command(label='随机模糊', command=Blur) - submenu_blur.add_command(label='中值滤波', command=Medianblur) - - submenu_sh = tk.Menu(fmenu_pix) - fmenu_pix.add_cascade(label='锐化',menu=submenu_sh) - # 给锐化加子菜单 - submenu_sh.add_command(label='robort算子',command=robert) - submenu_sh.add_command(label='Prewitt算子',command=Prewitt) - submenu_sh.add_command(label='Sobel算子',command=sobel) - - submenu_noise = tk.Menu(fmenu_pix) - fmenu_pix.add_cascade(label='添加噪声',menu=submenu_noise) - # 给添加噪声加子菜单 - submenu_noise.add_command(label='高斯噪声',command=add_gaussian_noise) - submenu_noise.add_command(label='椒盐噪声',command=add_salt_and_pepper_noise) - submenu_noise.add_command(label='均值噪声',command=add_mean_noise) - - # 基于多张图片 - fmenu_mul = tk.Menu(master) - fmenu_mul.add_command(label='mixup',command=mixup) - - # 将菜单内容 添加到menubar - menubar.add_cascade(label="文件", menu=fmenu_file) - menubar.add_cascade(label="几何变化", menu=fmenu_geo) - menubar.add_cascade(label="颜色空间变换", menu=fmenu_sp) - menubar.add_cascade(label="频域像素点操作", menu=fmenu_pix) - menubar.add_cascade(label='基于多张图片',menu=fmenu_mul) - - # 整体显示 - master.config(menu=menubar) - - def setVisibleLeft(self): - # label1是文字,label3目前是空只是占了位置,且背景颜色是灰色,需要放图片 - - self.label1.place(relx=0.25, rely=0.04, anchor=tkinter.CENTER) # 设置相对座标 - self.label3.place(relx=0.25, rely=0.40, width=picSize, height=picSize,anchor=tkinter.CENTER) # 设置绝对座标 - - def setVisibleRight0(self): - # 右边窗格重叠的显示之一(right0) - # right0一般算法结果显示窗格 - # right1-用于显示车牌识别结果 - # myFig0-使用mayplot显示运行结果图片 - # label2 是文字,label4目前是空只是占了位置 且背景颜色是灰色,需要放图片 - - self.label2.place(relx=0.75, rely=0.04, anchor=tkinter.CENTER) - self.label4.place(relx=0.75, rely=0.40, width=picSize, height=picSize,anchor=tkinter.CENTER) - - def setVisibleBottom(self): - - # 下边窗格的重叠显示之一(label5) - # label5-仅显示文字说明 - # myFig1-用matplot显示多个文字图片 - # explain-左边是label5,右边是myFig2 - - self.label5.place(relx=0.50, rely=0.86, width=900, height=180,anchor=tkinter.CENTER) - self.hideFig1() - self.hideExplain() - - def hideFig0(self): - self.myCanvas0.get_tk_widget().place_forget() # 隐藏画布self - - def hideFig1(self): - self.myCanvas1.get_tk_widget().place_forget() # 隐藏画布self - - def hideExplain(self): - self.label5.config(wraplength=850) - self.myCanvas2.get_tk_widget().place_forget() # 隐藏画布self(暂时隐藏,用的时候可以用place方法恢复) - - # 有的功能还需要选择具体参数,这个时候需要弹出一个小窗口给参数,并获取这些参数值,给具体的变化 - - -# ---------------------------------------------------------------------- -class paraWindow(tkinter.Toplevel): - - # 多行一列的参数设置窗口 - def __init__(self, root, title = None, paraLists=[]): - # Constructor - self.root = root - self.paraLists=paraLists - self.names = locals() #动态组件 - tkinter.Toplevel.__init__(self,root) - if title: - self.title(title) - # 创建对话框的主体内容 - frame = tkinter.Frame(self) - # 调用init_widgets方法来初始化对话框界面 - self.initial_focus = self.init_widgets(frame) - frame.pack(padx=5, pady=5) - # 根据modal选项设置是否为模式对话框 - self.grab_set() #重要,必须是模式对话框 - # 为"WM_DELETE_WINDOW"协议使用self.cancel_click事件处理方法 - self.protocol("WM_DELETE_WINDOW", self.cancel_click) - # 根据父窗口来设置对话框的位置 - self.geometry("+%d+%d" % (root.winfo_rootx() + 100, root.winfo_rooty() + 100)) - # 让对话框获取焦点 - self.initial_focus.focus_set() - self.wait_window(self) - - def init_widgets(self,master): - # 创建自定义对话框的内容 - nrow=0 - for i in range(len(self.paraLists)): - str0 = self.paraLists[i][0] - nrow = i + 1 - labelMessage = tkinter.Label(master, text=str0, font=("song", 12)) - labelMessage.grid(row=nrow, column=0) - self.names['paraV' + str(i)] = tkinter.StringVar() - self.names['paraE' + str(i)] = tkinter.Entry(master, textvariable=self.names['paraV' + str(i)], width=20) - self.names['paraV' + str(i)].set(self.paraLists[i][1]) - self.names['paraE' + str(i)].grid(row=nrow, column=1) # 控件按列排列 - b1 = tkinter.Button(master, text='确定退出', command=self.setPara) - b1.grid(row=nrow + 1, column=1) - self.bind("", self.setPara) - self.bind("", self.cancel_click) - return self.names['paraE0'] - - def cancel_click(self, event=None): - showwarning(title='警告', message='必须先设置参数') - self.initial_focus.focus_set() - - def setPara(self): - # 通过对话框设置参数 - for i in range(len(self.paraLists)): - text0 = self.names['paraV' + str(i)].get() - if not self.on_validate(text0): # 如果不能通过校验,让用户重新输入 - showwarning(title='警告', message='必须输入数字') - self.names['paraV' + str(i)].set(self.paraLists[i][1]) - self.names['paraE'+ str(i)].focus_set() - return - else: - self.paraLists[i][1] = float(text0) - self.hide() - - def on_validate(self,content): - # 该方法可对用户输入的数据进行校验,保证输入的是数字 - for i in range(len(content) - 1, -1, -1): - if not (48 <= ord(content[i]) <= 57 or content[i] == "." or content[i] =="+" or content[i] =="-" ): - return False - return True - - def hide(self): - # 销毁对话框 - self.withdraw() - self.update_idletasks() - # 将焦点返回给父窗口 - self.root.focus_set() - # 销毁自己 - self.destroy() - self.root.update() - self.root.deiconify() - self.root.focus_set() - -class paraWindow2(tkinter.Toplevel): - # 多行多列参数设置窗口 - def __init__(self, root, paraLists,title,explain): - # Constructor - self.root = root - self.names=locals() - self.paraLists=paraLists - self.explain=explain - tkinter.Toplevel.__init__(self,root) - # self.geometry("400x300") - self.title(title) - # 调用init_widgets方法来初始化对话框界面 - self.initial_focus = self.init_widgets() - # 根据modal选项设置是否为模式对话框 - self.grab_set() - # 为"WM_DELETE_WINDOW"协议使用self.cancel_click事件处理方法 - self.protocol("WM_DELETE_WINDOW", self.cancel_click) - # 根据父窗口来设置对话框的位置 - self.geometry("+%d+%d" % (root.winfo_rootx() + 100, root.winfo_rooty() + 100)) - # print(self.initial_focus) - # 让对话框获取焦点 - self.initial_focus.focus_set() - self.wait_window(self) - - def init_widgets(self): - frame1 = tkinter.Frame(self) - explainLabel = tkinter.Label(frame1, text=self.explain, font=("song", 12)) - explainLabel.pack(padx=50, pady=5) - frame1.pack(padx=5, pady=5) - frame2 = tkinter.Frame(self) - nrow=1 - for i in range(len(self.paraLists)): - nrow = i + 3 - for j in range(len(self.paraLists[i])): - self.names['ev' + str(i) + str(j)] = tkinter.StringVar() - self.names['e' + str(i) + str(j)] = tkinter.Entry(frame2, textvariable=self.names['ev' + str(i) + str(j)],width=10) - self.names['ev' + str(i) + str(j)].set(self.paraLists[i][j]) - self.names['e' + str(i) + str(j)].grid(row=nrow, column=j) - b1 = tkinter.Button(frame2, text='确定退出', command=self.setPara) - b1.grid(row=nrow + 1, column=1) - frame2.pack(padx=5, pady=6) - return b1 - - def setPara(self): - # 通过对话框给参数赋值 - for i in range(len(self.paraLists)): - for j in range(len(self.paraLists[i])): - text0 = self.names['ev' + str(i) + str(j)].get() - if not self.on_validate(text0): # 如果不能通过校验,让用户重新输入 - showwarning(title='警告', message='必须输入数字') - self.names['ev' + str(i) + str(j)].set(self.paraLists[i][j]) - self.names['e' + str(i) + str(j)].focus_set() - return - else: - self.paraLists[i][j] = float(text0) - self.hide() - - def on_validate(self,content): - # 该方法可对用户输入的数据进行校验,保证输入的是数字 - for i in range(len(content) - 1, -1, -1): - if not (48 <= ord(content[i]) <= 57 or content[i] == "." or content[i] == "+" or content[i] == "-"): - return False - return True - - def cancel_click(self, event=None): - showwarning(title='警告', message='必须先设置参数') - self.initial_focus.focus_set() - - def hide(self): - self.withdraw() - self.update_idletasks() - # 将焦点返回给父窗口 - self.root.focus_set() - # 销毁自己 - self.destroy() - self.root.update() - self.root.deiconify() - self.root.focus_set() - -class listWindow(tkinter.Toplevel): - # 下拉列表窗口,用对参数设置 - def __init__(self, root, title = None, paraLists=[]): - # Constructor - self.root = root - self.paraLists=paraLists - tkinter.Toplevel.__init__(self,root) - if title: - self.title(title) - # 创建对话框的主体内容 - # 调用init_widgets方法来初始化对话框界面 - self.initial_focus = self.init_widgets(self) - # 根据modal选项设置是否为模式对话框 - self.grab_set() - # 为"WM_DELETE_WINDOW"协议使用self.cancel_click事件处理方法 - self.protocol("WM_DELETE_WINDOW", self.cancel_click) - # 根据父窗口来设置对话框的位置 - self.geometry("+%d+%d" % (root.winfo_rootx() + 100, root.winfo_rooty() + 100)) - # print(self.initial_focus) - # 让对话框获取焦点 - self.initial_focus.focus_set() - self.wait_window(self) - - def init_widgets(self,master): - str0 = self.paraLists[0][0] - labelMessage = tkinter.Label(master, text=self.paraLists[0][0], font=("song", 12)) - labelMessage.grid(row=0, column=0) - self.listBox = tkinter.Listbox(master,selectmode=tkinter.SINGLE) - self.listBox.grid(row=1, column=0) - lists=self.paraLists[0][1] - for item in lists: - self.listBox.insert(tkinter.END, item) - self.listBox.select_set(0) - b1 = tkinter.Button(master, text='确定退出', command=self.setPara) - b1.grid(row=2, column=0) - self.bind("", self.setPara) - self.bind("", self.cancel_click) - return self.listBox - - def cancel_click(self, event=None): - showwarning(title='警告', message='必须先设置参数') - self.initial_focus.focus_set() - - def setPara(self): - self.returnValue=self.listBox.curselection()[0] - self.hide() - - def hide(self): - self.withdraw() - self.update_idletasks() - # 将焦点返回给父窗口 - self.root.focus_set() - # 销毁自己 - self.destroy() - self.root.update() - self.root.deiconify() - self.root.focus_set() - - -# ---------------------------------------------------------------------- -if __name__ == "__main__": - root = tk.Tk() - root.geometry("1000x640+150+5") # 界面大小,以相对屏幕的坐标 - root.resizable(0, 0) - myWindow = ImageApp(root) - root.mainloop() \ No newline at end of file