import cv2
import numpy as np
import tkinter as tk
import matplotlib
matplotlib.use('TkAgg')
from tkinter import ttk, filedialog, messagebox
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
plt.rcParams['font.sans-serif']=['SimHei']
class MachineVisionApp:
def __init__(self, root):
self.root = root
self.root.title("机械零件视觉检测系统")
self.root.geometry("1200×800")
# 初始化变量
self.original_image=None
self.processed_image = None
self.filename = None
self.setup_ui()
def setup_ui(self):
"""设置用户界面"""
# 主框架
main_frame = ttk.Frame(self.root)
main_frame.pack(fill=tk.BOTH, expand=True, padx=10,pady=10)
# 左侧控制面板
control_frame = ttk.LabelFrame(main_frame, text="处理控制",width=300)
control_frame.pack(side=tk.LEFT, fill=tk.Y, padx=5, pady=5)
control_frame.pack_propagate(False)
display_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=Trve, padx=5, pady=5)
file_frame = ttk.LabelFrane(control_frame, text="文件操作")
file_frame.pack(fill=tk.X, padx=5, pady=5)
# 文件操作区域
file_frame = ttk.LabelFrame(control_frame, text="文件操作")
file_frame.pack(fill=tk.X, padx=5,pady = 5)
ttk.Button(file_frame, text="打开图像",command = self.open_image).pack(fill=tk.x, pady=2)
ttk.Button(file_frame, text="保存结果",comnand = self.save_image).pack(fill=tk.X, pady=2)
ttk, Button(file_frame, text="重置图像",conmmand = self.reset_image).pack(fill=tk.X, pady=2)
# 图像增强
enhance_frame = ttk.LabelFrame(control_frame,text = "图像增强")
enhance_frame.pack(fill=tk.X, padx=5, pady=5)
ttk.Button(enhance_frame, text = "直方图均衡化", command = self.histogram_egualization).pack(fill=tk.X,pady=2)
ttk.Button(enhance_frame,text = "对比度增强",command = self.contrast_enhancement).pack(fill=tk.X,pady=2)
ttk.Button(enhance_frame, text = "伽马校正",command = self.gamma_correction).pack(fill=tk.X,pady = 2)
# 图像滤波
filter_frame = ttk.LabelFrame(control_frame,text = "图像滤波")
filter_frame.pack(fill=tk.X, padx=5, pady=5)
ttk.Button(filter_frame,text = "高斯滤波", command = self.gaussian_blur).pack(fill=tk.X, pady = 2)
ttk.Button(filter_frame, text = "中值滤波", command = self.median_blur).pack(fill=tk.X, pady = 2)
# 边缘检测
edge_frame = ttk.LabelFrame(control_frame, text = "边缘检测")
edge_frame.pack(fill=tk.X,padx = 5,pady = 5)
ttk.Button(edge_frame, text="Sobel算子", command=self.sobel_edge).pack(fill=tk.X, pady=2)
ttk.Button(edge_frame, text="Laplacian算子", command=self.laplacian_edge).pack(fill=tk.X, pady=2)
#形态学处理
morph_frame = ttk.LabeLFrame(control_frame, text="形态学处理")
morph_frame.pack(fill=tk.X,padx=5,pady=5)
ttk.Button(morph_frame,text="腐蚀操作",command=self.erosion).pack(fill=tk.X, pady=2)
ttk.Button(morph_frame,text="膨胀操作",command=self.dilation).pack(fill=tk.X, pady=2)
ttk.Button(morph_frame,text="开运算", command=self.opening).pack(fill=tk.X, pady=2)
ttk.Button(morph_frame,text="闭运算", command=self.closing).pack(fill=tk.X, pady=2)
#几何变换
geom_frame = ttk.LabelFrame(control_frame, text="几何变换")
geom_frame.pack(fill=tk.X, padx=5, pady=5)
ttk.Button(geom_frame,text="旋转90°",command=self.rotate_90).pack(fill=tk.X,pady=2)
ttk.Button(geom_frame, text="水平翻转", command=self.flip_horizontal).pack(fill=tk.X, pady=2)
ttk.Button(geom_frame, text="垂直翻转", command=self.flip_vertical).pack(fill=tk.X, pady=2)
# 图像显示区域
self.canvas_frame = ttk.Frame(display_frame)
self.canvas_frame.pack(fill=tk.BoTH,expand=True)
#创建matplotlib图形
self.fig, (self.axl, self.ax2) =plt.subplots(nrows=1,ncols=2,figsize=(10,5))
self.axl.set_title("原始图像")
self.ax2.set_title("处理结果")
self.canvas = FigureCanvasTkAgg(self.fig,master=self.canvas_frame)
self.canvas.draw()
self.canvas.get_tk_widget().pack(fill=tk.BoTH,expand=True)
def open_image(self):
"""打开图像文件"""
filename = filedialog.askopenfilename(
filetypes=[("图像文件","*.jpg *.jpeg *.png *.bmp *.tiff")]
)
if filename:
self.filename = filename
self.original_image = cv2.imread(filename)
if self.original_image is not None:
self.processed_image = self.original_image.copy()
self.display_images()
else:
messagebox.showerror( "错误", "无法打开图像文件")
def save_image(self):
""""保存处理后的图像"""
if self.processed_image is not None:
filename = filedialog.asksaveasfilename(
filetypes=[("PNG文件","*.png"),("JPEG文件","*.jpg"),("所有文件","*.*")]
)
if filename:
cv2.imwrite(filename, self.processed_image)
messagebox.showinfo("成功","图像已保存")
else:
messagebox.showwarning("警告", "没有图像可保存")
def resetimage(self):
"""重置图像"""
if self.originalimage is not None:
self.processed_image = self.origlnal_image.copy()
self.display_images()
def display_images(self):
"""显示原始图像和处理后的图像"""
if self.original_image is not None and self.processed_image is not None:
# 清除之前的图像
self.axl.clear()
self.ax2.clear()
#转换BGR到RGB用于显示
original_rgb = cv2.cvtColor(self.original_image, cv2.C0L0R_BGR2RGB)
processed_rgb = cv2.cvtColor(self.processed_image, cv2.C0L0R_BGR2RGB)
#显示图像
self.axl.imshow(original_rgb)
self.axl.settitle("原始图像")
self.axl.axis('off')
self.ax2.imshow(processed_rgb)
self.ax2.set_title("处理结果")
self.ax2.axis('off')
self.canvas.draw()
#图像增强方法
def histogram_egualization(self):
"""直方图均衡化"""
if self.processed_image is not None:
#转换为YUV色彩空间
img_yuv = cv2.cvtcolor(self.processed_image, cv2.c0L0R_BGR2YUV)
#对通道进行直方图均衡化
img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:, :, 0])
#转换回BGR
self.processed_image = cv2.cvtColor(img_yuv, cv2.c0L0R_YUV2BGR)
self.display_images()
def contrast_enhancement(self):
"""对比度增强"""
if self.processedimageisnotNone:
# 使用CLAHE(限制对比度自适应直方图均衡化)
lab = cv2.cvtColor(self.processed_image, cv2.C0L0R_BGR2LAB)
labplanes=list(cv2.split(lab))
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
lab_planes[o] = clahe.apply(lab_planes[0])
lab = cv2.merge(lab_planes)
self.processedimage=cv2.cvtColor(lab.cv2.C0L0RLAB2BGR)
self.display_images()
def gamma_correction(self):
"""伽马校正"""
if self.processed_image is not None:
gamma = 1.5
inv_gamma = 1.0 / gamma
table = np.array([((i / 255.0) ** inv_gamma) * 255 for i in np.arange(0, 256)]).astype("uint8")
self.processed_image = cv2.LuT(self.processed_image, table)
self.display_images()
# 图像滤波方法
def gaussian_blur(self):
"""高斯滤波"""
if self.processed_image is not None:
self.processed_image = cv2.GaussianBlur(self.processed_image, (5, 5), 0)
self.display_images()
def median_blur(self):
"""中值滤波"""
if self.processed_image is not None:
self.processed_image = cv2.medianBlur(self.processed_image,5)
self.display_images()
def bilateral_filter(self):
"""双边滤波"""
if self.processed_image is not None:
self.processed_image = cv2.bilateralFilter(self.processed_image, 9, 75, 75)
self.display_images()
#边缘检测方法
def canny_edge(self):
"""Canny边缘检测"""
if self.processed_image is not None:
gray= cv2.cvtColor(self.processed_image, cv2.C0L0R_GRAY2BGR)
#使用固定國值
edges = cv2.Canny(gray, 100, 200)
# 将边缘图像转换为彩色显示
self.processed_image = cv2.cvtColor(edges, cv2.C0L0R_GRAY2BGR)
self.display_images()
def sobel_edge(self):
"""Sobe边缘检测"""
if self.processedimageisnotNone:
gray = cv2.cvtColor(self.processed_image, cv2.C0L0R_BGR2GRAY)
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
sobel = cv2.maqnitude(sobelx, sobely)
sobel = np.uint8(sobel)
self.processed_image = cv2.cvtColor(sobel, cv2.C0L0R_GRAY2BGR)
self.display_images()
def laplacian_edge(self):
"""LapLacian边缘检测"""
if self.processed_image is not None:
gray = cv2.cvtColor(self.processed_image, cv2.C0L0R_BGR2GRAY)
laplacian = cv2.Laplacian(gray, cv2.CV_64F)
laplacian = np.uint8(np.absolute(laplacian))
self.processed_1mage=cv2.cvtColor(laplaclan,cv2.C0L0R_GRAY2BGR)
self.display_images()
# 形态学处理方法
def erosion(self):
"""腐蚀操作"""
if self.processed_image is not None:
kernel = np.ones( shape,(5,5) , np.uint8)
self.processed_image = cv2.erode(self.processed_image, kernel, iterations=1)
self.display_images()
def dilation(self):
"""膨胀操作"""
if self.processed_image is not None:
kernel = np.ones( shape,(5, 5), np.uint8)
self.processed_image = cv2.dilate(self.processed_image,kernel, iterations=1)
self.display_images()
def opening(self):
"""开运算"""
if self.processed_image is not None:
kernel = np.ones( shape,(5, 5), np.uint8)
self.processed_image = cv2.morphologyEx(self.processed_image,cv2.MoRPH_oPEN,kernel)
self.display_images()
def closing(self):
"""闭运算"""
if self.processed_image is not None:
kernel = np.ones( shape,(5, 5), np.uint8)
self.processed_image = cv2.morphologyEx(self.processed_image,cv2.MoRPH_cLoSE, kernel)
self.display_images()
#几何变换方法
def rotate_90(self):
"""旋转90度"""
if self.processed_image is not None:
self.processed_image = cv2.rotate(self.processed_image, cv2.R0TATE_90_CL0cKwISE)
self.display_images()
def fliphorizontal(self):
"""水平翻转"""
if self.processed_imageisnotNone:
self.processed_image = cv2.flip(self.processed_image, 1)
self.display_images()
def flip_vertical(self):
"""垂直翻转"""
if self.processed_image is not None:
self.processed_image = cv2.flip(self.processed_image, 0)
self.display_images()
def main():
root=tk.Tk()
app = MachineVisionApp(root)
root.malnloop()
if __name__ == "__main__":
main()