|
|
|
|
import tkinter as tk
|
|
|
|
|
from tkinter import filedialog
|
|
|
|
|
from tkinter import messagebox
|
|
|
|
|
import cv2
|
|
|
|
|
import numpy as np
|
|
|
|
|
from PIL import Image, ImageTk
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MyApp:
|
|
|
|
|
def __init__(self, root):
|
|
|
|
|
# 三个frame从左到右分别放置原图,结果图,控制台,标为123
|
|
|
|
|
self.frame1 = None
|
|
|
|
|
self.frame2 = None
|
|
|
|
|
self.frame3 = None
|
|
|
|
|
self.src = None # 原始图像
|
|
|
|
|
# self.src = cv2.imread("fxe.png")
|
|
|
|
|
self.image = None # 结果输出图像
|
|
|
|
|
self.src2 = None # 二元运算的第二张图
|
|
|
|
|
self.tem_img = None # 临时保存本地的图片
|
|
|
|
|
|
|
|
|
|
# UI设置
|
|
|
|
|
self.root = root
|
|
|
|
|
self.root.title("简易数字图像处理系统")
|
|
|
|
|
self.root.state('zoomed') # 窗口最大化
|
|
|
|
|
# 获取窗口大小,得到窗口大小(减去底部任务栏的高度)
|
|
|
|
|
self.width = root.winfo_screenwidth()
|
|
|
|
|
self.height = root.winfo_screenheight() - 71
|
|
|
|
|
# frame12的宽高
|
|
|
|
|
self.fwidth = int(self.width * 7 / 16)
|
|
|
|
|
self.fheight = self.height
|
|
|
|
|
# console控制台的宽高
|
|
|
|
|
self.cwidth = int(self.width * 2 / 16)
|
|
|
|
|
self.cheight = self.height
|
|
|
|
|
|
|
|
|
|
self.create_widget() # 布置组件
|
|
|
|
|
# 布置菜单
|
|
|
|
|
self.menu_bar = tk.Menu(root)
|
|
|
|
|
root.config(menu=self.menu_bar)
|
|
|
|
|
self.create_menu()
|
|
|
|
|
|
|
|
|
|
def create_widget(self):
|
|
|
|
|
# 布置组件
|
|
|
|
|
self.frame1 = tk.Frame(root, width=self.fwidth, height=920, bd=2, relief="ridge")
|
|
|
|
|
self.frame2 = tk.Frame(root, width=self.fwidth, height=920, bd=2, relief="ridge")
|
|
|
|
|
self.frame3 = tk.Frame(root, width=1600 - 2 * self.fwidth, height=920, bd=2, relief="ridge")
|
|
|
|
|
self.frame1.place(x=0, y=0, anchor="nw")
|
|
|
|
|
self.frame2.place(x=self.fwidth, y=0, anchor="nw")
|
|
|
|
|
self.frame3.place(x=2 * self.fwidth, y=0, anchor="nw")
|
|
|
|
|
label1 = tk.Label(self.frame1, text="原始图像", font=("宋体", 30))
|
|
|
|
|
label1.place(x=self.fwidth / 2 - 100, y=15, anchor="nw")
|
|
|
|
|
label2 = tk.Label(self.frame2, text="输出图像", font=("宋体", 30))
|
|
|
|
|
label2.place(x=self.fwidth / 2 - 100, y=15, anchor="nw")
|
|
|
|
|
label3 = tk.Label(self.frame3, text="控制台", font=("宋体", 30))
|
|
|
|
|
label3.place(x=self.cwidth / 2 - 60, y=15, anchor="nw")
|
|
|
|
|
self.src_panel = tk.Label(self.frame1, image=None)
|
|
|
|
|
self.img_panel = tk.Label(self.frame2, image=None)
|
|
|
|
|
|
|
|
|
|
def create_menu(self):
|
|
|
|
|
# 布置菜单
|
|
|
|
|
self.menu_bar.add_cascade(label="加载图片", command=self.load_src)
|
|
|
|
|
self.menu_bar.add_cascade(label="加载输出图像", command=self.load_image_use_src)
|
|
|
|
|
|
|
|
|
|
self.file_menu = tk.Menu(self.menu_bar, tearoff=0)
|
|
|
|
|
self.file_menu.add_command(label="灰化", command=self.convert_to_gray)
|
|
|
|
|
self.file_menu.add_command(label="算术运算", command=self.arithmetic_calculation)
|
|
|
|
|
self.file_menu.add_command(label="缩放旋转图像", command=self.rotate_image)
|
|
|
|
|
self.file_menu.add_command(label="翻转", command=self.flip_image)
|
|
|
|
|
self.file_menu.add_command(label="仿射变换", command=self.affine_transform)
|
|
|
|
|
self.file_menu.add_command(label="对数变换", command=self.logarithmic_transform)
|
|
|
|
|
self.file_menu.add_command(label="线性变换", command=self.linear_transform)
|
|
|
|
|
self.file_menu.add_command(label="直方图均衡化", command=self.equalizehist)
|
|
|
|
|
self.file_menu.add_command(label="开运算", command=self.open)
|
|
|
|
|
self.file_menu.add_command(label="闭运算", command=self.close)
|
|
|
|
|
self.menu_bar.add_cascade(label="处理图像", menu=self.file_menu)
|
|
|
|
|
|
|
|
|
|
self.menu_bar.add_cascade(label="保存图片", command=self.save_image)
|
|
|
|
|
|
|
|
|
|
def load_image(self):
|
|
|
|
|
# 加载本地图片至self.tem_img
|
|
|
|
|
file_path = filedialog.askopenfilename()
|
|
|
|
|
if len(file_path) > 0:
|
|
|
|
|
image = cv2.imread(file_path, cv2.IMREAD_COLOR)
|
|
|
|
|
self.tem_img = image
|
|
|
|
|
|
|
|
|
|
def load_src(self):
|
|
|
|
|
# 加载原始图片并显示
|
|
|
|
|
self.load_image()
|
|
|
|
|
self.src = self.tem_img
|
|
|
|
|
self.clear_frame1()
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
self.display_image(self.src, self.frame1)
|
|
|
|
|
|
|
|
|
|
def load_image_use_src(self):
|
|
|
|
|
# 把输出图像加载到原始图像并显示
|
|
|
|
|
if self.image is not None:
|
|
|
|
|
self.src = self.image
|
|
|
|
|
self.clear_frame1()
|
|
|
|
|
self.display_image(self.src, self.frame1)
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "没有输出图像")
|
|
|
|
|
|
|
|
|
|
def display_image(self, image, frame):
|
|
|
|
|
# 将opencv格式的image显示到frame(1或2)
|
|
|
|
|
panel = tk.Label(frame, image=None)
|
|
|
|
|
# 将opencv的图片转换成PIL格式,并等比例适配frame大小
|
|
|
|
|
img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
|
|
|
|
img = Image.fromarray(img)
|
|
|
|
|
width, height = img.size
|
|
|
|
|
rwidth, rheight = 0, 0
|
|
|
|
|
q = width / height
|
|
|
|
|
# 下面将fheight-200是为了空出上下文字的空间
|
|
|
|
|
if q > self.fwidth / (self.fheight - 220): # 图片较宽的情况
|
|
|
|
|
rwidth = self.fwidth
|
|
|
|
|
rheight = 1 / q * self.fwidth
|
|
|
|
|
panel.place(x=0, y=self.fheight / 2 - rheight / 2, anchor="nw")
|
|
|
|
|
else: # 图片较高的情况
|
|
|
|
|
rheight = self.fheight - 175
|
|
|
|
|
rwidth = q * rheight
|
|
|
|
|
panel.place(x=self.fwidth / 2 - rwidth / 2, y=60, anchor="nw")
|
|
|
|
|
img = img.resize((int(rwidth), int(rheight)))
|
|
|
|
|
img = ImageTk.PhotoImage(img)
|
|
|
|
|
panel.configure(image=img)
|
|
|
|
|
panel.image = img
|
|
|
|
|
|
|
|
|
|
# 显示图片大小
|
|
|
|
|
height, width = image.shape[:2] # image是传进来的opencv格式的图片
|
|
|
|
|
width_lab = tk.Label(frame, text=f"宽度:{width}", font=("宋体", 18))
|
|
|
|
|
width_lab.place(x=self.fwidth / 2 - 100, y=self.fheight - 110, anchor="nw")
|
|
|
|
|
height_lab = tk.Label(frame, text=f"高度:{height}", font=("宋体", 18))
|
|
|
|
|
height_lab.place(x=self.fwidth / 2 - 100, y=self.fheight - 60, anchor="nw")
|
|
|
|
|
|
|
|
|
|
def clear_frame1(self):
|
|
|
|
|
for widget in self.frame1.winfo_children():
|
|
|
|
|
widget.destroy()
|
|
|
|
|
label = tk.Label(self.frame1, text="原始图像", font=("宋体", 30))
|
|
|
|
|
label.place(x=self.fwidth / 2 - 100, y=15, anchor="nw")
|
|
|
|
|
|
|
|
|
|
def clear_frame2(self):
|
|
|
|
|
for widget in self.frame2.winfo_children():
|
|
|
|
|
widget.destroy()
|
|
|
|
|
label = tk.Label(self.frame2, text="输出图像", font=("宋体", 30))
|
|
|
|
|
label.place(x=self.fwidth / 2 - 100, y=15, anchor="nw")
|
|
|
|
|
|
|
|
|
|
def clear_frame23(self):
|
|
|
|
|
# 清楚frame23上的所有组件
|
|
|
|
|
self.src2 = None
|
|
|
|
|
for widget in self.frame3.winfo_children():
|
|
|
|
|
widget.destroy()
|
|
|
|
|
label3 = tk.Label(self.frame3, text="控制台", font=("宋体", 30))
|
|
|
|
|
label3.place(x=self.cwidth / 2 - 60, y=15, anchor="nw")
|
|
|
|
|
for widget in self.frame2.winfo_children():
|
|
|
|
|
widget.destroy()
|
|
|
|
|
label2 = tk.Label(self.frame2, text="输出图像", font=("宋体", 30))
|
|
|
|
|
label2.place(x=self.fwidth / 2 - 100, y=15, anchor="nw")
|
|
|
|
|
|
|
|
|
|
def save_image(self):
|
|
|
|
|
# 保存图片至本地
|
|
|
|
|
if self.image is not None:
|
|
|
|
|
file_path = filedialog.asksaveasfilename(defaultextension=".jpg",
|
|
|
|
|
filetypes=[("JPEG files", "*.jpg"), ("PNG files", "*.png")],
|
|
|
|
|
initialfile="image.jpg")
|
|
|
|
|
if file_path:
|
|
|
|
|
cv2.imwrite(file_path, self.image)
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "没有输出图像")
|
|
|
|
|
|
|
|
|
|
def convert_to_gray(self):
|
|
|
|
|
# 灰化图片
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
self.image = cv2.cvtColor(self.src, cv2.COLOR_BGR2GRAY)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def arithmetic_calculation(self):
|
|
|
|
|
# 算术运算
|
|
|
|
|
def add():
|
|
|
|
|
if self.src2 is not None:
|
|
|
|
|
height, width = self.src.shape[:2]
|
|
|
|
|
src2 = cv2.resize(self.src2, (int(width), int(height)))
|
|
|
|
|
self.image = cv2.add(self.src, src2)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def subtract():
|
|
|
|
|
if self.src2 is not None:
|
|
|
|
|
height, width, _ = self.src.shape
|
|
|
|
|
src2 = cv2.resize(self.src2, (int(width), int(height)))
|
|
|
|
|
self.image = cv2.subtract(self.src, src2)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def multiply():
|
|
|
|
|
if self.src2 is not None:
|
|
|
|
|
height, width, _ = self.src.shape
|
|
|
|
|
src2 = cv2.resize(self.src2, (int(width), int(height)))
|
|
|
|
|
img = cv2.subtract(self.src, src2)
|
|
|
|
|
image1_float = np.float32(self.src)
|
|
|
|
|
image2_float = np.float32(img)
|
|
|
|
|
result = cv2.multiply(image1_float, image2_float)
|
|
|
|
|
self.image = np.uint8(result)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def button():
|
|
|
|
|
self.load_image()
|
|
|
|
|
self.src2 = self.tem_img
|
|
|
|
|
|
|
|
|
|
label = tk.Label(self.frame3, image=None)
|
|
|
|
|
img = cv2.cvtColor(self.src2, cv2.COLOR_BGR2RGB)
|
|
|
|
|
img = Image.fromarray(img)
|
|
|
|
|
width, height = img.size
|
|
|
|
|
rwidth, rheight = 0, 0
|
|
|
|
|
q = width / height
|
|
|
|
|
if q > self.cwidth / 400: # 图片较宽的情况
|
|
|
|
|
rwidth = self.cwidth
|
|
|
|
|
rheight = 1 / q * self.cwidth
|
|
|
|
|
label.place(x=0, y=325 - rheight / 2, anchor="nw")
|
|
|
|
|
else:
|
|
|
|
|
rheight = 400
|
|
|
|
|
rwidth = q * 400
|
|
|
|
|
label.place(x=(1600 - 2 * self.fwidth) / 2 - rwidth / 2, y=100, anchor="nw")
|
|
|
|
|
img = img.resize((int(rwidth), int(rheight)))
|
|
|
|
|
img = ImageTk.PhotoImage(img)
|
|
|
|
|
|
|
|
|
|
label.configure(image=img)
|
|
|
|
|
label.image = img
|
|
|
|
|
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
load_but = tk.Button(self.frame3, text="加载第二张图", font=("宋体", 18), command=button)
|
|
|
|
|
load_but.place(x=self.cwidth / 2 - 75, y=100, anchor="nw")
|
|
|
|
|
load_a = tk.Button(self.frame3, text="加法运算", font=("宋体", 18), command=add)
|
|
|
|
|
load_a.place(x=self.cwidth / 2 - 60, y=500, anchor="nw")
|
|
|
|
|
load_s = tk.Button(self.frame3, text="减法运算", font=("宋体", 18), command=subtract)
|
|
|
|
|
load_s.place(x=self.cwidth / 2 - 60, y=600, anchor="nw")
|
|
|
|
|
load_m = tk.Button(self.frame3, text="乘法运算", font=("宋体", 18), command=multiply)
|
|
|
|
|
load_m.place(x=self.cwidth / 2 - 60, y=700, anchor="nw")
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def rotate_image(self):
|
|
|
|
|
# 旋转图像
|
|
|
|
|
def button():
|
|
|
|
|
try:
|
|
|
|
|
angle = int(angel_en.get()) # 旋转角度,可以根据需要调整
|
|
|
|
|
scale = float(scale_en.get())
|
|
|
|
|
except ValueError:
|
|
|
|
|
messagebox.showerror("Error", "输入异常,请输入数字")
|
|
|
|
|
height, width = self.src.shape[:2]
|
|
|
|
|
center = (width // 2, height // 2)
|
|
|
|
|
rotation_matrix = cv2.getRotationMatrix2D(center, angle, scale)
|
|
|
|
|
|
|
|
|
|
cos = np.abs(rotation_matrix[0, 0])
|
|
|
|
|
sin = np.abs(rotation_matrix[0, 1])
|
|
|
|
|
new_width = int((height * sin) + (width * cos))
|
|
|
|
|
new_height = int((height * cos) + (width * sin))
|
|
|
|
|
|
|
|
|
|
# 调整旋转矩阵的平移部分
|
|
|
|
|
rotation_matrix[0, 2] += (new_width / 2) - center[0]
|
|
|
|
|
rotation_matrix[1, 2] += (new_height / 2) - center[1]
|
|
|
|
|
|
|
|
|
|
# 进行仿射变换
|
|
|
|
|
self.image = cv2.warpAffine(self.src, rotation_matrix, (new_width, new_height))
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
angel_lab = tk.Label(self.frame3, text="旋转角度", font=("宋体", 18))
|
|
|
|
|
angel_lab.place(x=10, y=100, anchor="nw")
|
|
|
|
|
angel_lab2 = tk.Label(self.frame3, text="(整数)", font=("宋体", 18))
|
|
|
|
|
angel_lab2.place(x=90, y=150, anchor="nw")
|
|
|
|
|
angel_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
angel_en.place(x=110, y=100, anchor="nw")
|
|
|
|
|
angel_en.insert(0, "0")
|
|
|
|
|
scale_lab = tk.Label(self.frame3, text="缩放因子", font=("宋体", 18))
|
|
|
|
|
scale_lab.place(x=10, y=200, anchor="nw")
|
|
|
|
|
scale_lab = tk.Label(self.frame3, text="(小数)", font=("宋体", 18))
|
|
|
|
|
scale_lab.place(x=90, y=250, anchor="nw")
|
|
|
|
|
scale_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
scale_en.place(x=110, y=200, anchor="nw")
|
|
|
|
|
scale_en.insert(0, "1")
|
|
|
|
|
but = tk.Button(self.frame3, text="运算", font=("宋体", 18), command=button)
|
|
|
|
|
but.place(x=self.cwidth / 2 - 40, y=300, anchor="nw")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def flip_image(self):
|
|
|
|
|
# 翻转图像
|
|
|
|
|
def horizontal():
|
|
|
|
|
self.image = cv2.flip(self.src, 1)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
|
|
|
|
|
def vertical():
|
|
|
|
|
self.image = cv2.flip(self.src, 0)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
|
|
|
|
|
def cross():
|
|
|
|
|
self.image = cv2.flip(self.src, -1)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
h_but = tk.Button(self.frame3, text="水平翻转", font=("宋体", 18), command=horizontal)
|
|
|
|
|
h_but.place(x=self.cwidth / 2 - 60, y=100, anchor="nw")
|
|
|
|
|
v_but = tk.Button(self.frame3, text="垂直翻转", font=("宋体", 18), command=vertical)
|
|
|
|
|
v_but.place(x=self.cwidth / 2 - 60, y=200, anchor="nw")
|
|
|
|
|
c_but = tk.Button(self.frame3, text="对角翻转", font=("宋体", 18), command=cross)
|
|
|
|
|
c_but.place(x=self.cwidth / 2 - 60, y=300, anchor="nw")
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def affine_transform(self):
|
|
|
|
|
def get_coordinates(entry, size):
|
|
|
|
|
coordinates = entry.get().split(',') # 英文逗号
|
|
|
|
|
if len(coordinates) != 2:
|
|
|
|
|
coordinates = entry.get().split(',') # 中文逗号
|
|
|
|
|
if len(coordinates) != 2:
|
|
|
|
|
coordinates = entry.get().split(' ')
|
|
|
|
|
if len(coordinates) != 2:
|
|
|
|
|
messagebox.showerror("Error", "请输入正确的坐标格式,如:x,y")
|
|
|
|
|
return -1, -1
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
x, y = int(coordinates[0]), int(coordinates[1])
|
|
|
|
|
if x > size[0] or y > size[1]:
|
|
|
|
|
messagebox.showerror("Error", "坐标必须在图像内")
|
|
|
|
|
else:
|
|
|
|
|
return x, y
|
|
|
|
|
except ValueError:
|
|
|
|
|
messagebox.showerror("Error", "坐标必须为整数")
|
|
|
|
|
return -1, -1
|
|
|
|
|
|
|
|
|
|
def check():
|
|
|
|
|
return get_coordinates(p1_en, size)[0] != -1 and get_coordinates(p2_en, size)[0] != -1 and \
|
|
|
|
|
get_coordinates(p3_en, size)[0] != -1 and get_coordinates(p4_en, size)[0] != -1 and \
|
|
|
|
|
get_coordinates(p5_en, size)[0] != -1 and get_coordinates(p6_en, size)[0] != -1
|
|
|
|
|
|
|
|
|
|
def show():
|
|
|
|
|
tmp = self.src.copy()
|
|
|
|
|
size = tmp.shape[:2]
|
|
|
|
|
if check():
|
|
|
|
|
radius = int(max(size[0], size[1]) / 100)
|
|
|
|
|
cv2.circle(tmp, get_coordinates(p1_en, size), radius, (255, 0, 0), -1)
|
|
|
|
|
cv2.circle(tmp, get_coordinates(p2_en, size), radius, (0, 255, 0), -1)
|
|
|
|
|
cv2.circle(tmp, get_coordinates(p3_en, size), radius, (0, 0, 255), -1)
|
|
|
|
|
cv2.circle(tmp, get_coordinates(p4_en, size), radius, (255, 0, 0), -1)
|
|
|
|
|
cv2.circle(tmp, get_coordinates(p5_en, size), radius, (0, 255, 0), -1)
|
|
|
|
|
cv2.circle(tmp, get_coordinates(p6_en, size), radius, (0, 0, 255), -1)
|
|
|
|
|
self.clear_frame2()
|
|
|
|
|
self.display_image(tmp, self.frame2)
|
|
|
|
|
|
|
|
|
|
def button():
|
|
|
|
|
if check():
|
|
|
|
|
self.clear_frame2()
|
|
|
|
|
post1 = np.float32([get_coordinates(p1_en, size), get_coordinates(p2_en, size), get_coordinates(p3_en, size)])
|
|
|
|
|
post2 = np.float32([get_coordinates(p4_en, size), get_coordinates(p5_en, size), get_coordinates(p6_en, size)])
|
|
|
|
|
M = cv2.getAffineTransform(post1, post2)
|
|
|
|
|
|
|
|
|
|
self.image = cv2.warpAffine(self.src, M, self.src.shape[:2])
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
size = self.src.shape[:2]
|
|
|
|
|
try_but = tk.Button(self.frame3, text="显示", font=("宋体", 18), command=show)
|
|
|
|
|
try_but.place(x=self.cwidth / 2 - 40, y=150, anchor="nw")
|
|
|
|
|
p1_lab = tk.Label(self.frame3, text="原始点1", font=("宋体", 18))
|
|
|
|
|
p1_lab.place(x=10, y=200, anchor="nw")
|
|
|
|
|
p1_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
p1_en.place(x=100, y=200, anchor="nw")
|
|
|
|
|
p1_en.insert(0, "50 50")
|
|
|
|
|
p2_lab = tk.Label(self.frame3, text="原始点2", font=("宋体", 18))
|
|
|
|
|
p2_lab.place(x=10, y=250, anchor="nw")
|
|
|
|
|
p2_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
p2_en.place(x=100, y=250, anchor="nw")
|
|
|
|
|
p2_en.insert(0, "200 50")
|
|
|
|
|
p3_lab = tk.Label(self.frame3, text="原始点3", font=("宋体", 18))
|
|
|
|
|
p3_lab.place(x=10, y=300, anchor="nw")
|
|
|
|
|
p3_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
p3_en.place(x=100, y=300, anchor="nw")
|
|
|
|
|
p3_en.insert(0, "50 200")
|
|
|
|
|
p4_lab = tk.Label(self.frame3, text="目标点1", font=("宋体", 18))
|
|
|
|
|
p4_lab.place(x=10, y=350, anchor="nw")
|
|
|
|
|
p4_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
p4_en.place(x=100, y=350, anchor="nw")
|
|
|
|
|
p4_en.insert(0, "10 100")
|
|
|
|
|
p5_lab = tk.Label(self.frame3, text="目标点2", font=("宋体", 18))
|
|
|
|
|
p5_lab.place(x=10, y=400, anchor="nw")
|
|
|
|
|
p5_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
p5_en.place(x=100, y=400, anchor="nw")
|
|
|
|
|
p5_en.insert(0, "200 50")
|
|
|
|
|
p6_lab = tk.Label(self.frame3, text="目标点3", font=("宋体", 18))
|
|
|
|
|
p6_lab.place(x=10, y=450, anchor="nw")
|
|
|
|
|
p6_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
p6_en.place(x=100, y=450, anchor="nw")
|
|
|
|
|
p6_en.insert(0, "100 250")
|
|
|
|
|
but = tk.Button(self.frame3, text="运算", font=("宋体", 18),
|
|
|
|
|
command=button)
|
|
|
|
|
but.place(x=self.cwidth / 2 - 40, y=500, anchor="nw")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def logarithmic_transform(self):
|
|
|
|
|
# 对数变换
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
img=cv2.cvtColor(self.src, cv2.COLOR_BGR2GRAY)
|
|
|
|
|
C = 255 / np.log(1 + 255)
|
|
|
|
|
result = C * np.log(1.0 + img)
|
|
|
|
|
self.image = np.uint8(result+0.5)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def linear_transform(self):
|
|
|
|
|
# 线性变换
|
|
|
|
|
|
|
|
|
|
def get_range(entry):
|
|
|
|
|
range = entry.get().split(',') # 英文逗号
|
|
|
|
|
if len(range) != 2:
|
|
|
|
|
range = entry.get().split(',') # 中文逗号
|
|
|
|
|
if len(range) != 2:
|
|
|
|
|
range = entry.get().split(' ')
|
|
|
|
|
if len(range) != 2:
|
|
|
|
|
messagebox.showerror("Error", "请输入正确的范围格式,如:x,y")
|
|
|
|
|
return -1, -1
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
x, y = int(range[0]), int(range[1])
|
|
|
|
|
if 0 > x or 255 < y:
|
|
|
|
|
messagebox.showerror("Error", "范围必须在(0,255)内")
|
|
|
|
|
else:
|
|
|
|
|
return x, y
|
|
|
|
|
except ValueError:
|
|
|
|
|
messagebox.showerror("Error", "坐标必须为整数")
|
|
|
|
|
return -1, -1
|
|
|
|
|
|
|
|
|
|
def check():
|
|
|
|
|
return get_range(p1_en)[0] != -1 and get_range(p2_en)[0] != -1
|
|
|
|
|
|
|
|
|
|
def button():
|
|
|
|
|
if check():
|
|
|
|
|
self.clear_frame2()
|
|
|
|
|
img = cv2.cvtColor(self.src, cv2.COLOR_BGR2GRAY)
|
|
|
|
|
a,b=get_range(p1_en)
|
|
|
|
|
c,d=get_range(p2_en)
|
|
|
|
|
result = (d - c) / (b - a) * img + (b * c - a * d) / (b - a)
|
|
|
|
|
self.image = np.uint8(result + 0.5)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
|
|
|
|
|
p1_lab = tk.Label(self.frame3, text="原始区间", font=("宋体", 18))
|
|
|
|
|
p1_lab.place(x=10, y=200, anchor="nw")
|
|
|
|
|
p1_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
p1_en.place(x=110, y=200, anchor="nw")
|
|
|
|
|
p1_en.insert(0, "50 100")
|
|
|
|
|
p2_lab = tk.Label(self.frame3, text="目标区间", font=("宋体", 18))
|
|
|
|
|
p2_lab.place(x=10, y=250, anchor="nw")
|
|
|
|
|
p2_en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
p2_en.place(x=110, y=250, anchor="nw")
|
|
|
|
|
p2_en.insert(0, "0 255")
|
|
|
|
|
but = tk.Button(self.frame3, text="运算", font=("宋体", 18),
|
|
|
|
|
command=button)
|
|
|
|
|
but.place(x=self.cwidth / 2 - 40, y=300, anchor="nw")
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
def equalizehist(self):
|
|
|
|
|
# 灰化图片
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
img = cv2.cvtColor(self.src,cv2.COLOR_BGR2GRAY)
|
|
|
|
|
self.image = cv2.equalizeHist(img)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def open(self):
|
|
|
|
|
selected_real_value = cv2.MORPH_CROSS
|
|
|
|
|
def get_size(entry,size):
|
|
|
|
|
range = entry.get().split(',') # 英文逗号
|
|
|
|
|
if len(range) != 2:
|
|
|
|
|
range = entry.get().split(',') # 中文逗号
|
|
|
|
|
if len(range) != 2:
|
|
|
|
|
range = entry.get().split(' ')
|
|
|
|
|
if len(range) != 2:
|
|
|
|
|
messagebox.showerror("Error", "请输入正确的范围格式,如:x,y")
|
|
|
|
|
return -1, -1
|
|
|
|
|
try:
|
|
|
|
|
x, y = int(range[0]), int(range[1])
|
|
|
|
|
if x<0 or y<0 or x>size[0] or y>size[1]:
|
|
|
|
|
messagebox.showerror("Error", "范围必须在图像内")
|
|
|
|
|
else:
|
|
|
|
|
return x, y
|
|
|
|
|
except ValueError:
|
|
|
|
|
messagebox.showerror("Error", "坐标必须为整数")
|
|
|
|
|
return -1, -1
|
|
|
|
|
def button():
|
|
|
|
|
kernel = cv2.getStructuringElement(selected_real_value, get_size(en,self.src.shape[:2]))
|
|
|
|
|
self.image = cv2.morphologyEx(self.src, cv2.MORPH_OPEN, kernel)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
def on_option_selected(*args):
|
|
|
|
|
option_value_map = {
|
|
|
|
|
"交叉": cv2.MORPH_CROSS,
|
|
|
|
|
"椭圆": cv2.MORPH_ELLIPSE,
|
|
|
|
|
"矩形": cv2.MORPH_RECT
|
|
|
|
|
}
|
|
|
|
|
nonlocal selected_real_value
|
|
|
|
|
selected_text = selected_value.get()
|
|
|
|
|
selected_real_value = option_value_map[selected_text]
|
|
|
|
|
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
|
|
|
|
|
lab = tk.Label(self.frame3, text="结构元", font=("宋体", 18))
|
|
|
|
|
lab.place(x=10, y=100, anchor="nw")
|
|
|
|
|
en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
en.place(x=100, y=100, anchor="nw")
|
|
|
|
|
en.insert(0, "5 5")
|
|
|
|
|
|
|
|
|
|
framet=tk.Frame(self.frame3)
|
|
|
|
|
options = [
|
|
|
|
|
"交叉",
|
|
|
|
|
"椭圆",
|
|
|
|
|
"矩形"
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# 创建一个变量来存储用户选择的显示文本
|
|
|
|
|
selected_value = tk.StringVar(root)
|
|
|
|
|
selected_value.set(options[0])
|
|
|
|
|
|
|
|
|
|
option_menu = tk.OptionMenu(framet, selected_value, *options, command=on_option_selected)
|
|
|
|
|
option_menu.pack()
|
|
|
|
|
framet.place(x=self.cwidth / 2 - 40, y=200, anchor="nw")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
but = tk.Button(self.frame3, text="运算", font=("宋体", 18),
|
|
|
|
|
command=button)
|
|
|
|
|
but.place(x=self.cwidth / 2 - 40, y=500, anchor="nw")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def close(self):
|
|
|
|
|
selected_real_value = cv2.MORPH_CROSS
|
|
|
|
|
def get_size(entry,size):
|
|
|
|
|
range = entry.get().split(',') # 英文逗号
|
|
|
|
|
if len(range) != 2:
|
|
|
|
|
range = entry.get().split(',') # 中文逗号
|
|
|
|
|
if len(range) != 2:
|
|
|
|
|
range = entry.get().split(' ')
|
|
|
|
|
if len(range) != 2:
|
|
|
|
|
messagebox.showerror("Error", "请输入正确的范围格式,如:x,y")
|
|
|
|
|
return -1, -1
|
|
|
|
|
try:
|
|
|
|
|
x, y = int(range[0]), int(range[1])
|
|
|
|
|
if x<0 or y<0 or x>size[0] or y>size[1]:
|
|
|
|
|
messagebox.showerror("Error", "范围必须在图像内")
|
|
|
|
|
else:
|
|
|
|
|
return x, y
|
|
|
|
|
except ValueError:
|
|
|
|
|
messagebox.showerror("Error", "坐标必须为整数")
|
|
|
|
|
return -1, -1
|
|
|
|
|
def button():
|
|
|
|
|
kernel = cv2.getStructuringElement(selected_real_value, get_size(en,self.src.shape[:2]))
|
|
|
|
|
self.image = cv2.morphologyEx(self.src, cv2.MORPH_CLOSE, kernel)
|
|
|
|
|
self.display_image(self.image, self.frame2)
|
|
|
|
|
def on_option_selected(*args):
|
|
|
|
|
option_value_map = {
|
|
|
|
|
"交叉": cv2.MORPH_CROSS,
|
|
|
|
|
"椭圆": cv2.MORPH_ELLIPSE,
|
|
|
|
|
"矩形": cv2.MORPH_RECT
|
|
|
|
|
}
|
|
|
|
|
nonlocal selected_real_value
|
|
|
|
|
selected_text = selected_value.get()
|
|
|
|
|
selected_real_value = option_value_map[selected_text]
|
|
|
|
|
|
|
|
|
|
if self.src is not None:
|
|
|
|
|
self.clear_frame23()
|
|
|
|
|
|
|
|
|
|
lab = tk.Label(self.frame3, text="结构元", font=("宋体", 18))
|
|
|
|
|
lab.place(x=10, y=100, anchor="nw")
|
|
|
|
|
en = tk.Entry(self.frame3, width=5, font=("宋体", 18))
|
|
|
|
|
en.place(x=100, y=100, anchor="nw")
|
|
|
|
|
en.insert(0, "5 5")
|
|
|
|
|
|
|
|
|
|
framet=tk.Frame(self.frame3)
|
|
|
|
|
options = [
|
|
|
|
|
"交叉",
|
|
|
|
|
"椭圆",
|
|
|
|
|
"矩形"
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# 创建一个变量来存储用户选择的显示文本
|
|
|
|
|
selected_value = tk.StringVar(root)
|
|
|
|
|
selected_value.set(options[0])
|
|
|
|
|
|
|
|
|
|
option_menu = tk.OptionMenu(framet, selected_value, *options, command=on_option_selected)
|
|
|
|
|
option_menu.pack()
|
|
|
|
|
framet.place(x=self.cwidth / 2 - 40, y=200, anchor="nw")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
but = tk.Button(self.frame3, text="运算", font=("宋体", 18),
|
|
|
|
|
command=button)
|
|
|
|
|
but.place(x=self.cwidth / 2 - 40, y=500, anchor="nw")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
messagebox.showerror("Error", "未加载图像")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
root = tk.Tk()
|
|
|
|
|
app = MyApp(root)
|
|
|
|
|
root.mainloop()
|