parent
							
								
									4dc8b82e85
								
							
						
					
					
						commit
						6570ee0239
					
				| @ -1,333 +1,320 @@ | ||||
| import tkinter as tk | ||||
| from tkinter import filedialog, messagebox | ||||
| from tkinter import 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  # 用于存储处理后的图像 | ||||
| 
 | ||||
| ThreWin = None  # 用于阈值化处理结果窗口 | ||||
| VergeWin = None  # 用于边缘检测结果窗口 | ||||
| LineWin = 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) | ||||
| 
 | ||||
|         # 使用 cv2.imdecode 加载图像,处理中文路径 | ||||
|         src_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED) | ||||
|         if src_temp is None: | ||||
|             messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径") | ||||
|             return | ||||
|         # 将图像从 BGR 转换为 RGB | ||||
|         src = cv2.cvtColor(src_temp, cv2.COLOR_BGR2RGB) | ||||
| 
 | ||||
|         # 检查 img_label 是否存在且有效,如果不存在则创建新的 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) | ||||
| 
 | ||||
|         # 使用 PIL 加载并缩放图像以适应标签大小 | ||||
|         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 | ||||
|     # 确保 edge 变量已定义 | ||||
|     if edge is not None: | ||||
|         try: | ||||
|             edge.save(filename) | ||||
|             messagebox.showinfo("保存成功", "图片保存成功!") | ||||
|         except Exception as e: | ||||
|             messagebox.showerror("保存失败", f"无法保存图片: {e}") | ||||
|     else: | ||||
|         messagebox.showerror("保存失败", "没有图像可保存") | ||||
| 
 | ||||
| def threshold(root): | ||||
|     """ | ||||
|     对图像进行阈值化处理并显示结果 | ||||
|     """ | ||||
|     global src, ThreWin, edge | ||||
| 
 | ||||
|     # 判断是否已经选取图片 | ||||
|     if src is None: | ||||
|         messagebox.showerror("错误", "没有选择图片!") | ||||
|         return | ||||
| 
 | ||||
|     # 转变图像为灰度图 | ||||
|     gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) | ||||
| 
 | ||||
|     # TRIANGLE 自适应阈值 | ||||
|     ret, TRIANGLE_img = cv2.threshold(gray, 0, 255, cv2.THRESH_TRIANGLE) | ||||
|     # OTSU 自适应阈值 | ||||
|     ret, OTSU_img = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) | ||||
|     # TRUNC 截断阈值(200) | ||||
|     ret, TRUNC_img = cv2.threshold(gray, 200, 255, cv2.THRESH_TRUNC) | ||||
|     # TOZERO 归零阈值(100) | ||||
|     ret, TOZERO__img = cv2.threshold(gray, 100, 255, cv2.THRESH_TOZERO) | ||||
| 
 | ||||
|     # 将处理后的图像拼接在一起 | ||||
|     combined = np.hstack((TRIANGLE_img, OTSU_img, TRUNC_img, TOZERO__img)) | ||||
| 
 | ||||
|     # 更新 edge 变量 | ||||
|     edge = Image.fromarray(combined) | ||||
| 
 | ||||
|     # 创建 Toplevel 窗口用于显示处理结果 | ||||
|     try: | ||||
|         ThreWin.destroy() | ||||
|     except Exception as e: | ||||
|         print("NVM") | ||||
|     finally: | ||||
|         ThreWin = Toplevel() | ||||
|         ThreWin.attributes('-topmost', True) | ||||
|     ThreWin.geometry("720x300") | ||||
|     ThreWin.resizable(True, True)  # 可缩放 | ||||
|     ThreWin.title("阈值化结果") | ||||
| 
 | ||||
|     # 显示图像 | ||||
|     LabelPic = tk.Label(ThreWin, 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(ThreWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, | ||||
|                          command=savefile) | ||||
|     btn_save.pack(pady=10) | ||||
| 
 | ||||
| def verge(root): | ||||
|     """ | ||||
|     对图像进行边缘检测并显示结果 | ||||
|     """ | ||||
|     global src, VergeWin, edge | ||||
| 
 | ||||
|     # 判断是否已经选取图片 | ||||
|     if src is None: | ||||
|         messagebox.showerror("错误", "没有选择图片!") | ||||
|         return | ||||
| 
 | ||||
|     # 转变图像为灰度图 | ||||
|     grayImage = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) | ||||
| 
 | ||||
