ADD file via upload

master
p4s3m8b7v 2 years ago
parent 74c58f94c2
commit 441d049f70

@ -0,0 +1,969 @@
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("<Return>", self.setPara)
self.bind("<Escape>", 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("<Return>", self.setPara)
self.bind("<Escape>", 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()
Loading…
Cancel
Save