You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

285 lines
9.6 KiB

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 # 用于存储处理后的图像
GraylineWin = None # 线性变换窗口
GraylogWin = None # 对数变换窗口
EqualWin = None # 直方图均衡化窗口
RegulWin = 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:
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) # 转换为 RGB 格式
# 创建或更新图像标签
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 = Image.fromarray(src) # 更新 edge 变量为 PIL.Image 对象
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 line_tra(root):
"""
进行线性变换
"""
global src, GraylineWin, edge
# 判断是否已经选择图片
if src is None:
messagebox.showerror("错误", "没有选择图片!")
return
gray_src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # 转换为灰度图
a = 20
b = 241
c = 0
d = 255
result = (d - c) / (b - a) * gray_src + (b * c - a * d) / (b - a) # 线性变换公式
edge = Image.fromarray(result) # 更新 edge 变量
# 创建或更新线性变换结果窗口
try:
GraylineWin.destroy()
except Exception:
print("NVM")
finally:
GraylineWin = Toplevel()
GraylineWin.attributes('-topmost', True)
GraylineWin.geometry("360x300")
GraylineWin.resizable(True, True)
GraylineWin.title("线性变换结果")
# 显示处理后的图像
LabelPic = tk.Label(GraylineWin, 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(GraylineWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=savefile)
btn_save.pack(pady=10)
def log_tra(root):
"""
进行对数变换
"""
global src, GraylogWin, edge
# 判断是否已经选择图片
if src is None:
messagebox.showerror("错误", "没有选择图片!")
return
gray_src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # 转换为灰度图
C = 255 / np.log(1 + 255) # 对数变换常数
result = np.array(C * np.log(1 + gray_src), np.float64) # 对数变换公式
edge = Image.fromarray(result) # 更新 edge 变量
# 创建或更新对数变换结果窗口
try:
GraylogWin.destroy()
except Exception:
print("NVM")
finally:
GraylogWin = Toplevel()
GraylogWin.attributes('-topmost', True)
GraylogWin.geometry("360x300")
GraylogWin.resizable(True, True)
GraylogWin.title("对数变换结果")
# 显示处理后的图像
LabelPic = tk.Label(GraylogWin, 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(GraylogWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=savefile)
btn_save.pack(pady=10)
def equal(root):
"""
进行直方图均衡化
"""
global src, EqualWin, edge
# 判断是否已经选择图片
if src is None:
messagebox.showerror("错误", "没有选择图片!")
return
gray_src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # 转换为灰度图
original_size = gray_src.shape # 保存原始图像尺寸
gray_src_resized = cv2.resize(gray_src, (256, 256)) # 图像放缩到 256 x 256
hist = cv2.calcHist([gray_src_resized], [0], None, [256], [0, 256]) # 计算直方图
equ_resized = cv2.equalizeHist(gray_src_resized) # 均衡化
equ = cv2.resize(equ_resized, (original_size[1], original_size[0])) # 恢复均衡化后的图像到原始尺寸
edge = Image.fromarray(equ) # 更新 edge 变量
# 创建或更新直方图均衡化结果窗口
try:
EqualWin.destroy()
except Exception as e:
print("NVM")
finally:
EqualWin = Toplevel()
EqualWin.attributes('-topmost', True)
EqualWin.geometry("360x300")
EqualWin.resizable(True, True)
EqualWin.title("直方图均衡化结果")
# 显示处理后的图像
LabelPic = tk.Label(EqualWin, text="IMG", width=720, height=480)
image = ImageTk.PhotoImage(Image.fromarray(equ))
LabelPic.image = image
LabelPic['image'] = image
LabelPic.bind('<Configure>', lambda event: changeSize(event, equ, LabelPic))
LabelPic.pack(fill=tk.BOTH, expand=tk.YES)
btn_save = tk.Button(EqualWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=savefile)
btn_save.pack(pady=10)
def regul(root):
"""
进行直方图正规化
"""
global src, RegulWin, edge
# 判断是否已经选择图片
if src is None:
messagebox.showerror("错误", "没有选择图片!")
return
gray_src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # 转换为灰度图
original_size = gray_src.shape # 保存原始图像尺寸
gray_src_resized = cv2.resize(gray_src, (256, 256)) # 图像放缩到 256 x 256
hist = cv2.calcHist([gray_src_resized], [0], None, [256], [0, 256]) # 计算直方图
cv2.normalize(hist, hist, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX) # 正规化
result = np.zeros((256, 256), dtype=np.uint8) # 初始化结果图像
for i in range(256):
result[gray_src_resized == i] = hist[i] # 应用正规化直方图
equ = cv2.resize(result, (original_size[1], original_size[0])) # 恢复正规化后的图像到原始尺寸
edge = Image.fromarray(equ) # 更新 edge 变量
# 创建或更新直方图正规化结果窗口
try:
RegulWin.destroy()
except Exception as e:
print("NVM")
finally:
RegulWin = Toplevel()
RegulWin.attributes('-topmost', True)
RegulWin.geometry("360x300")
RegulWin.resizable(True, True)
RegulWin.title("直方图正规化结果")
# 显示处理后的图像
LabelPic = tk.Label(RegulWin, text="IMG", width=720, height=480)
image = ImageTk.PhotoImage(Image.fromarray(equ))
LabelPic.image = image
LabelPic['image'] = image
LabelPic.bind('<Configure>', lambda event: changeSize(event, equ, LabelPic))
LabelPic.pack(fill=tk.BOTH, expand=tk.YES)
btn_save = tk.Button(RegulWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20, command=savefile)
btn_save.pack(pady=10)