|     # 1. Roberts 算子 | ||||
|     kernelx = np.array([[-1, 0], [0, 1]], dtype=int) | ||||
|     kernely = np.array([[0, -1], [1, 0]], dtype=int) | ||||
|     x = cv2.filter2D(grayImage, cv2.CV_16S, kernelx) | ||||
|     y = cv2.filter2D(grayImage, cv2.CV_16S, kernely) | ||||
|     absX = cv2.convertScaleAbs(x) | ||||
|     absY = cv2.convertScaleAbs(y) | ||||
|     Roberts = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) | ||||
| 
 | ||||
|     # 2. Sobel 算子 | ||||
|     x = cv2.Sobel(grayImage, cv2.CV_16S, 1, 0) | ||||
|     y = cv2.Sobel(grayImage, cv2.CV_16S, 0, 1) | ||||
|     absX = cv2.convertScaleAbs(x) | ||||
|     absY = cv2.convertScaleAbs(y) | ||||
|     Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) | ||||
| 
 | ||||
|     # 3. 拉普拉斯算法 & 高斯滤波 | ||||
|     gray = cv2.GaussianBlur(grayImage, (5, 5), 0, 0) | ||||
|     dst = cv2.Laplacian(gray, cv2.CV_16S, ksize=3) | ||||
|     Laplacian = cv2.convertScaleAbs(dst) | ||||
| 
 | ||||
|     # 4. LoG 边缘算子 & 边缘扩充 & 高斯滤波 | ||||
|     gray = cv2.copyMakeBorder(grayImage, 2, 2, 2, 2, borderType=cv2.BORDER_REPLICATE) | ||||
|     image = cv2.GaussianBlur(gray, (3, 3), 0, 0) | ||||
|     #使用Numpy定义LoG算子 | ||||
|     m1 = np.array( | ||||
|         [[0, 0, -1, 0, 0], [0, -1, -2, -1, 0], [-1, -2, 16, -2, -1], [0, -1, -2, -1, 0], [0, 0, -1, 0, 0]]) | ||||
|     image1 = np.zeros(image.shape) | ||||
|     rows = image.shape[0] | ||||
|     cols = image.shape[1] | ||||
|     for i in range(2, rows - 2): | ||||
|         for j in range(2, cols - 2): | ||||
|             image1[i, j] = np.sum((m1 * image[i - 2:i + 3, j - 2:j + 3])) | ||||
| 
 | ||||
|     Log = cv2.convertScaleAbs(image1) | ||||
| 
 | ||||
|     # 5. Canny 边缘检测 | ||||
|     image = cv2.GaussianBlur(grayImage, (3, 3), 0) | ||||
|     gradx = cv2.Sobel(image, cv2.CV_16SC1, 1, 0) | ||||
|     grady = cv2.Sobel(image, cv2.CV_16SC1, 0, 1) | ||||
|     edge_output = cv2.Canny(gradx, grady, 50, 150) | ||||
| 
 | ||||
|     # 调整大小以匹配原始图像大小 | ||||
|     Roberts = cv2.resize(Roberts, (grayImage.shape[1], grayImage.shape[0])) | ||||
|     Sobel = cv2.resize(Sobel, (grayImage.shape[1], grayImage.shape[0])) | ||||
|     Laplacian = cv2.resize(Laplacian, (grayImage.shape[1], grayImage.shape[0])) | ||||
|     Log = cv2.resize(Log, (grayImage.shape[1], grayImage.shape[0])) | ||||
|     edge_output = cv2.resize(edge_output, (grayImage.shape[1], grayImage.shape[0])) | ||||
| 
 | ||||
|     # 将结果水平堆叠在一起 | ||||
|     combined = np.hstack((Roberts, Sobel, Laplacian, Log, edge_output)) | ||||
| 
 | ||||
|     # 更新 edge 变量为 PIL.Image 对象 | ||||
|     edge = Image.fromarray(combined) | ||||
| 
 | ||||
