|  |  |  | @ -1,351 +1,338 @@ | 
			
		
	
		
			
				
					|  |  |  |  | import tkinter as tk | 
			
		
	
		
			
				
					|  |  |  |  | from tkinter import filedialog, messagebox, Toplevel | 
			
		
	
		
			
				
					|  |  |  |  | from PIL import Image, ImageTk | 
			
		
	
		
			
				
					|  |  |  |  | import numpy as np | 
			
		
	
		
			
				
					|  |  |  |  | import cv2 | 
			
		
	
		
			
				
					|  |  |  |  | import os | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | # 全局变量声明 | 
			
		
	
		
			
				
					|  |  |  |  | img_path = ""  # 用于存储图像路径 | 
			
		
	
		
			
				
					|  |  |  |  | src = None  # 用于存储已选择的图像 | 
			
		
	
		
			
				
					|  |  |  |  | X = None  # 用于存储第一张图像 | 
			
		
	
		
			
				
					|  |  |  |  | Y = None  # 用于存储第二张图像 | 
			
		
	
		
			
				
					|  |  |  |  | img_label = None  # 用于存储显示选择的图片的标签 | 
			
		
	
		
			
				
					|  |  |  |  | edge = None  # 用于存储当前处理后的图像 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | # 用于不同功能的Toplevel窗口 | 
			
		
	
		
			
				
					|  |  |  |  | AffineWin = None | 
			
		
	
		
			
				
					|  |  |  |  | TurnWin = None | 
			
		
	
		
			
				
					|  |  |  |  | ArithWin = None | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def select_image(root): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     选择图像并显示在主窗口中 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global img_path, src, img_label, edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 打开文件对话框选择图像文件 | 
			
		
	
		
			
				
					|  |  |  |  |     img_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.jpeg;*.bmp")]) | 
			
		
	
		
			
				
					|  |  |  |  |     if img_path: | 
			
		
	
		
			
				
					|  |  |  |  |         # 处理图像路径以确保反斜杠正确处理,并使用UTF-8编码处理中文路径 | 
			
		
	
		
			
				
					|  |  |  |  |         img_path_fixed = os.path.normpath(img_path) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 读取图像文件 | 
			
		
	
		
			
				
					|  |  |  |  |         src_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED) | 
			
		
	
		
			
				
					|  |  |  |  |         if src_temp is None: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |             return | 
			
		
	
		
			
				
					|  |  |  |  |         src = cv2.cvtColor(src_temp, cv2.COLOR_BGR2RGB) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 检查 img_label 是否存在且有效 | 
			
		
	
		
			
				
					|  |  |  |  |         if img_label is None or not img_label.winfo_exists(): | 
			
		
	
		
			
				
					|  |  |  |  |             img_label = tk.Label(root) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label.pack(side=tk.TOP, pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 显示缩略图 | 
			
		
	
		
			
				
					|  |  |  |  |         img = Image.open(img_path) | 
			
		
	
		
			
				
					|  |  |  |  |         img.thumbnail((160, 160)) | 
			
		
	
		
			
				
					|  |  |  |  |         img_tk = ImageTk.PhotoImage(img) | 
			
		
	
		
			
				
					|  |  |  |  |         img_label.configure(image=img_tk) | 
			
		
	
		
			
				
					|  |  |  |  |         img_label.image = img_tk | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 更新 edge 变量为 PIL.Image 对象,以便稍后保存 | 
			
		
	
		
			
				
					|  |  |  |  |         edge = Image.fromarray(src) | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |         messagebox.showerror("错误", "没有选择图片路径") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def show_selected_image(root): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     显示选定的图像 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global img_label | 
			
		
	
		
			
				
					|  |  |  |  |     img_label = tk.Label(root) | 
			
		
	
		
			
				
					|  |  |  |  |     img_label.pack(side=tk.TOP, pady=10) | 
			
		
	
		
			
				
					|  |  |  |  |     img = Image.open(img_path) | 
			
		
	
		
			
				
					|  |  |  |  |     img.thumbnail((160, 160)) | 
			
		
	
		
			
				
					|  |  |  |  |     img_tk = ImageTk.PhotoImage(img) | 
			
		
	
		
			
				
					|  |  |  |  |     img_label.configure(image=img_tk) | 
			
		
	
		
			
				
					|  |  |  |  |     img_label.image = img_tk | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def changeSize(event, img, LabelPic): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     根据窗口大小调整图像大小 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     img_aspect = img.shape[1] / img.shape[0]  # 计算图像的宽高比 | 
			
		
	
		
			
				
					|  |  |  |  |     new_aspect = event.width / event.height  # 计算窗口的新宽高比 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     if new_aspect > img_aspect: | 
			
		
	
		
			
				
					|  |  |  |  |         new_width = int(event.height * img_aspect)  # 根据新高度计算新宽度 | 
			
		
	
		
			
				
					|  |  |  |  |         new_height = event.height  # 使用新高度 | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |         new_width = event.width  # 使用新宽度 | 
			
		
	
		
			
				
					|  |  |  |  |         new_height = int(event.width / img_aspect)  # 根据新宽度计算新高度 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     resized_image = cv2.resize(img, (new_width, new_height))  # 调整图像大小 | 
			
		
	
		
			
				
					|  |  |  |  |     image1 = ImageTk.PhotoImage(Image.fromarray(resized_image)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.image = image1 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic['image'] = image1 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def savefile(): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     保存处理后的图像文件 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 打开保存文件对话框 | 
			
		
	
		
			
				
					|  |  |  |  |     filename = filedialog.asksaveasfilename(defaultextension=".jpg", filetypes=[("JPEG files", "*.jpg"), ("PNG files", "*.png"), ("BMP files", "*.bmp")]) | 
			
		
	
		
			
				
					|  |  |  |  |     if not filename: | 
			
		
	
		
			
				
					|  |  |  |  |         return | 
			
		
	
		
			
				
					|  |  |  |  |     if edge is not None: | 
			
		
	
		
			
				
					|  |  |  |  |         try: | 
			
		
	
		
			
				
					|  |  |  |  |             edge.save(filename) | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showinfo("保存成功", "图片保存成功!") | 
			
		
	
		
			
				
					|  |  |  |  |         except Exception as e: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("保存失败", f"无法保存图片: {e}") | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |         messagebox.showerror("保存失败", "没有图像可保存") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def affine_tra(root): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     对图像进行仿射变换 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global src, AffineWin, edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     #判断是否已经选取图片 | 
			
		
	
		
			
				
					|  |  |  |  |     if src is None: | 
			
		
	
		
			
				
					|  |  |  |  |         messagebox.showerror("错误", "没有选择图片!") | 
			
		
	
		
			
				
					|  |  |  |  |         return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     rows, cols = src.shape[:2]  # 获取图像的行和列 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 设置图像仿射变化矩阵 | 
			
		
	
		
			
				
					|  |  |  |  |     post1 = np.float32([[50, 50], [200, 50], [50, 200]]) | 
			
		
	
		
			
				
					|  |  |  |  |     post2 = np.float32([[10, 100], [200, 50], [100, 250]]) | 
			
		
	
		
			
				
					|  |  |  |  |     m = cv2.getAffineTransform(post1, post2) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 图像仿射变换 | 
			
		
	
		
			
				
					|  |  |  |  |     result = cv2.warpAffine(src, m, (cols, rows)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 更新 edge 变量 | 
			
		
	
		
			
				
					|  |  |  |  |     edge = Image.fromarray(result) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 创建Toplevel窗口 | 
			
		
	
		
			
				
					|  |  |  |  |     try: | 
			
		
	
		
			
				
					|  |  |  |  |         if AffineWin: | 
			
		
	
		
			
				
					|  |  |  |  |             AffineWin.destroy() | 
			
		
	
		
			
				
					|  |  |  |  |     except Exception: | 
			
		
	
		
			
				
					|  |  |  |  |         print("NVM") | 
			
		
	
		
			
				
					|  |  |  |  |     finally: | 
			
		
	
		
			
				
					|  |  |  |  |         AffineWin = Toplevel(root) | 
			
		
	
		
			
				
					|  |  |  |  |         AffineWin.attributes('-topmost', True) | 
			
		
	
		
			
				
					|  |  |  |  |     AffineWin.geometry("360x300") | 
			
		
	
		
			
				
					|  |  |  |  |     AffineWin.resizable(True, True) | 
			
		
	
		
			
				
					|  |  |  |  |     AffineWin.title("仿射变换结果") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 显示图像 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic = tk.Label(AffineWin, text="IMG", width=360, height=240) | 
			
		
	
		
			
				
					|  |  |  |  |     image = ImageTk.PhotoImage(Image.fromarray(result)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.image = image | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic['image'] = image | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.bind('<Configure>', lambda event: changeSize(event, result, LabelPic)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.pack(fill=tk.BOTH, expand=tk.YES) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 添加保存按钮 | 
			
		
	
		
			
				
					|  |  |  |  |     btn_save = tk.Button(AffineWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), | 
			
		
	
		
			
				
					|  |  |  |  |                          width=20, command=savefile) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_save.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def turn(root): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     对图像进行翻转操作 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global src, TurnWin, edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     if src is None: | 
			
		
	
		
			
				
					|  |  |  |  |         messagebox.showerror("错误", "没有选择图片!") | 
			
		
	
		
			
				
					|  |  |  |  |         return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 水平镜像 | 
			
		
	
		
			
				
					|  |  |  |  |     horizontal = cv2.flip(src, 1) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 垂直镜像 | 
			
		
	
		
			
				
					|  |  |  |  |     vertical = cv2.flip(src, 0) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 对角镜像 | 
			
		
	
		
			
				
					|  |  |  |  |     cross = cv2.flip(src, -1) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 将三种翻转图像组合成一个图像进行显示 | 
			
		
	
		
			
				
					|  |  |  |  |     combined = np.hstack((horizontal, vertical, cross)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 更新 edge 变量 | 
			
		
	
		
			
				
					|  |  |  |  |     edge = Image.fromarray(combined) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 创建Toplevel窗口 | 
			
		
	
		
			
				
					|  |  |  |  |     try: | 
			
		
	
		
			
				
					|  |  |  |  |         if TurnWin: | 
			
		
	
		
			
				
					|  |  |  |  |             TurnWin.destroy() | 
			
		
	
		
			
				
					|  |  |  |  |     except Exception as e: | 
			
		
	
		
			
				
					|  |  |  |  |         print("NVM") | 
			
		
	
		
			
				
					|  |  |  |  |     finally: | 
			
		
	
		
			
				
					|  |  |  |  |         TurnWin = Toplevel(root) | 
			
		
	
		
			
				
					|  |  |  |  |         TurnWin.attributes('-topmost', True) | 
			
		
	
		
			
				
					|  |  |  |  |     TurnWin.geometry("720x300") | 
			
		
	
		
			
				
					|  |  |  |  |     TurnWin.resizable(True, True) | 
			
		
	
		
			
				
					|  |  |  |  |     TurnWin.title("翻转结果") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 显示图像 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic = tk.Label(TurnWin, text="IMG", width=720, height=240) | 
			
		
	
		
			
				
					|  |  |  |  |     image = ImageTk.PhotoImage(Image.fromarray(combined)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.image = image | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic['image'] = image | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.bind('<Configure>', lambda event: changeSize(event, combined, LabelPic)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.pack(fill=tk.BOTH, expand=tk.YES) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 添加保存按钮 | 
			
		
	
		
			
				
					|  |  |  |  |     btn_save = tk.Button(TurnWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=savefile) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_save.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def arithmetic(root): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     对图像进行算术变换操作 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global src, X, Y, ArithWin, img_label_first, img_label_second, edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     final = None  # 用于存储最终的算术运算结果 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def select_first_image(): | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         选择第一张图像 | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         global X, img_label_first | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', True)  # 设置窗口为最上层 | 
			
		
	
		
			
				
					|  |  |  |  |         img_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.bmp;*.jpeg")], parent=ArithWin) | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', False)  # 恢复窗口最上层属性 | 
			
		
	
		
			
				
					|  |  |  |  |         if img_path: | 
			
		
	
		
			
				
					|  |  |  |  |             img_path_fixed = os.path.normpath(img_path) | 
			
		
	
		
			
				
					|  |  |  |  |             img_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED) | 
			
		
	
		
			
				
					|  |  |  |  |             if img_temp is None: | 
			
		
	
		
			
				
					|  |  |  |  |                 messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |                 return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             image = cv2.cvtColor(img_temp, cv2.COLOR_BGR2RGB)  # 转换颜色空间 | 
			
		
	
		
			
				
					|  |  |  |  |             img = Image.fromarray(image) | 
			
		
	
		
			
				
					|  |  |  |  |             img.thumbnail((100, 100))  # 缩略图 | 
			
		
	
		
			
				
					|  |  |  |  |             img_tk = ImageTk.PhotoImage(img) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label_first.configure(image=img_tk) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label_first.image = img_tk | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("错误", "没有选择图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |         X = image.copy() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def select_second_image(): | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         选择第二张图像 | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         global Y, img_label_second | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', True)  # 设置窗口为最上层 | 
			
		
	
		
			
				
					|  |  |  |  |         img_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.bmp;*.jpeg")], parent=ArithWin) | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', False)  # 恢复窗口最上层属性 | 
			
		
	
		
			
				
					|  |  |  |  |         if img_path: | 
			
		
	
		
			
				
					|  |  |  |  |             img_path_fixed = os.path.normpath(img_path) | 
			
		
	
		
			
				
					|  |  |  |  |             img_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED) | 
			
		
	
		
			
				
					|  |  |  |  |             if img_temp is None: | 
			
		
	
		
			
				
					|  |  |  |  |                 messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |                 return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             image = cv2.cvtColor(img_temp, cv2.COLOR_BGR2RGB)  # 转换颜色空间 | 
			
		
	
		
			
				
					|  |  |  |  |             img = Image.fromarray(image) | 
			
		
	
		
			
				
					|  |  |  |  |             img.thumbnail((100, 100))  # 缩略图 | 
			
		
	
		
			
				
					|  |  |  |  |             img_tk = ImageTk.PhotoImage(img) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label_second.configure(image=img_tk) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label_second.image = img_tk | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("错误", "没有选择图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |         Y = image.copy() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def perform_operation(operation): | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         执行图像算术运算 | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         nonlocal final | 
			
		
	
		
			
				
					|  |  |  |  |         if X is None or Y is None: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("错误", "请选择两张图片") | 
			
		
	
		
			
				
					|  |  |  |  |             return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 调整Y图像的尺寸和通道数与X一致 | 
			
		
	
		
			
				
					|  |  |  |  |         Y_resized = cv2.resize(Y, (X.shape[1], X.shape[0])) | 
			
		
	
		
			
				
					|  |  |  |  |         if len(X.shape) != len(Y_resized.shape): | 
			
		
	
		
			
				
					|  |  |  |  |             if len(X.shape) == 2: | 
			
		
	
		
			
				
					|  |  |  |  |                 Y_resized = cv2.cvtColor(Y_resized, cv2.COLOR_BGR2GRAY) | 
			
		
	
		
			
				
					|  |  |  |  |             else: | 
			
		
	
		
			
				
					|  |  |  |  |                 Y_resized = cv2.cvtColor(Y_resized, cv2.COLOR_GRAY2BGR) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if operation == "add": | 
			
		
	
		
			
				
					|  |  |  |  |             final = cv2.add(X, Y_resized) | 
			
		
	
		
			
				
					|  |  |  |  |         elif operation == "sub": | 
			
		
	
		
			
				
					|  |  |  |  |             final = cv2.subtract(X, Y_resized) | 
			
		
	
		
			
				
					|  |  |  |  |         elif operation == "mult": | 
			
		
	
		
			
				
					|  |  |  |  |             final = cv2.multiply(X, Y_resized) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         show_result(final) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def show_result(result_image): | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         显示运算结果图像 | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         global edge  # 更新全局变量 edge | 
			
		
	
		
			
				
					|  |  |  |  |         edge = Image.fromarray(result_image) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         result_window = Toplevel(root) | 
			
		
	
		
			
				
					|  |  |  |  |         result_window.attributes('-topmost', True) | 
			
		
	
		
			
				
					|  |  |  |  |         result_window.geometry("620x480") | 
			
		
	
		
			
				
					|  |  |  |  |         result_window.resizable(True, True) | 
			
		
	
		
			
				
					|  |  |  |  |         result_window.title("运算结果") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic = tk.Label(result_window, text="IMG", width=720, height=240) | 
			
		
	
		
			
				
					|  |  |  |  |         image = ImageTk.PhotoImage(Image.fromarray(result_image)) | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic.image = image | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic['image'] = image | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic.bind('<Configure>', lambda event: changeSize(event, result_image, LabelPic)) | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic.pack(fill=tk.BOTH, expand=tk.YES) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 添加保存按钮 | 
			
		
	
		
			
				
					|  |  |  |  |         btn_save = tk.Button(result_window, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=savefile) | 
			
		
	
		
			
				
					|  |  |  |  |         btn_save.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 创建算术运算窗口 | 
			
		
	
		
			
				
					|  |  |  |  |     try: | 
			
		
	
		
			
				
					|  |  |  |  |         if ArithWin: | 
			
		
	
		
			
				
					|  |  |  |  |             ArithWin.destroy() | 
			
		
	
		
			
				
					|  |  |  |  |     except Exception as e: | 
			
		
	
		
			
				
					|  |  |  |  |         print("NVM") | 
			
		
	
		
			
				
					|  |  |  |  |     finally: | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin = Toplevel(root) | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', True) | 
			
		
	
		
			
				
					|  |  |  |  |     ArithWin.geometry("720x480") | 
			
		
	
		
			
				
					|  |  |  |  |     ArithWin.resizable(True, True) | 
			
		
	
		
			
				
					|  |  |  |  |     ArithWin.title("选择运算类型") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 添加一个框架来容纳两个图像标签 | 
			
		
	
		
			
				
					|  |  |  |  |     frame = tk.Frame(ArithWin) | 
			
		
	
		
			
				
					|  |  |  |  |     frame.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     img_label_first = tk.Label(frame) | 
			
		
	
		
			
				
					|  |  |  |  |     img_label_first.pack(side=tk.LEFT, padx=10) | 
			
		
	
		
			
				
					|  |  |  |  |     img_label_second = tk.Label(frame) | 
			
		
	
		
			
				
					|  |  |  |  |     img_label_second.pack(side=tk.RIGHT, padx=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 添加选择图像和运算按钮 | 
			
		
	
		
			
				
					|  |  |  |  |     btn_select_first = tk.Button(ArithWin, text="选择第一张图片", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=select_first_image) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_select_first.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_select_second = tk.Button(ArithWin, text="选择第二张图片", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=select_second_image) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_select_second.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_add = tk.Button(ArithWin, text="加法", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=lambda: perform_operation("add")) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_add.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_sub = tk.Button(ArithWin, text="减法", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=lambda: perform_operation("sub")) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_sub.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_mult = tk.Button(ArithWin, text="乘法", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=lambda: perform_operation("mult")) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_mult.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | import tkinter as tk | 
			
		
	
		
			
				
					|  |  |  |  | from tkinter import filedialog, messagebox, Toplevel | 
			
		
	
		
			
				
					|  |  |  |  | from PIL import Image, ImageTk | 
			
		
	
		
			
				
					|  |  |  |  | import numpy as np | 
			
		
	
		
			
				
					|  |  |  |  | import cv2 | 
			
		
	
		
			
				
					|  |  |  |  | import os | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | # 全局变量声明 | 
			
		
	
		
			
				
					|  |  |  |  | img_path = ""  # 用于存储图像路径 | 
			
		
	
		
			
				
					|  |  |  |  | src = None  # 用于存储已选择的图像 | 
			
		
	
		
			
				
					|  |  |  |  | X = None  # 用于存储第一张图像 | 
			
		
	
		
			
				
					|  |  |  |  | Y = None  # 用于存储第二张图像 | 
			
		
	
		
			
				
					|  |  |  |  | img_label = None  # 用于存储显示选择的图片的标签 | 
			
		
	
		
			
				
					|  |  |  |  | edge = None  # 用于存储当前处理后的图像 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | # 用于不同功能的Toplevel窗口 | 
			
		
	
		
			
				
					|  |  |  |  | AffineWin = None | 
			
		
	
		
			
				
					|  |  |  |  | TurnWin = None | 
			
		
	
		
			
				
					|  |  |  |  | ArithWin = None | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def select_image(root): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     选择图像并显示在主窗口中 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global img_path, src, img_label, edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 打开文件对话框选择图像文件 | 
			
		
	
		
			
				
					|  |  |  |  |     img_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.jpeg;*.bmp")]) | 
			
		
	
		
			
				
					|  |  |  |  |     if img_path: | 
			
		
	
		
			
				
					|  |  |  |  |         # 处理图像路径以确保反斜杠正确处理,并使用UTF-8编码处理中文路径 | 
			
		
	
		
			
				
					|  |  |  |  |         img_path_fixed = os.path.normpath(img_path) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 读取图像文件 | 
			
		
	
		
			
				
					|  |  |  |  |         src_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED) | 
			
		
	
		
			
				
					|  |  |  |  |         if src_temp is None: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |             return | 
			
		
	
		
			
				
					|  |  |  |  |         src = cv2.cvtColor(src_temp, cv2.COLOR_BGR2RGB) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 检查 img_label 是否存在且有效 | 
			
		
	
		
			
				
					|  |  |  |  |         if img_label is None or not img_label.winfo_exists(): | 
			
		
	
		
			
				
					|  |  |  |  |             img_label = tk.Label(root) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label.pack(side=tk.TOP, pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 显示缩略图 | 
			
		
	
		
			
				
					|  |  |  |  |         img = Image.open(img_path) | 
			
		
	
		
			
				
					|  |  |  |  |         img.thumbnail((160, 160)) | 
			
		
	
		
			
				
					|  |  |  |  |         img_tk = ImageTk.PhotoImage(img) | 
			
		
	
		
			
				
					|  |  |  |  |         img_label.configure(image=img_tk) | 
			
		
	
		
			
				
					|  |  |  |  |         img_label.image = img_tk | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 更新 edge 变量为 PIL.Image 对象,以便稍后保存 | 
			
		
	
		
			
				
					|  |  |  |  |         edge = Image.fromarray(src) | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |         messagebox.showerror("错误", "没有选择图片路径") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def changeSize(event, img, LabelPic): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     根据窗口大小调整图像大小 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     img_aspect = img.shape[1] / img.shape[0]  # 计算图像的宽高比 | 
			
		
	
		
			
				
					|  |  |  |  |     new_aspect = event.width / event.height  # 计算窗口的新宽高比 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     if new_aspect > img_aspect: | 
			
		
	
		
			
				
					|  |  |  |  |         new_width = int(event.height * img_aspect)  # 根据新高度计算新宽度 | 
			
		
	
		
			
				
					|  |  |  |  |         new_height = event.height  # 使用新高度 | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |         new_width = event.width  # 使用新宽度 | 
			
		
	
		
			
				
					|  |  |  |  |         new_height = int(event.width / img_aspect)  # 根据新宽度计算新高度 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     resized_image = cv2.resize(img, (new_width, new_height))  # 调整图像大小 | 
			
		
	
		
			
				
					|  |  |  |  |     image1 = ImageTk.PhotoImage(Image.fromarray(resized_image)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.image = image1 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic['image'] = image1 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def savefile(): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     保存处理后的图像文件 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 打开保存文件对话框 | 
			
		
	
		
			
				
					|  |  |  |  |     filename = filedialog.asksaveasfilename(defaultextension=".jpg", filetypes=[("JPEG files", "*.jpg"), ("PNG files", "*.png"), ("BMP files", "*.bmp")]) | 
			
		
	
		
			
				
					|  |  |  |  |     if not filename: | 
			
		
	
		
			
				
					|  |  |  |  |         return | 
			
		
	
		
			
				
					|  |  |  |  |     if edge is not None: | 
			
		
	
		
			
				
					|  |  |  |  |         try: | 
			
		
	
		
			
				
					|  |  |  |  |             edge.save(filename) | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showinfo("保存成功", "图片保存成功!") | 
			
		
	
		
			
				
					|  |  |  |  |         except Exception as e: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("保存失败", f"无法保存图片: {e}") | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |         messagebox.showerror("保存失败", "没有图像可保存") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def affine_tra(root): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     对图像进行仿射变换 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global src, AffineWin, edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     #判断是否已经选取图片 | 
			
		
	
		
			
				
					|  |  |  |  |     if src is None: | 
			
		
	
		
			
				
					|  |  |  |  |         messagebox.showerror("错误", "没有选择图片!") | 
			
		
	
		
			
				
					|  |  |  |  |         return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     rows, cols = src.shape[:2]  # 获取图像的行和列 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 设置图像仿射变化矩阵 | 
			
		
	
		
			
				
					|  |  |  |  |     post1 = np.float32([[50, 50], [200, 50], [50, 200]]) | 
			
		
	
		
			
				
					|  |  |  |  |     post2 = np.float32([[10, 100], [200, 50], [100, 250]]) | 
			
		
	
		
			
				
					|  |  |  |  |     m = cv2.getAffineTransform(post1, post2) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 图像仿射变换 | 
			
		
	
		
			
				
					|  |  |  |  |     result = cv2.warpAffine(src, m, (cols, rows)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 更新 edge 变量 | 
			
		
	
		
			
				
					|  |  |  |  |     edge = Image.fromarray(result) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 创建Toplevel窗口 | 
			
		
	
		
			
				
					|  |  |  |  |     try: | 
			
		
	
		
			
				
					|  |  |  |  |         if AffineWin: | 
			
		
	
		
			
				
					|  |  |  |  |             AffineWin.destroy() | 
			
		
	
		
			
				
					|  |  |  |  |     except Exception: | 
			
		
	
		
			
				
					|  |  |  |  |         print("NVM") | 
			
		
	
		
			
				
					|  |  |  |  |     finally: | 
			
		
	
		
			
				
					|  |  |  |  |         AffineWin = Toplevel(root) | 
			
		
	
		
			
				
					|  |  |  |  |         AffineWin.attributes('-topmost', True) | 
			
		
	
		
			
				
					|  |  |  |  |     AffineWin.geometry("360x300") | 
			
		
	
		
			
				
					|  |  |  |  |     AffineWin.resizable(True, True) | 
			
		
	
		
			
				
					|  |  |  |  |     AffineWin.title("仿射变换结果") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 显示图像 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic = tk.Label(AffineWin, text="IMG", width=360, height=240) | 
			
		
	
		
			
				
					|  |  |  |  |     image = ImageTk.PhotoImage(Image.fromarray(result)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.image = image | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic['image'] = image | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.bind('<Configure>', lambda event: changeSize(event, result, LabelPic)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.pack(fill=tk.BOTH, expand=tk.YES) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 添加保存按钮 | 
			
		
	
		
			
				
					|  |  |  |  |     btn_save = tk.Button(AffineWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), | 
			
		
	
		
			
				
					|  |  |  |  |                          width=20, command=savefile) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_save.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def turn(root): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     对图像进行翻转操作 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global src, TurnWin, edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     if src is None: | 
			
		
	
		
			
				
					|  |  |  |  |         messagebox.showerror("错误", "没有选择图片!") | 
			
		
	
		
			
				
					|  |  |  |  |         return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 水平镜像 | 
			
		
	
		
			
				
					|  |  |  |  |     horizontal = cv2.flip(src, 1) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 垂直镜像 | 
			
		
	
		
			
				
					|  |  |  |  |     vertical = cv2.flip(src, 0) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 对角镜像 | 
			
		
	
		
			
				
					|  |  |  |  |     cross = cv2.flip(src, -1) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 将三种翻转图像组合成一个图像进行显示 | 
			
		
	
		
			
				
					|  |  |  |  |     combined = np.hstack((horizontal, vertical, cross)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 更新 edge 变量 | 
			
		
	
		
			
				
					|  |  |  |  |     edge = Image.fromarray(combined) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 创建Toplevel窗口 | 
			
		
	
		
			
				
					|  |  |  |  |     try: | 
			
		
	
		
			
				
					|  |  |  |  |         if TurnWin: | 
			
		
	
		
			
				
					|  |  |  |  |             TurnWin.destroy() | 
			
		
	
		
			
				
					|  |  |  |  |     except Exception as e: | 
			
		
	
		
			
				
					|  |  |  |  |         print("NVM") | 
			
		
	
		
			
				
					|  |  |  |  |     finally: | 
			
		
	
		
			
				
					|  |  |  |  |         TurnWin = Toplevel(root) | 
			
		
	
		
			
				
					|  |  |  |  |         TurnWin.attributes('-topmost', True) | 
			
		
	
		
			
				
					|  |  |  |  |     TurnWin.geometry("720x300") | 
			
		
	
		
			
				
					|  |  |  |  |     TurnWin.resizable(True, True) | 
			
		
	
		
			
				
					|  |  |  |  |     TurnWin.title("翻转结果") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 显示图像 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic = tk.Label(TurnWin, text="IMG", width=720, height=240) | 
			
		
	
		
			
				
					|  |  |  |  |     image = ImageTk.PhotoImage(Image.fromarray(combined)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.image = image | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic['image'] = image | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.bind('<Configure>', lambda event: changeSize(event, combined, LabelPic)) | 
			
		
	
		
			
				
					|  |  |  |  |     LabelPic.pack(fill=tk.BOTH, expand=tk.YES) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 添加保存按钮 | 
			
		
	
		
			
				
					|  |  |  |  |     btn_save = tk.Button(TurnWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=savefile) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_save.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def arithmetic(root): | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     对图像进行算术变换操作 | 
			
		
	
		
			
				
					|  |  |  |  |     """ | 
			
		
	
		
			
				
					|  |  |  |  |     global src, X, Y, ArithWin, img_label_first, img_label_second, edge | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     final = None  # 用于存储最终的算术运算结果 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def select_first_image(): | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         选择第一张图像 | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         global X, img_label_first | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', True)  # 设置窗口为最上层 | 
			
		
	
		
			
				
					|  |  |  |  |         img_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.bmp;*.jpeg")], parent=ArithWin) | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', False)  # 恢复窗口最上层属性 | 
			
		
	
		
			
				
					|  |  |  |  |         if img_path: | 
			
		
	
		
			
				
					|  |  |  |  |             img_path_fixed = os.path.normpath(img_path) | 
			
		
	
		
			
				
					|  |  |  |  |             img_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED) | 
			
		
	
		
			
				
					|  |  |  |  |             if img_temp is None: | 
			
		
	
		
			
				
					|  |  |  |  |                 messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |                 return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             image = cv2.cvtColor(img_temp, cv2.COLOR_BGR2RGB)  # 转换颜色空间 | 
			
		
	
		
			
				
					|  |  |  |  |             img = Image.fromarray(image) | 
			
		
	
		
			
				
					|  |  |  |  |             img.thumbnail((100, 100))  # 缩略图 | 
			
		
	
		
			
				
					|  |  |  |  |             img_tk = ImageTk.PhotoImage(img) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label_first.configure(image=img_tk) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label_first.image = img_tk | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("错误", "没有选择图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |         X = image.copy() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def select_second_image(): | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         选择第二张图像 | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         global Y, img_label_second | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', True)  # 设置窗口为最上层 | 
			
		
	
		
			
				
					|  |  |  |  |         img_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.bmp;*.jpeg")], parent=ArithWin) | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', False)  # 恢复窗口最上层属性 | 
			
		
	
		
			
				
					|  |  |  |  |         if img_path: | 
			
		
	
		
			
				
					|  |  |  |  |             img_path_fixed = os.path.normpath(img_path) | 
			
		
	
		
			
				
					|  |  |  |  |             img_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED) | 
			
		
	
		
			
				
					|  |  |  |  |             if img_temp is None: | 
			
		
	
		
			
				
					|  |  |  |  |                 messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |                 return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             image = cv2.cvtColor(img_temp, cv2.COLOR_BGR2RGB)  # 转换颜色空间 | 
			
		
	
		
			
				
					|  |  |  |  |             img = Image.fromarray(image) | 
			
		
	
		
			
				
					|  |  |  |  |             img.thumbnail((100, 100))  # 缩略图 | 
			
		
	
		
			
				
					|  |  |  |  |             img_tk = ImageTk.PhotoImage(img) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label_second.configure(image=img_tk) | 
			
		
	
		
			
				
					|  |  |  |  |             img_label_second.image = img_tk | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("错误", "没有选择图片路径") | 
			
		
	
		
			
				
					|  |  |  |  |         Y = image.copy() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def perform_operation(operation): | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         执行图像算术运算 | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         nonlocal final | 
			
		
	
		
			
				
					|  |  |  |  |         if X is None or Y is None: | 
			
		
	
		
			
				
					|  |  |  |  |             messagebox.showerror("错误", "请选择两张图片") | 
			
		
	
		
			
				
					|  |  |  |  |             return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 调整Y图像的尺寸和通道数与X一致 | 
			
		
	
		
			
				
					|  |  |  |  |         Y_resized = cv2.resize(Y, (X.shape[1], X.shape[0])) | 
			
		
	
		
			
				
					|  |  |  |  |         if len(X.shape) != len(Y_resized.shape): | 
			
		
	
		
			
				
					|  |  |  |  |             if len(X.shape) == 2: | 
			
		
	
		
			
				
					|  |  |  |  |                 Y_resized = cv2.cvtColor(Y_resized, cv2.COLOR_BGR2GRAY) | 
			
		
	
		
			
				
					|  |  |  |  |             else: | 
			
		
	
		
			
				
					|  |  |  |  |                 Y_resized = cv2.cvtColor(Y_resized, cv2.COLOR_GRAY2BGR) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if operation == "add": | 
			
		
	
		
			
				
					|  |  |  |  |             final = cv2.add(X, Y_resized) | 
			
		
	
		
			
				
					|  |  |  |  |         elif operation == "sub": | 
			
		
	
		
			
				
					|  |  |  |  |             final = cv2.subtract(X, Y_resized) | 
			
		
	
		
			
				
					|  |  |  |  |         elif operation == "mult": | 
			
		
	
		
			
				
					|  |  |  |  |             final = cv2.multiply(X, Y_resized) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         show_result(final) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def show_result(result_image): | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         显示运算结果图像 | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         global edge  # 更新全局变量 edge | 
			
		
	
		
			
				
					|  |  |  |  |         edge = Image.fromarray(result_image) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         result_window = Toplevel(root) | 
			
		
	
		
			
				
					|  |  |  |  |         result_window.attributes('-topmost', True) | 
			
		
	
		
			
				
					|  |  |  |  |         result_window.geometry("620x480") | 
			
		
	
		
			
				
					|  |  |  |  |         result_window.resizable(True, True) | 
			
		
	
		
			
				
					|  |  |  |  |         result_window.title("运算结果") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic = tk.Label(result_window, text="IMG", width=720, height=240) | 
			
		
	
		
			
				
					|  |  |  |  |         image = ImageTk.PhotoImage(Image.fromarray(result_image)) | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic.image = image | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic['image'] = image | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic.bind('<Configure>', lambda event: changeSize(event, result_image, LabelPic)) | 
			
		
	
		
			
				
					|  |  |  |  |         LabelPic.pack(fill=tk.BOTH, expand=tk.YES) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # 添加保存按钮 | 
			
		
	
		
			
				
					|  |  |  |  |         btn_save = tk.Button(result_window, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=savefile) | 
			
		
	
		
			
				
					|  |  |  |  |         btn_save.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 创建算术运算窗口 | 
			
		
	
		
			
				
					|  |  |  |  |     try: | 
			
		
	
		
			
				
					|  |  |  |  |         if ArithWin: | 
			
		
	
		
			
				
					|  |  |  |  |             ArithWin.destroy() | 
			
		
	
		
			
				
					|  |  |  |  |     except Exception as e: | 
			
		
	
		
			
				
					|  |  |  |  |         print("NVM") | 
			
		
	
		
			
				
					|  |  |  |  |     finally: | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin = Toplevel(root) | 
			
		
	
		
			
				
					|  |  |  |  |         ArithWin.attributes('-topmost', True) | 
			
		
	
		
			
				
					|  |  |  |  |     ArithWin.geometry("720x480") | 
			
		
	
		
			
				
					|  |  |  |  |     ArithWin.resizable(True, True) | 
			
		
	
		
			
				
					|  |  |  |  |     ArithWin.title("选择运算类型") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 添加一个框架来容纳两个图像标签 | 
			
		
	
		
			
				
					|  |  |  |  |     frame = tk.Frame(ArithWin) | 
			
		
	
		
			
				
					|  |  |  |  |     frame.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     img_label_first = tk.Label(frame) | 
			
		
	
		
			
				
					|  |  |  |  |     img_label_first.pack(side=tk.LEFT, padx=10) | 
			
		
	
		
			
				
					|  |  |  |  |     img_label_second = tk.Label(frame) | 
			
		
	
		
			
				
					|  |  |  |  |     img_label_second.pack(side=tk.RIGHT, padx=10) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # 添加选择图像和运算按钮 | 
			
		
	
		
			
				
					|  |  |  |  |     btn_select_first = tk.Button(ArithWin, text="选择第一张图片", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=select_first_image) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_select_first.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_select_second = tk.Button(ArithWin, text="选择第二张图片", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=select_second_image) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_select_second.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_add = tk.Button(ArithWin, text="加法", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=lambda: perform_operation("add")) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_add.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_sub = tk.Button(ArithWin, text="减法", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=lambda: perform_operation("sub")) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_sub.pack(pady=10) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_mult = tk.Button(ArithWin, text="乘法", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=lambda: perform_operation("mult")) | 
			
		
	
		
			
				
					|  |  |  |  |     btn_mult.pack(pady=10) | 
			
		
	
	
		
			
				
					|  |  |  | 
 |