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.

551 lines
21 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from PIL import Image as Im
from PIL import ImageTk
import tkinter as tk # 导入 Tkinter 库
from tkinter.filedialog import askopenfilename
import tkinter.messagebox
import tkinter.ttk
import tkinter.messagebox
from PIL import ImageDraw
from PIL import ImageFont
from PIL import ImageEnhance
from hig_class import *
from extra import wlw
import numpy as np
import tempfile
import os
class Win(tk.Tk):
def __init__(self):
super().__init__()
self.title('图像处理工具')
self.geometry('1080x720')
self.picture = None # self.picture将作为picture类的实例化对象
self.img = None # self.img将作为窗口类中一直变动的PIL对象图片
self.file_entry = None
self.setupUI()
def setupUI(self):
# 右边菜单栏
right_f = tk.Frame(self, height=720, width=360, bg="#F8F8FF")
right_f.pack(side=tk.RIGHT)
# 各种功能按钮名称及位置
btn1 = tk.Button(right_f, text='打开图像', bg="#BFEFFF", command=self.openToshow)
btn1.place(y=25, x=30, width=300, height=40)
btn2 = tk.Button(right_f, text='截图', bg="#BFEFFF", command=self.window_cut)
btn2.place(y=85, x=30, width=144, height=40)
btn3 = tk.Button(right_f, text='大小', bg="#BFEFFF", command=self.window_size)
btn3.place(y=85, x=186, width=144, height=40)
btn4 = tk.Button(right_f, text='旋转', bg='#B0E2FF', command=self.window_rotate)
btn4.place(y=145, x=30, width=144, height=40)
btn5 = tk.Button(right_f, text='翻转', bg='#B0E2FF', command=self.window_mirror)
btn5.place(y=145, x=186, width=144, height=40)
btn6 = tk.Button(right_f, text='灰度变换', bg='#B0E2FF', command=self.window_word)
btn6.place(y=205, x=30, width=144, height=40)
btn7 = tk.Button(right_f, text='滤镜', bg='#B0E2FF', command=self.window_style)
btn7.place(y=205, x=186, width=144, height=40)
btn8 = tk.Button(right_f, text='显示直方图', bg='#63B8FF', command=self.toshowhist)
btn8.place(y=265, x=30, width=144, height=40)
btn9 = tk.Button(right_f, text='图像相加', bg='#63B8FF', command=self.openToshow2)
btn9.place(y=265, x=186, width=144, height=40)
btn10 = tk.Button(right_f, text='滤波', bg='#63B8FF', command=self.openfilter)
btn10.place(y=325, x=30, width=144, height=40)
btn11 = tk.Button(right_f, text='Sobel锐化', bg='#63B8FF', command=self.opensharpen)
btn11.place(y=325, x=186, width=144, height=40)
# 各种调整名称及位置
lb1 = tk.Label(right_f, text='亮 度:', bg="#F8F8FF")
lb1.place(y=395, x=55, width=60, height=30)
self.inp1 = tk.Entry(right_f)
self.inp1.place(y=395, x=105, width=90, height=30)
lb2 = tk.Label(right_f, text='%', bg="#F8F8FF")
lb2.place(y=395, x=205, width=13, height=30)
b1 = tk.Button(right_f, text='确定', fg='#F8F8FF', width=8, command=self.brightnessPic, bg="#7EC0EE")
b1.place(y=395, x=240)
lb3 = tk.Label(right_f, text='色彩度:', bg="#F8F8FF")
lb3.place(y=440, x=55, width=60, height=30)
self.inp2 = tk.Entry(right_f)
self.inp2.place(y=440, x=105, width=90, height=30)
lb4 = tk.Label(right_f, text='%', bg="#F8F8FF")
lb4.place(y=440, x=205, width=13, height=30)
b2 = tk.Button(right_f, text='确定', fg='#F8F8FF', width=8, command=self.coolorPic, bg="#7EC0EE")
b2.place(y=444, x=240)
lb5 = tk.Label(right_f, text='对比度:', bg="#F8F8FF")
lb5.place(y=485, x=55, width=60, height=30)
self.inp3 = tk.Entry(right_f)
self.inp3.place(y=485, x=105, width=90, height=30)
lb6 = tk.Label(right_f, text='%', bg="#F8F8FF")
lb6.place(y=485, x=205, width=13, height=30)
b3 = tk.Button(right_f, text='确定', fg='#F8F8FF', width=8, command=self.contrastPic, bg="#7EC0EE")
b3.place(y=489, x=240)
lb7 = tk.Label(right_f, text='锐 度:', bg="#F8F8FF")
lb7.place(y=530, x=55, width=60, height=30)
self.inp4 = tk.Entry(right_f)
self.inp4.place(y=530, x=105, width=90, height=30)
lb8 = tk.Label(right_f, text='%', bg="#F8F8FF")
lb8.place(y=530, x=205, width=13, height=30)
b4 = tk.Button(right_f, text='确定', fg='#F8F8FF', width=8, command=self.sharpnessPic, bg="#7EC0EE")
b4.place(y=534, x=240)
# 底部恢复、保存、对比、人脸识别
btn18 = tk.Button(right_f, text='保存图像', fg='#F8F8FF', command=self.save_pic, bg="#1E90FF")
btn18.place(y=590, x=200, width=100, height=30)
btn19 = tk.Button(right_f, text='恢复图像', fg='#F8F8FF', command=self.replay, bg="#1E90FF")
btn19.place(y=590, x=30)
btn20 = tk.Button(right_f, text='对比图像', fg='#F8F8FF', command=self.compare, bg="#1E90FF")
btn20.place(y=590, x=120)
btn21 = tk.Button(right_f, text='人脸识别', fg='#F8F8FF', command=self.facedetec, bg="#1874CD")
btn21.place(y=640, x=30)
# 右侧图像显示栏
right_f = tk.Frame(self, height=720, width=720)
right_f.pack(side=tk.RIGHT)
self.image_l = tk.Label(right_f, relief='ridge')
self.image_l.place(x=0, y=0, width=720, height=720)
def openfilter(self):
filter_win = tk.Toplevel()
filter_win.title('滤波选择')
filter_win.geometry('150x150')
b1 = tk.Button(filter_win, text='均值滤波', command=self.filter1)
b1.place(y=30, x=35, width=75)
b2 = tk.Button(filter_win, text='中值滤波', command=self.filter2)
b2.place(y=60, x=35, width=75)
b3 = tk.Button(filter_win, text='完成', command=filter_win.destroy)
b3.place(y=110, x=80, width=40)
def opensharpen(self):
sharpen_pic = self.img
sharpen_pic = wlw.sharpen(sharpen_pic)
self.show_img(sharpen_pic)
# 打开图片时使用,传值(图)给展示函数
def openToshow(self):
address = self.getAddress()
self.open_picToimg = self.picture.open_pic(address)
self.firstPic(self.open_picToimg)
self.show_img(self.open_picToimg)
# 打开图片时使用,传值(图)给展示函数
def openToshow2(self):
address2 = self.getAddress2()
self.open_picToimg2 = self.picture.open_pic(address2)
self.firstPic2(self.open_picToimg2)
self.show_img2(self.open_picToimg2)
def filter1(self):
img_show = wlw.filter1(self.img)
self.image_l.config(image=img_show)
self.image_l.image = img_show
return self.img
def filter2(self):
img_show = wlw.filter2(self.img)
self.image_l.config(image=img_show)
self.image_l.image = img_show
return self.img
# 打开图片时使用,获得地址
def getAddress(self):
path = tk.StringVar()
self.file_entry = tk.Entry(self, state='readonly', text=path)
path_ = askopenfilename()
path.set(path_)
self.picture = picture()
return self.file_entry.get()
# 打开图片时使用,获得地址
def getAddress2(self):
path2 = tk.StringVar()
file_entry2 = tk.Entry(self, state='readonly', text=path2)
path_2 = askopenfilename()
path2.set(path_2)
self.picture2 = picture()
return file_entry2.get()
# 展示函数
def show_img(self, n_img):
self.img = n_img # self.img PIL对象方便传值给picture类以及本类中其他需要使用PIL图像的地方
img_show = ImageTk.PhotoImage(self.img)
self.image_l.config(image=img_show)
self.image_l.image = img_show
return self.img
def show_img2(self, n_img):
self.img2 = n_img # self.img PIL对象方便传值给picture类以及本类中其他需要使用PIL图像的地方
img_show2 = self.img2
img_show2 = wlw.Add(img_show2, self.Fpic)
self.image_l.config(image=img_show2)
self.image_l.image = img_show2
return self.img2
# 保存函数
def save_pic(self):
fname = tkinter.filedialog.asksaveasfilename(title='保存文件', filetypes=[("PNG", ".png")])
self.img.save(str(fname)) # PIL保存
# 打开图像调用
def open_pic(self, address):
self.pic_get = Im.open(address).convert('RGBA')
wid, hei = self.pic_get.size
if wid > 600 or hei > 400:
if tk.messagebox.askokcancel('提示', '图片可能过大,是否压缩?'):
needShow_pic = self.openResize()
return needShow_pic
return self.pic_get
else:
return self.pic_get
# 原图储存
def firstPic(self, pic):
self.Fpic = pic
return self.Fpic
# 原图储存
def firstPic2(self, pic):
self.Fpic2 = pic
return self.Fpic2
# 打开图像时的图像压缩展示
def openResize(self):
w, h = self.pic_get.size
w_hope = 500
h_hope = 300
f1 = 1.0 * w_hope / w
f2 = 1.0 * h_hope / h
factor = min([f1, f2])
width = int(w * factor)
height = int(h * factor)
pic_show = self.pic_get.resize((width, height))
return pic_show
# 截图操作页面
def window_cut(self):
Cut_win = tk.Toplevel()
Cut_win.title('截图操作')
Cut_win.geometry('220x380')
nowPic = self.img
if self.img == None:
lNone = tk.Label(Cut_win, text='请先打开一张图片')
lNone.place(y=55, x=50)
else:
wNow, hNow = nowPic.size
l1 = tk.Label(Cut_win, text="此时图片尺寸:")
l1.place(y=30, x=25)
l2 = tk.Label(Cut_win, text=wNow)
l2.place(y=55, x=25)
l3 = tk.Label(Cut_win, text="X")
l3.place(y=55, x=65)
l4 = tk.Label(Cut_win, text=hNow)
l4.place(y=55, x=85)
l5 = tk.Label(Cut_win, text="截图区域")
l5.place(y=85, x=25)
l6 = tk.Label(Cut_win, text="起始点左上为00")
l6.place(y=115, x=25)
l7 = tk.Label(Cut_win, text="x")
l7.place(y=145, x=25)
self.e1 = tk.Entry(Cut_win, width=10)
self.e1.place(y=145, x=55)
l8 = tk.Label(Cut_win, text="y")
l8.place(y=180, x=25)
self.e2 = tk.Entry(Cut_win, width=10)
self.e2.place(y=180, x=55)
l9 = tk.Label(Cut_win, text="终止点:")
l9.place(y=220, x=25)
l10 = tk.Label(Cut_win, text="x")
l10.place(y=250, x=25)
self.e3 = tk.Entry(Cut_win, width=10)
self.e3.place(y=250, x=55)
l11 = tk.Label(Cut_win, text="y")
l11.place(y=285, x=25)
self.e4 = tk.Entry(Cut_win, width=10)
self.e4.place(y=285, x=55)
b1 = tk.Button(Cut_win, text='确定', command=self.getCutpart)
b1.place(y=320, x=80, width=40)
b2 = tk.Button(Cut_win, text='完成', command=Cut_win.destroy)
b2.place(y=350, x=150, width=40)
# 大小尺寸操作窗口
def window_size(self):
Size_win = tk.Toplevel()
Size_win.title('尺寸操作')
Size_win.geometry('200x180')
l1 = tk.Label(Size_win, text="宽:")
l1.place(y=30, x=25)
self.text1 = tk.Entry(Size_win, width=10)
self.text1.place(y=25, x=50)
l1_1 = tk.Label(Size_win, text="px")
l1_1.place(y=28, x=150)
l2 = tk.Label(Size_win, text="高:")
l2.place(y=60, x=25)
self.text2 = tk.Entry(Size_win, width=10)
self.text2.place(y=55, x=50)
l2_1 = tk.Label(Size_win, text="px")
l2_1.place(y=58, x=150)
b1 = tk.Button(Size_win, text='确定', command=self.getSize_change)
b1.place(y=100, x=80, width=40)
b2 = tk.Button(Size_win, text='完成', command=Size_win.destroy)
b2.place(y=145, x=140, width=40)
# 接收截图区域,传送展示
def getCutpart(self):
nCut_pic = self.img
x = int(self.e1.get())
y = int(self.e2.get())
xl = int(self.e3.get())
yl = int(self.e4.get())
self.picture = picture()
showCut_pic = self.picture.Cutpic(nCut_pic, x, y, xl, yl)
self.show_img(showCut_pic)
# 获得输入尺寸
def getSize_change(self):
sizeNum_w = int(self.text1.get())
sizeNum_h = int(self.text2.get())
# print('1')
self.showSize_change(sizeNum_w, sizeNum_h)
# print(sizeNum_w, sizeNum_h)
# 尺寸修改并展示图片
def showSize_change(self, renewSize_w, renewSize_h):
# print('2')
self.picture = picture()
needResize_pic = self.img
show_resizePic = self.picture.changeResize(needResize_pic, renewSize_w, renewSize_h)
self.show_img(show_resizePic)
# 灰度转换功能窗口
def window_word(self):
Word_win = tk.Toplevel()
Word_win.title('灰度变化')
Word_win.geometry('300x400')
l1 = tk.Label(Word_win, text='请选择灰度转换方法:')
l1.place(y=10, x=20, width=130)
l0 = tk.Label(Word_win, text="nn值")
l0.place(y=40, x=20)
self.i0 = tk.Entry(Word_win, width=13) # 输入参数n
self.i0.place(y=40, x=100)
bt1 = tk.Button(Word_win, text='n值化', command=self.getn)
bt1.place(y=70, x=20, width=80)
l2 = tk.Label(Word_win, text="k对比度")
l2.place(y=110, x=20)
self.i1 = tk.Entry(Word_win, width=13) # 输入线性化参数k
self.i1.place(y=110, x=100)
l3 = tk.Label(Word_win, text="b亮度")
l3.place(y=130, x=20)
self.i2 = tk.Entry(Word_win, width=13) # 输入线性化参数b
self.i2.place(y=130, x=100)
bt2 = tk.Button(Word_win, text='线性化', command=self.getkb)
bt2.place(y=160, x=20, width=80)
l3 = tk.Label(Word_win, text="c尺度比较常数")
l3.place(y=200, x=20)
self.i3 = tk.Entry(Word_win, width=13) # 输入参数c
self.i3.place(y=200, x=140)
bt3 = tk.Button(Word_win, text='非线性化(对数转换)', command=self.getc)
bt3.place(y=230, x=20, width=120)
b7 = tk.Button(Word_win, text='完成', command=Word_win.destroy)
b7.place(y=300, x=210)
# 获得输入的n值转换值
def getn(self):
npic = self.img
n = float(self.i0.get())
# 图像线性化获取展示
npic = wlw.tonpic(npic, n)
self.show_img(npic)
# 获得输入的线性转换值
def getkb(self):
linearpic = self.img
k = float(self.i1.get())
b = float(self.i2.get())
# 图像线性化获取展示
linearpic = wlw.linearization(linearpic, k, b)
self.show_img(linearpic)
# 获得输入的对数转换值
def getc(self):
logpic = self.img
c = float(self.i3.get())
# 图像对数化获取展示
logpic = wlw.tologpic(logpic, c)
self.show_img(logpic)
# 图像旋转操作窗口
def window_rotate(self):
Rot_win = tk.Toplevel()
Rot_win.title('旋转')
Rot_win.geometry('225x220')
l1 = tk.Label(Rot_win, text="角度:")
l1.place(y=20, x=10)
self.inpt = tk.Entry(Rot_win, width=13)
self.inpt.place(y=15, x=50)
b0 = tk.Button(Rot_win, text='确定', command=lambda: self.getDegree('1'))
b0.place(y=55, x=160, width=40)
b1 = tk.Button(Rot_win, text='+90', command=lambda: self.getDegree('2'))
b1.place(y=85, x=60, width=95)
b2 = tk.Button(Rot_win, text='-90', command=lambda: self.getDegree('3'))
b2.place(y=115, x=60, width=95)
b3 = tk.Button(Rot_win, text='180', command=lambda: self.getDegree('4'))
b3.place(y=145, x=60, width=95)
b4 = tk.Button(Rot_win, text='完成', command=Rot_win.destroy)
b4.place(y=180, x=160, width=40)
# 旋转角度获取
def getDegree(self, n):
self.picture = picture()
needRotate_pic = self.img
# print('99')
# print(n)
if n == '1':
shouldDegree = float(self.inpt.get())
# print('36')
# print(shouldDegree)
showRotate_pic = self.picture.rotatePic(needRotate_pic, shouldDegree)
elif n == '2':
# print('34')
showRotate_pic = self.picture.rotatePic(needRotate_pic, +90)
elif n == '3':
showRotate_pic = self.picture.rotatePic(needRotate_pic, -90)
elif n == '4':
showRotate_pic = self.picture.rotatePic(needRotate_pic, 180)
else:
return 0
self.show_img(showRotate_pic)
# 滤镜选择窗口
def window_style(self):
Sty_win = tk.Toplevel()
Sty_win.title('滤镜选择')
Sty_win.geometry('230x180')
bt1 = tk.Button(Sty_win, text='图像模糊', command=self.sty_1)
bt1.place(y=25, x=25, width=80)
bt2 = tk.Button(Sty_win, text='轮廓滤波', command=self.sty_2)
bt2.place(y=25, x=115, width=80)
bt3 = tk.Button(Sty_win, text='高斯模糊', command=self.sty_3)
bt3.place(y=65, x=25, width=80)
bt4 = tk.Button(Sty_win, text='浮雕滤镜', command=self.sty_4)
bt4.place(y=65, x=115, width=80)
bt6 = tk.Button(Sty_win, text='完成', command=Sty_win.destroy)
bt6.place(y=140, x=160)
# 图像模糊获取展示
def sty_1(self):
sty_1_pic = self.img
relSty_1 = wlw.blurPic(sty_1_pic)
self.show_img(relSty_1)
# 边界增强获取展示
def sty_2(self):
sty_2_pic = self.img
reSty_2 = wlw.edge(sty_2_pic)
self.show_img(reSty_2)
# 高斯模糊获取展示
def sty_3(self):
sty_3_pic = self.img
reSty_3 = wlw.gaussianBlur(sty_3_pic)
self.show_img(reSty_3)
# 浮雕滤镜获取展示
def sty_4(self):
sty_4_pic = self.img
reSty_4 = wlw.emboss(sty_4_pic)
self.show_img(reSty_4)
# 亮度调整
def brightnessPic(self):
self.picture = picture()
needBright_pic = self.img
b_num = float(self.inp1.get())
briNum = b_num / 100
showBright_pic = self.picture.brightPic(needBright_pic, briNum)
self.show_img(showBright_pic)
# 色彩度调整
def coolorPic(self):
self.picture = picture()
needColor_pic = self.img
co_num = float(self.inp2.get())
colNum = co_num / 100
showColor_pic = self.picture.colornPic(needColor_pic, colNum)
self.show_img(showColor_pic)
# 对比度调整
def contrastPic(self):
self.picture = picture()
needCon_pic = self.img
c_num = float(self.inp3.get())
ConNum = c_num / 100
showContrast_pic = self.picture.constractPic(needCon_pic, ConNum)
self.show_img(showContrast_pic)
# 锐度调整
def sharpnessPic(self):
self.picture = picture()
needSharp_pic = self.img
s_num = float(self.inp4.get())
ShNum = s_num / 100
showSharp_pic = self.picture.constractPic(needSharp_pic, ShNum)
self.show_img(showSharp_pic)
# 镜像操作窗口
def window_mirror(self):
Mir_win = tk.Toplevel()
Mir_win.title('镜像操作')
Mir_win.geometry('150x150')
b1 = tk.Button(Mir_win, text='左右', command=self.MirrorImg_lr)
b1.place(y=30, x=35, width=75)
b2 = tk.Button(Mir_win, text='上下', command=self.MirrorImg_tb)
b2.place(y=60, x=35, width=75)
b3 = tk.Button(Mir_win, text='完成', command=Mir_win.destroy)
b3.place(y=110, x=80, width=40)
# 镜像左右调用展示
def MirrorImg_lr(self):
self.picture = picture()
Mirror_img_lr = self.img
MittotImg_lrFinish = self.picture.MirrorPic_leftOrright(Mirror_img_lr)
self.show_img(MittotImg_lrFinish)
# 镜像上下调用展示
def MirrorImg_tb(self):
self.picture = picture()
Mirror_img_tb = self.img
MittotImg_tbFinish = self.picture.MirrorPic_topOrbuttom(Mirror_img_tb)
self.show_img(MittotImg_tbFinish)
# 恢复图像
def replay(self):
self.show_img(self.Fpic)
# 对比图像
def compare(self):
Im._show(self.Fpic)
def toshowhist(self):
# gethist = wlw.showhist(self.img)
# self.show_img(gethist)
wlw.showhist(self.img)
#人脸识别
def facedetec(self):
minc=self.img
path=self.file_entry.get()
minc = wlw.face_detect(minc, path)
self.show_img(minc)
print("图片路径:", path)
if __name__ == '__main__':
root = Win()
# 窗体主循环
root.mainloop()