|     # 创建 Toplevel 窗口显示边缘检测结果 | ||||
|     try: | ||||
|         VergeWin.destroy() | ||||
|     except Exception as e: | ||||
|         print("NVM") | ||||
|     finally: | ||||
|         VergeWin = Toplevel() | ||||
|         VergeWin.attributes('-topmost', True) | ||||
|     VergeWin.geometry("720x300") | ||||
|     VergeWin.resizable(True, True)  # 可缩放 | ||||
|     VergeWin.title("边缘检测结果") | ||||
| 
 | ||||
|     # 显示图像 | ||||
|     LabelPic = tk.Label(VergeWin, 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(VergeWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, | ||||
|                          command=savefile) | ||||
|     btn_save.pack(pady=10) | ||||
| 
 | ||||
| 
 | ||||
| def line_chan(root): | ||||
|     """ | ||||
|     检测图像中的线条变化并显示结果 | ||||
|     """ | ||||
|     global src, LineWin, edge | ||||
| 
 | ||||
|     # 判断是否已经选取图片 | ||||
|     if src is None: | ||||
|         messagebox.showerror("错误", "没有选择图片!") | ||||
|         return | ||||
| 
 | ||||
|     # 使用高斯模糊和 Canny 边缘检测处理图像 | ||||
|     img = cv2.GaussianBlur(src, (3, 3), 0) | ||||
|     edges = cv2.Canny(img, 50, 150, apertureSize=3) | ||||
| 
 | ||||
|     # 使用 HoughLines 算法检测直线 | ||||
|     lines = cv2.HoughLines(edges, 1, np.pi / 2, 118) | ||||
|     result = img.copy() | ||||
|     for i_line in lines: | ||||
|         for line in i_line: | ||||
|             rho = line[0] | ||||
|             theta = line[1] | ||||
|             if (theta < (np.pi / 4.)) or (theta > (3. * np.pi / 4.0)):  # 垂直直线 | ||||
|                 pt1 = (int(rho / np.cos(theta)), 0) | ||||
|                 pt2 = (int((rho - result.shape[0] * np.sin(theta)) / np.cos(theta)), result.shape[0]) | ||||
|                 cv2.line(result, pt1, pt2, (0, 0, 255)) | ||||
|             else: | ||||
|                 pt1 = (0, int(rho / np.sin(theta))) | ||||
|                 pt2 = (result.shape[1], int((rho - result.shape[1] * np.cos(theta)) / np.sin(theta))) | ||||
|                 cv2.line(result, pt1, pt2, (0, 0, 255), 1) | ||||
| 
 | ||||
|     # 使用 HoughLinesP 算法检测直线段 | ||||
|     minLineLength = 200 | ||||
|     maxLineGap = 15 | ||||
|     linesP = cv2.HoughLinesP(edges, 1, np.pi / 180, 80, minLineLength, maxLineGap) | ||||
|     result_P = img.copy() | ||||
|     for i_P in linesP: | ||||
|         for x1, y1, x2, y2 in i_P: | ||||
|             cv2.line(result_P, (x1, y1), (x2, y2), (0, 255, 0), 3) | ||||
| 
 | ||||
|     # 将结果水平堆叠在一起 | ||||
|     combined = np.hstack((result, result_P)) | ||||
| 
 | ||||
|     # 更新 edge 变量为 PIL.Image 对象 | ||||
|     edge = Image.fromarray(result) | ||||
| 
 | ||||
|     # 创建 Toplevel 窗口显示线条变化检测结果 | ||||
|     try: | ||||
|         LineWin.destroy() | ||||
|     except Exception as e: | ||||
|         print("NVM") | ||||
|     finally: | ||||
|         LineWin = Toplevel() | ||||
|         LineWin.attributes('-topmost', True) | ||||
|     LineWin.geometry("720x300") | ||||
|     LineWin.resizable(True, True)  # 可缩放 | ||||
|     LineWin.title("线条变化检测结果") | ||||
| 
 | ||||
|     # 显示图像 | ||||
|     LabelPic = tk.Label(LineWin, text="IMG", width=720, height=240) | ||||
|     image = ImageTk.PhotoImage(Image.fromarray(cv2.cvtColor(combined, cv2.COLOR_BGR2RGB))) | ||||
|     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(LineWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, | ||||
|                          command=savefile) | ||||
|     btn_save.pack(pady=10) | ||||
| import tkinter as tk | ||||
| from tkinter import filedialog, messagebox | ||||
| from tkinter import 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  # 用于存储处理后的图像 | ||||
| 
 | ||||
| ThreWin = None  # 用于阈值化处理结果窗口 | ||||
| VergeWin = None  # 用于边缘检测结果窗口 | ||||
| LineWin = 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) | ||||
| 
 | ||||
|         # 使用 cv2.imdecode 加载图像,处理中文路径 | ||||
|         src_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED) | ||||
|         if src_temp is None: | ||||
|             messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径") | ||||
|             return | ||||
|         # 将图像从 BGR 转换为 RGB | ||||
|         src = cv2.cvtColor(src_temp, cv2.COLOR_BGR2RGB) | ||||
| 
 | ||||
|         # 检查 img_label 是否存在且有效,如果不存在则创建新的 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) | ||||
| 
 | ||||
|         # 使用 PIL 加载并缩放图像以适应标签大小 | ||||
|         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 | ||||
|     # 确保 edge 变量已定义 | ||||
|     if edge is not None: | ||||
|         try: | ||||
|             edge.save(filename) | ||||
|             messagebox.showinfo("保存成功", "图片保存成功!") | ||||
|         except Exception as e: | ||||
|             messagebox.showerror("保存失败", f"无法保存图片: {e}") | ||||
|     else: | ||||
|         messagebox.showerror("保存失败", "没有图像可保存") | ||||
| 
 | ||||
| def threshold(root): | ||||
|     """ | ||||
|     对图像进行阈值化处理并显示结果 | ||||
|     """ | ||||
|     global src, ThreWin, edge | ||||
| 
 | ||||
|     # 判断是否已经选取图片 | ||||
|     if src is None: | ||||
|         messagebox.showerror("错误", "没有选择图片!") | ||||
|         return | ||||
| 
 | ||||
|     # 转变图像为灰度图 | ||||
|     gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) | ||||
| 
 | ||||
|     # TRIANGLE 自适应阈值 | ||||
|     ret, TRIANGLE_img = cv2.threshold(gray, 0, 255, cv2.THRESH_TRIANGLE) | ||||
|     # OTSU 自适应阈值 | ||||
|     ret, OTSU_img = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) | ||||
|     # TRUNC 截断阈值(200) | ||||
|     ret, TRUNC_img = cv2.threshold(gray, 200, 255, cv2.THRESH_TRUNC) | ||||
|     # TOZERO 归零阈值(100) | ||||
|     ret, TOZERO__img = cv2.threshold(gray, 100, 255, cv2.THRESH_TOZERO) | ||||
| 
 | ||||
|     # 将处理后的图像拼接在一起 | ||||
|     combined = np.hstack((TRIANGLE_img, OTSU_img, TRUNC_img, TOZERO__img)) | ||||
| 
 | ||||
|     # 更新 edge 变量 | ||||
|     edge = Image.fromarray(combined) | ||||
| 
 | ||||
|     # 创建 Toplevel 窗口用于显示处理结果 | ||||
|     try: | ||||
|         ThreWin.destroy() | ||||
|     except Exception as e: | ||||
|         print("NVM") | ||||
|     finally: | ||||
|         ThreWin = Toplevel() | ||||
|         ThreWin.attributes('-topmost', True) | ||||
|     ThreWin.geometry("720x300") | ||||
|     ThreWin.resizable(True, True)  # 可缩放 | ||||
|     ThreWin.title("阈值化结果") | ||||
| 
 | ||||
|     # 显示图像 | ||||
|     LabelPic = tk.Label(ThreWin, 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(ThreWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, | ||||
|                          command=savefile) | ||||
|     btn_save.pack(pady=10) | ||||
| 
 | ||||
| def verge(root): | ||||
|     """ | ||||
|     对图像进行边缘检测并显示结果 | ||||
|     """ | ||||
|     global src, VergeWin, edge | ||||
| 
 | ||||
|     # 判断是否已经选取图片 | ||||
|     if src is None: | ||||
|         messagebox.showerror("错误", "没有选择图片!") | ||||
|         return | ||||
| 
 | ||||
|     # 转变图像为灰度图 | ||||
|     grayImage = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) | ||||
| 
 | ||||
|     # 1. Roberts 算子 | ||||
|     kernelx = np.array([[-1, 0], [0, 1]], dtype=int) | ||||
|     kernely = np.array([[0, -1], [1, 0]], dtype=int) | ||||
|     x = cv2.filter2D(grayImage, cv2.CV_16S, kernelx) | ||||
|     y = cv2.filter2D(grayImage, cv2.CV_16S, kernely) | ||||
|     absX = cv2.convertScaleAbs(x) | ||||
|     absY = cv2.convertScaleAbs(y) | ||||
|     Roberts = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) | ||||
| 
 | ||||
|     # 2. Sobel 算子 | ||||
|     x = cv2.Sobel(grayImage, cv2.CV_16S, 1, 0) | ||||
|     y = cv2.Sobel(grayImage, cv2.CV_16S, 0, 1) | ||||
|     absX = cv2.convertScaleAbs(x) | ||||
|     absY = cv2.convertScaleAbs(y) | ||||
|     Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) | ||||
| 
 | ||||
|     # 3. 拉普拉斯算法 & 高斯滤波 | ||||
|     gray = cv2.GaussianBlur(grayImage, (5, 5), 0, 0) | ||||
|     dst = cv2.Laplacian(gray, cv2.CV_16S, ksize=3) | ||||
|     Laplacian = cv2.convertScaleAbs(dst) | ||||
| 
 | ||||
|     # 4. LoG 边缘算子 & 边缘扩充 & 高斯滤波 | ||||
|     gray = cv2.copyMakeBorder(grayImage, 2, 2, 2, 2, borderType=cv2.BORDER_REPLICATE) | ||||
|     image = cv2.GaussianBlur(gray, (3, 3), 0, 0) | ||||
|     #使用Numpy定义LoG算子 | ||||
|     m1 = np.array( | ||||
|         [[0, 0, -1, 0, 0], [0, -1, -2, -1, 0], [-1, -2, 16, -2, -1], [0, -1, -2, -1, 0], [0, 0, -1, 0, 0]]) | ||||
|     image1 = np.zeros(image.shape) | ||||
|     rows = image.shape[0] | ||||
|     cols = image.shape[1] | ||||
|     for i in range(2, rows - 2): | ||||
|         for j in range(2, cols - 2): | ||||
|             image1[i, j] = np.sum((m1 * image[i - 2:i + 3, j - 2:j + 3])) | ||||
| 
 | ||||
|     Log = cv2.convertScaleAbs(image1) | ||||
| 
 | ||||
|     # 5. Canny 边缘检测 | ||||
|     image = cv2.GaussianBlur(grayImage, (3, 3), 0) | ||||
|     gradx = cv2.Sobel(image, cv2.CV_16SC1, 1, 0) | ||||
|     grady = cv2.Sobel(image, cv2.CV_16SC1, 0, 1) | ||||
|     edge_output = cv2.Canny(gradx, grady, 50, 150) | ||||
| 
 | ||||
|     # 调整大小以匹配原始图像大小 | ||||
|     Roberts = cv2.resize(Roberts, (grayImage.shape[1], grayImage.shape[0])) | ||||
|     Sobel = cv2.resize(Sobel, (grayImage.shape[1], grayImage.shape[0])) | ||||
|     Laplacian = cv2.resize(Laplacian, (grayImage.shape[1], grayImage.shape[0])) | ||||
|     Log = cv2.resize(Log, (grayImage.shape[1], grayImage.shape[0])) | ||||
|     edge_output = cv2.resize(edge_output, (grayImage.shape[1], grayImage.shape[0])) | ||||
| 
 | ||||
|     # 将结果水平堆叠在一起 | ||||
|     combined = np.hstack((Roberts, Sobel, Laplacian, Log, edge_output)) | ||||
| 
 | ||||
|     # 更新 edge 变量为 PIL.Image 对象 | ||||
|     edge = Image.fromarray(combined) | ||||
| 
 | ||||
|     # 创建 Toplevel 窗口显示边缘检测结果 | ||||
|     try: | ||||
|         VergeWin.destroy() | ||||
|     except Exception as e: | ||||
|         print("NVM") | ||||
|     finally: | ||||
|         VergeWin = Toplevel() | ||||
|         VergeWin.attributes('-topmost', True) | ||||
|     VergeWin.geometry("720x300") | ||||
|     VergeWin.resizable(True, True)  # 可缩放 | ||||
|     VergeWin.title("边缘检测结果") | ||||
| 
 | ||||
|     # 显示图像 | ||||
|     LabelPic = tk.Label(VergeWin, 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(VergeWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, | ||||
|                          command=savefile) | ||||
|     btn_save.pack(pady=10) | ||||
| 
 | ||||
| 
 | ||||
| def line_chan(root): | ||||
|     """ | ||||
|     检测图像中的线条变化并显示结果 | ||||
|     """ | ||||
|     global src, LineWin, edge | ||||
| 
 | ||||
|     # 判断是否已经选取图片 | ||||
|     if src is None: | ||||
|         messagebox.showerror("错误", "没有选择图片!") | ||||
|         return | ||||
| 
 | ||||
|     # 使用高斯模糊和 Canny 边缘检测处理图像 | ||||
|     img = cv2.GaussianBlur(src, (3, 3), 0) | ||||
|     edges = cv2.Canny(img, 50, 150, apertureSize=3) | ||||
| 
 | ||||
|     # 使用 HoughLines 算法检测直线 | ||||
|     lines = cv2.HoughLines(edges, 1, np.pi / 2, 118) | ||||
|     result = img.copy() | ||||
|     for i_line in lines: | ||||
|         for line in i_line: | ||||
|             rho = line[0] | ||||
|             theta = line[1] | ||||
|             if (theta < (np.pi / 4.)) or (theta > (3. * np.pi / 4.0)):  # 垂直直线 | ||||
|                 pt1 = (int(rho / np.cos(theta)), 0) | ||||
|                 pt2 = (int((rho - result.shape[0] * np.sin(theta)) / np.cos(theta)), result.shape[0]) | ||||
|                 cv2.line(result, pt1, pt2, (0, 0, 255)) | ||||
|             else: | ||||
|                 pt1 = (0, int(rho / np.sin(theta))) | ||||
|                 pt2 = (result.shape[1], int((rho - result.shape[1] * np.cos(theta)) / np.sin(theta))) | ||||
|                 cv2.line(result, pt1, pt2, (0, 0, 255), 1) | ||||
| 
 | ||||
|     # 使用 HoughLinesP 算法检测直线段 | ||||
|     minLineLength = 200 | ||||
|     maxLineGap = 15 | ||||
|     linesP = cv2.HoughLinesP(edges, 1, np.pi / 180, 80, minLineLength, maxLineGap) | ||||
|     result_P = img.copy() | ||||
|     for i_P in linesP: | ||||
|         for x1, y1, x2, y2 in i_P: | ||||
|             cv2.line(result_P, (x1, y1), (x2, y2), (0, 255, 0), 3) | ||||
| 
 | ||||
|     # 将结果水平堆叠在一起 | ||||
|     combined = np.hstack((result, result_P)) | ||||
| 
 | ||||
|     # 更新 edge 变量为 PIL.Image 对象 | ||||
|     edge = Image.fromarray(result) | ||||
| 
 | ||||
|     # 创建 Toplevel 窗口显示线条变化检测结果 | ||||
|     try: | ||||
|         LineWin.destroy() | ||||
|     except Exception as e: | ||||
|         print("NVM") | ||||
|     finally: | ||||
|         LineWin = Toplevel() | ||||
|         LineWin.attributes('-topmost', True) | ||||
|     LineWin.geometry("720x300") | ||||
|     LineWin.resizable(True, True)  # 可缩放 | ||||
|     LineWin.title("线条变化检测结果") | ||||
| 
 | ||||
|     # 显示图像 | ||||
|     LabelPic = tk.Label(LineWin, text="IMG", width=720, height=240) | ||||
|     image = ImageTk.PhotoImage(Image.fromarray(cv2.cvtColor(combined, cv2.COLOR_BGR2RGB))) | ||||
|     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(LineWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, | ||||
|                          command=savefile) | ||||
|     btn_save.pack(pady=10) | ||||
|  | ||||
					Loading…
					
					
				
		Reference in new issue