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.

1003 lines
36 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
from PIL import ImageTk
from PIL import ImageFilter
from PIL import ImageEnhance
import tkinter as tk # Tkinter: python内置GUI
from tkinter.filedialog import askopenfilename
import tkinter.ttk
import tkinter.messagebox
from tkinter import simpledialog
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchvision.transforms as transforms
import torchvision.models as models
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
import collections
#import os
#os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
class picture(object):
"""description of class"""
# 打开图像调用
def open_pic(self, address):
self.pic_get = Image.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 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 Cutpic(self, pic_preCut, p1, p2, p3, p4):
cropped_pic = pic_preCut.crop((p1, p2, p3, p4))#截图
return cropped_pic
# 尺寸大小变化
def changeResize(self, pic_reshow, newWidth, newHeight):
reesizeNew_pic = pic_reshow.resize((newWidth, newHeight))#修改尺寸
# print('3')
return reesizeNew_pic
# 镜像左右
def MirrorPic_leftOrright(self, pic_mir_lr):
Mirror_lrFinish = pic_mir_lr.transpose(Image.Transpose.FLIP_LEFT_RIGHT)# 镜像左右
return Mirror_lrFinish
# 镜像上下
def MirrorPic_topOrbuttom(self, pic_mir_tp):
Mirror_tbFinish = pic_mir_tp.transpose(Image.Transpose.FLIP_LEFT_RIGHT)# 镜像上下
return Mirror_tbFinish
# 旋转
def rotatePic(self, pic_prerotate, rodegreee):
rotateNew_pic = pic_prerotate.rotate(rodegreee, expand=True)
return rotateNew_pic
# 亮度
def brightPic(self, pic_prebright, n):
pic_brighted = ImageEnhance.Brightness(pic_prebright).enhance(n)# 亮度
return pic_brighted
# 色彩度
def colornPic(self, pic_preColor, n):
pic_colored = ImageEnhance.Color(pic_preColor).enhance(n)# 色彩度
return pic_colored
# 对比度
def constractPic(self, pic_preCon, n):
enh_con = ImageEnhance.Contrast(pic_preCon)
contrast = n
pic_contrasted = enh_con.enhance(contrast)# 对比度
return pic_contrasted
# 锐度调整
def sharpPic(self, pic_preSharp, n):
pic_sharped = ImageEnhance.Sharpness(pic_preSharp).enhance(n)
return pic_sharped
class modules(object):
def forward(self, img):
# normalize img
return (img - self.mean) / self.std
"""description of class"""
# 加了滤镜的拓展功能用的ImageFilter库
def blurPic(Imf):
Im2 = Imf.filter(ImageFilter.BLUR) # 图像模糊
return Im2
def edge(Imf):
Im4 = Imf.filter(ImageFilter.EDGE_ENHANCE) # 边界增强
return Im4
def gaussianBlur(Imf):
Im6 = Imf.filter(ImageFilter.GaussianBlur) # 高斯模糊
return Im6
def emboss(Imf):
Im8 = Imf.filter(ImageFilter.EMBOSS) # 浮雕滤镜,
return Im8
# 线性灰度转换
def linearization(Imf, a, c):
Im12=np.array(Imf)
r,g,b = Im12[:,:,0], Im12[:,:,1], Im12[:,:,2]
Im12 = 0.2989*r + 0.5870*g + 0.1140*b
Im12=float(a)*Im12+float(c) # 对矩阵类型计算,a是对比度c是亮度由k和b传入
# 进行数据截断大于255的值要截断为255
Im12[Im12>255]=255
# 数据类型转化
Im12=np.round(Im12)
Im12=Im12.astype(np.uint8)
return Image.fromarray(Im12)
# 非线性log灰度转换
def tologpic(Imf, c):
Im14=np.array(Imf)
r,g,b = Im14[:,:,0], Im14[:,:,1], Im14[:,:,2]
Im14 = 0.2989*r + 0.5870*g + 0.1140*b
Im14 = c * np.log(1.0 + Im14) # 对数运算
Im14[Im14>255]=255 #
Im14 = np.uint8(Im14 + 0.5)
return Image.fromarray(Im14)
# n值灰度转换
def tonpic(Imf, n):
Im16=np.array(Imf)
r,g,b = Im16[:,:,0], Im16[:,:,1], Im16[:,:,2]
Im16 = 0.2989*r + 0.5870*g + 0.1140*b
Im16=float(n)*Im16
Im16[Im16>255]=255
# 数据类型转化
Im16=np.round(Im16)
Im16=Im16.astype(np.uint8)
return Image.fromarray(Im16)
def calc_hist(gray):
# 计算彩色图单通道的直方图
hist_new = []
num = []
hist_result = []
hist_key = []
gray1 = list(gray.ravel()) # 将读取出来的数组转化为一维列表方便循环遍历
obj = dict(collections.Counter(gray1)) # 计算每个灰度级出现的次数
obj = sorted(obj.items(),key=lambda item:item[0])
# 初始化hist数组
for each in obj:
hist1 = []
key = list(each)[0]
cnt = list(each)[1]
hist_key.append(key)
hist1.append(cnt)
hist_new.append(hist1)
# 检查从0-255每个通道是否都有个数没有的话添加并将值设为0
for i in range (0, 256):
if i in hist_key:
num = hist_key.index(i)
hist_result.append(hist_new[num])
else:
hist_result.append([0])
hist_result = np.array(hist_result)
return hist_result
# 计算直方图
def showhist(image):
image= np.array(image)
r,g,b = image[:,:,0], image[:,:,1], image[:,:,2]
hist_new_b = modules.calc_hist(b)
hist_new_g = modules.calc_hist(g)
hist_new_r = modules.calc_hist(r)
# 绘制直方图
plt.plot(hist_new_b, color='b')
plt.plot(hist_new_g, color='g')
plt.plot(hist_new_r, color='r')
plt.show()
# 图像相加函数
def IMG_PLUS(img1, img2):
# 先修改img1尺寸和img2相同
img1 = cv.resize(img1, (img2.shape[1], img2.shape[0]))
# 矩阵相加
newimg = img1*0.5 + img2*0.5
newimg = newimg.astype(np.uint8)
return newimg
# 图像相加
def Add(img1, img2):
first = np.array(img1)
second = np.array(img2)
newimg = modules.IMG_PLUS(first, second)
#return ImageTk.PhotoImage(Image.fromarray(newimg))
return Image.fromarray(newimg)
# 均值滤波处理函数
def mean_filter(img, b=3):
padnum = (b-1)//2# 填充数量
pad = ((padnum, padnum), (padnum, padnum), (0,0))# 填充格式
Filter = np.ones((b, b, img.shape[2]), img.dtype)# 方阵滤波器
padnumImg= np.pad(img, pad, 'constant', constant_values=(0, 0))
# 用滤波器对图像中像素依次计算取均值
for i in range(padnum, padnumImg.shape[0] - padnum):
for j in range(padnum, padnumImg.shape[1] - padnum):
padnumImg[i][j] = (Filter * padnumImg[i-padnum:i+padnum+1, j-padnum:j+padnum+1]).sum(axis = 0).sum(axis = 0)//(b ** 2)
newimg = padnumImg[padnum:padnumImg.shape[0] - padnum, padnum:padnumImg.shape[1] - padnum] # 剪切使尺寸一样
return newimg
# 中值滤波处理函数
def median_filter(img, b=3):
padnum = (b-1)//2# 填充数量
pad = ((padnum, padnum), (padnum, padnum), (0,0))# 填充格式
padImg= np.pad(img, pad, 'constant', constant_values=(0, 0))# 方阵滤波器
# 按通道计算中值函数
def DimensionAdd(img):
blank = np.zeros((img.shape[2]))
for i in range(img.shape[2]):
blank[i] = np.median(img[:,:,i])
return blank
# 用滤波器对图像中像素依次计算中值
for i in range(padnum, padImg.shape[0] - padnum):
for j in range(padnum, padImg.shape[1] - padnum):
padImg[i][j] = DimensionAdd(padImg[i-padnum:i+padnum+1, j-padnum:j+padnum+1])
newimg = padImg[padnum:padImg.shape[0] - padnum, padnum:padImg.shape[1] - padnum] # 把操作完多余的0去除保证尺寸一样大
return newimg
# 均值滤波
def filter1(img):
l = simpledialog.askinteger(title='滤波核size', prompt='边长L', initialvalue=3, minvalue=0, maxvalue=99)
img = modules.mean_filter(np.array(img), l)
return ImageTk.PhotoImage(Image.fromarray(img))
# 中值滤波
def filter2(img):
l = simpledialog.askinteger(title='滤波核size', prompt='边长L', initialvalue=3, minvalue=0, maxvalue=99)
img = modules.median_filter(np.array(img), l)
return ImageTk.PhotoImage(Image.fromarray(img))
# sobel锐化
def sharpen(img):
img = np.array(img)
r,g,b = img[:,:,0], img[:,:,1], img[:,:,2]
img = 0.2989*r + 0.5870*g + 0.1140*b
# sobel算子
G_x = np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]])
G_y = np.array([[-1, -2, -1],[0, 0, 0],[1, 2, 1]])
rows = np.size(img, 0)
columns = np.size(img, 1)
mag = np.zeros(img.shape)
# 分别检测水平和垂直在计算每个pixel的时候将水平和垂直的值作一次平方和的处理
for i in range(0, rows - 2):
for j in range(0, columns - 2):
v = sum(sum(G_x * img[i:i+3, j:j+3])) # vertical
h = sum(sum(G_y * img[i:i+3, j:j+3])) # horizon
mag[i+1, j+1] = np.sqrt((v ** 2) + (h ** 2))
# 设置阈值
threshold=120
mag[mag<threshold] = 0
mag = mag.astype(np.uint8)
return Image.fromarray(mag)
def style_transfer(content_img, style_img, steps):
result = solver.run(content_img, style_img, steps)
return result
# ---风格转换相关---
# 内容损失
class ContentLoss(nn.Module):
def __init__(self, target,):
super(ContentLoss, self).__init__()
# 将目标内容从用于动态计算梯度的树中“分离”出来
self.target = target.detach()
def forward(self, input):
self.loss = F.mse_loss(input, self.target)
return input
def gram_matrix(input):
a, b, c, d = input.size()
# a:=batch size(=1)
# b:=number of feature maps
# (c,d):=dimensions of a f. map (N=c*d)
features = input.view(a * b, c * d)
G = torch.mm(features, features.t()) # 计算格拉姆矩阵
# 矩阵标准化
return G.div(a * b * c * d)
# 风格损失
class StyleLoss(nn.Module):
def __init__(self, target_feature):
super(StyleLoss, self).__init__()
self.target = gram_matrix(target_feature).detach()
def forward(self, input):
G = gram_matrix(input)
self.loss = F.mse_loss(G, self.target)
return input
# 创建一个模块来标准化输入的图像使其能被放在nn.Sequential中
class Normalization(nn.Module):
def __init__(self, mean, std):
super(Normalization, self).__init__()
# .view the mean and std to make them [C x 1 x 1] so that they can
# directly work with image Tensor of shape [B x C x H x W].
# B is batch size. C is number of channels. H is height and W is width.
self.mean = mean.clone().detach().view(-1, 1, 1)
self.std = std.clone().detach().view(-1, 1, 1)
def forward(self, img):
# normalize img
return (img - self.mean) / self.std
class solver(object):
content_layers_default = ['conv_4']
style_layers_default = ['conv_1', 'conv_2', 'conv_3', 'conv_4', 'conv_5']
unloader = transforms.ToPILImage() # 转换到PIL格式
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 期望输出图像的大小
imsize = 512
loader = transforms.Compose([
# 缩放图片大小
transforms.Resize(imsize),
# 转换成pytorch tensor形式
transforms.ToTensor()])
def load_image(image_name):
image = solver.loader(image_name).unsqueeze(0)
return image.to(solver.device, torch.float)
# 打印图像
def show_image(tensor, title=None):
image = tensor.cpu().clone() # 复制参数tensor
image = image.squeeze(0) # 削减无用维度
image = solver.unloader(image)
plt.imshow(image)
if title is not None:
plt.title(title)
plt.pause(1)
return image
def get_style_model_and_losses(cnn, normalization_mean, normalization_std,
style_img, content_img,
content_layers=content_layers_default,
style_layers=style_layers_default):
# 标准化模块
normalization = Normalization(normalization_mean, normalization_std).to(solver.device)
content_losses = []
style_losses = []
# 使用的是nn.Sequential, 则建立一个新的nn.Sequential
# 放入模块,会按顺序激活
model = nn.Sequential(normalization)
i = 0 # 每次看到一个conv层就增加
for layer in cnn.children():
if isinstance(layer, nn.Conv2d):
i += 1
name = 'conv_{}'.format(i)
elif isinstance(layer, nn.ReLU):
name = 'relu_{}'.format(i)
layer = nn.ReLU(inplace=False)
elif isinstance(layer, nn.MaxPool2d):
name = 'pool_{}'.format(i)
elif isinstance(layer, nn.BatchNorm2d):
name = 'bn_{}'.format(i)
else:
raise RuntimeError('Unrecognized layer: {}'.format(layer.__class__.__name__))
model.add_module(name, layer)
if name in content_layers:
# 加入内容损失:
target = model(content_img).detach()
content_loss = ContentLoss(target)
model.add_module("content_loss_{}".format(i), content_loss)
content_losses.append(content_loss)
if name in style_layers:
# 加入风格损失:
target_feature = model(style_img).detach()
style_loss = StyleLoss(target_feature)
model.add_module("style_loss_{}".format(i), style_loss)
style_losses.append(style_loss)
for i in range(len(model) - 1, -1, -1):
if isinstance(model[i], ContentLoss) or isinstance(model[i], StyleLoss):
break
model = model[:(i + 1)]
return model, style_losses, content_losses
def get_input_optimizer(input_img):
optimizer = optim.LBFGS([input_img])
return optimizer
def run_style_transfer(cnn, normalization_mean, normalization_std,
content_img, style_img, input_img, num_steps=300,
style_weight=1000000, content_weight=1):
"""Run the style transfer."""
print('Building the style transfer model..')
model, style_losses, content_losses = solver.get_style_model_and_losses(cnn,
normalization_mean, normalization_std, style_img, content_img)
# 优化输入而不是模型参数因此更新所有requires_grad字段
input_img.requires_grad_(True)
model.requires_grad_(False)
optimizer = solver.get_input_optimizer(input_img)
print('Optimizing..')
run = [0]
while run[0] <= num_steps:
def closure():
# 修正更新后的输入图像的值
with torch.no_grad():
input_img.clamp_(0, 1)
optimizer.zero_grad()
model(input_img)
style_score = 0
content_score = 0
for sl in style_losses:
style_score += sl.loss
for cl in content_losses:
content_score += cl.loss
style_score *= style_weight
content_score *= content_weight
loss = style_score + content_score
loss.backward()
run[0] += 1
if run[0] % 50 == 0:
print("run {}:".format(run))
print('Style Loss: {:4f} Content Loss: {:4f}'.format(
style_score.item(), content_score.item()))
print()
return style_score + content_score
optimizer.step(closure)
with torch.no_grad():
input_img.clamp_(0, 1)
return input_img
def run(content_img, style_img, steps):
content_img = solver.load_image(content_img.convert('RGB'))
style_img = solver.load_image(style_img.convert('RGB'))
# 风格图像和内容图像大小要保持一致
assert style_img.size() == content_img.size(), "Error"
#plt.ion()
#plt.figure()
#solver.show_image(style_img, title='Style Image')
#plt.figure()
#solver.show_image(content_img, title='Content Image')
cnn = models.vgg19(weights='VGG19_Weights.DEFAULT').features.to(solver.device).eval()
cnn_normalization_mean = torch.tensor([0.485, 0.456, 0.406]).to(solver.device)
cnn_normalization_std = torch.tensor([0.229, 0.224, 0.225]).to(solver.device)
input_img = content_img.clone()
# input_img = torch.randn(content_img.data.size(), device=device)
output = solver.run_style_transfer(cnn, cnn_normalization_mean, cnn_normalization_std,
content_img, style_img, input_img, steps)
plt.figure()
result = solver.show_image(output, title='Output Image')
# plt.ioff()
# plt.show()
return result
class Win(tk.Tk):
def __init__(self):
super().__init__()
self.title('图像处理期末demo')
self.geometry('1080x720')
self.picture = picture() # self.picture将作为picture类的实例化对象
self.img = None # self.img将作为窗口类中一直变动的PIL对象图片
self.setupUI()
def setupUI(self):
# 右边菜单栏
right_f = tk.Frame(self, height=720, width=360,bg="#FFFFFF")
right_f.pack(side=tk.RIGHT)
# 各种功能按钮名称及位置
btn1 = tk.Button(right_f, text='打开图像',fg='#FFFFFF', bg="#7C3338",command=self.open_picture)
btn1.place(y=25, x=30, width=300, height=40)
btn2 = tk.Button(right_f, text='基本调整', bg="#FFE498", command=self.basic_proc)
btn2.place(y=85, x=30, width=144, height=40)
btn3 = tk.Button(right_f, text='调整大小', bg="#FFE498", command=self.picture_resize)
btn3.place(y=85, x=186, width=144,height=40)
btn4 = tk.Button(right_f, text='旋转操作', bg='#FFE498', command=self.picture_rotate)
btn4.place(y=145, x=30, width=144, height=40)
btn5 = tk.Button(right_f, text='镜像操作', bg='#FFE498',command=self.picture_mirror)
btn5.place(y=145, x=186, width=144, height=40)
btn6 = tk.Button(right_f, text='灰度变换', bg='#FFE498',command=self.picture_gray)
btn6.place(y=205, x=30, width=144, height=40)
btn7 = tk.Button(right_f, text='滤镜', bg='#FFE498',command=self.picture_filters)
btn7.place(y=205, x=186, width=144, height=40)
btn8 = tk.Button(right_f, text='显示直方图', bg='#FFE498',command=self.show_hist)
btn8.place(y=265, x=30, width=144, height=40)
btn9 = tk.Button(right_f, text='图像相加', bg='#FFE498',command=self.add_picture)
btn9.place(y=265, x=186, width=144, height=40)
btn10 = tk.Button(right_f, text='滤波', bg='#FFE498',command=self.filtering)
btn10.place(y=325, x=30, width=144, height=40)
btn11 = tk.Button(right_f, text='Sobel锐化', bg='#FFE498',command=self.sharpening)
btn11.place(y=325, x=186, width=144, height=40)
btn12 = tk.Button(right_f, text='风格转换', bg='#FFE498',command=self.style_transfer)
btn12.place(y=385, x=30, width=144, height=40)
# 底部恢复、保存、对比
btn13 = tk.Button(right_f, text='保存图像',fg='#FFFFFF', command=self.save_pic,bg="#7C3338")
btn13.place(y=590, x=230, width=90, height=30)
btn14 = tk.Button(right_f, text='恢复图像',fg='#FFFFFF', command=self.replay,bg="#7C3338")
btn14.place(y=590, x=30, width=90, height=30)
btn15 = tk.Button(right_f, text='对比图像',fg='#FFFFFF', command=self.compare,bg="#7C3338")
btn15.place(y=590, x=130, width=90, height=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 filtering(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 sharpening(self):
sharpen_pic = self.img
sharpen_pic = modules.sharpen(sharpen_pic)
self.show_img(sharpen_pic)
# 打开图片时使用,传值(图)给展示函数
def open_picture(self):
address = self.getAddress()
self.open_picToimg = self.picture.open_pic(address)
self.firstPic(self.open_picToimg)
self.show_img(self.open_picToimg)
# 打开图片时使用,传值(图)给展示函数
def add_picture(self):
address = self.getAddress()
self.open_picToimg = self.picture.open_pic(address)
self.add_pic(self.open_picToimg)
def filter1(self):
img_show = modules.filter1(self.img)
self.image_l.config(image=img_show)
self.image_l.image = img_show
return self.img
def filter2(self):
img_show = modules.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()
file_entry = tk.Entry(self, state='readonly', text=path)
path_ = askopenfilename()
path.set(path_)
return file_entry.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 add_pic(self, n_img):
img_show = n_img
img_show = modules.Add(img_show, self.img)
self.show_img(img_show)
# 保存函数
def save_pic(self):
fname = tkinter.filedialog.asksaveasfilename(title='保存文件', filetypes=[("PNG", ".png")])
self.img.save(str(fname)) # PIL保存
# 原图储存
def firstPic(self, pic):
self.Fpic = pic
return self.Fpic
# 打开图像时的图像压缩展示
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 basic_proc(self):
Bas_win = tk.Toplevel()
Bas_win.title('基本调整')
Bas_win.geometry('250x250')
l0 = tk.Label(Bas_win, text="%")
l0.place(y=30, x=100)
self.i0 = tk.Entry(Bas_win, width=13)#输入参数n
self.i0.place(y=30, x=20)
bt1 = tk.Button(Bas_win, text='亮度调整', command=self.brightnessPic)
bt1.place(y=25, x=130, width=80)
l1 = tk.Label(Bas_win, text="%")
l1.place(y=65, x=100)
self.i1 = tk.Entry(Bas_win, width=13)#输入参数n
self.i1.place(y=70, x=20)
bt2 = tk.Button(Bas_win, text='色彩度调整', command=self.colorPic)
bt2.place(y=65, x=130, width=80)
l2 = tk.Label(Bas_win, text="%")
l2.place(y=105, x=100)
self.i2 = tk.Entry(Bas_win, width=13)#输入参数n
self.i2.place(y=110, x=20)
bt3 = tk.Button(Bas_win, text='对比度调整', command=self.contrastPic)
bt3.place(y=105, x=130, width=80)
l3 = tk.Label(Bas_win, text="%")
l3.place(y=145, x=100)
self.i3 = tk.Entry(Bas_win, width=13)#输入参数n
self.i3.place(y=150, x=20)
bt4 = tk.Button(Bas_win, text='锐度调整', command=self.sharpnessPic)
bt4.place(y=145, x=130, width=80)
bt6 = tk.Button(Bas_win, text='完成', command=Bas_win.destroy)
bt6.place(y=200, x=100)
# 大小尺寸操作窗口
def picture_resize(self):
Size_win = tk.Toplevel()
Size_win.title('尺寸操作')
Size_win.geometry('300x180')
l1 = tk.Label(Size_win, text="宽:")
l1.place(y=30, x=80)
self.text1 = tk.Entry(Size_win, width=10)
self.text1.place(y=30, x=100)
l1_1 = tk.Label(Size_win, text="px")
l1_1.place(y=30, x=170)
l2 = tk.Label(Size_win, text="高:")
l2.place(y=60, x=80)
self.text2 = tk.Entry(Size_win, width=10)
self.text2.place(y=60, x=100)
l2_1 = tk.Label(Size_win, text="px")
l2_1.place(y=60, x=170)
b1 = tk.Button(Size_win, text='确定', command=self.getSize_change)
b1.place(y=100, x=100, width=40)
b2 = tk.Button(Size_win, text='完成', command=Size_win.destroy)
b2.place(y=145, x=100, width=40)
# 获得输入尺寸
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')
needResize_pic = self.img
show_resizePic = self.picture.changeResize(needResize_pic, renewSize_w, renewSize_h)
self.show_img(show_resizePic)
# 灰度转换功能窗口
def picture_gray(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="n(n值默认1.5):")
l0.place(y=40, x=20)
self.i0 = tk.Entry(Word_win, width=13)#输入参数n
self.i0.place(y=40, x=110)
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(对比度默认1.5):")
l2.place(y=110, x=20)
self.i1 = tk.Entry(Word_win, width=13)#输入线性化参数k
self.i1.place(y=110, x=110)
l3 = tk.Label(Word_win, text="b(亮度默认1.5):")
l3.place(y=130, x=20)
self.i2 = tk.Entry(Word_win, width=13)#输入线性化参数b
self.i2.place(y=130, x=110)
bt2 = tk.Button(Word_win, text='线性化', command=self.getkb)
bt2.place(y=160, x=20, width=80)
l3 = tk.Label(Word_win, text="c(尺度比较常数默认30.0):")
l3.place(y=200, x=20)
self.i3 = tk.Entry(Word_win, width=13)#输入参数c
self.i3.place(y=200, x=150)
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= modules.tonpic(npic,
1.5 if self.i0.get()=="" else float(self.i0.get()))
self.show_img(npic)
# 获得输入的线性转换值
def getkb(self):
linearpic = self.img
#k = float(self.i1.get())
#b = float(self.i2.get())
# 图像线性化获取展示
linearpic= modules.linearization(linearpic,
1.5 if self.i1.get()=="" else float(self.i1.get()),
1.5 if self.i2.get()=="" else float(self.i2.get()))
self.show_img(linearpic)
# 获得输入的对数转换值
def getc(self):
logpic = self.img
#c = float(self.i3.get())
# 图像对数化获取展示
logpic= modules.tologpic(logpic,
30.0 if self.i3.get()=="" else float(self.i3.get()))
self.show_img(logpic)
# 图像旋转操作窗口
def picture_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=15)
self.inpt.place(y=20, x=70)
b0 = tk.Button(Rot_win, text='确定', command=lambda: self.getDegree('1'))
b0.place(y=15, x=170, width=40)
b1 = tk.Button(Rot_win, text='+90', command=lambda: self.getDegree('2'))
b1.place(y=85, x=70, width=95)
b2 = tk.Button(Rot_win, text='-90', command=lambda: self.getDegree('3'))
b2.place(y=115, x=70, width=95)
b3 = tk.Button(Rot_win, text='180', command=lambda: self.getDegree('4'))
b3.place(y=145, x=70, width=95)
b4 = tk.Button(Rot_win, text='完成', command=Rot_win.destroy)
b4.place(y=180, x=100, width=40)
# 旋转角度获取
def getDegree(self, n):
needRotate_pic = self.img
# print('99')
# print(n)
if n == '1':
inputDegree = float(self.inpt.get())
showRotate_pic = self.picture.rotatePic(needRotate_pic, inputDegree)
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 picture_filters(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 = modules.blurPic(sty_1_pic)
self.show_img(relSty_1)
# 边界增强获取展示
def sty_2(self):
sty_2_pic = self.img
reSty_2 = modules.edge(sty_2_pic)
self.show_img(reSty_2)
# 高斯模糊获取展示
def sty_3(self):
sty_3_pic = self.img
reSty_3 = modules.gaussianBlur(sty_3_pic)
self.show_img(reSty_3)
# 浮雕滤镜获取展示
def sty_4(self):
sty_4_pic = self.img
reSty_4 = modules.emboss(sty_4_pic)
self.show_img(reSty_4)
# 亮度调整
def brightnessPic(self):
needBright_pic = self.img
b_num = float(self.i0.get())
briNum = b_num / 100
showBright_pic = self.picture.brightPic(needBright_pic, briNum)
self.show_img(showBright_pic)
# 色彩度调整
def colorPic(self):
needColor_pic = self.img
co_num = float(self.i1.get())
colNum = co_num / 100
showColor_pic = self.picture.colornPic(needColor_pic, colNum)
self.show_img(showColor_pic)
# 对比度调整
def contrastPic(self):
needCon_pic = self.img
c_num = float(self.i2.get())
ConNum = c_num / 100
showContrast_pic = self.picture.constractPic(needCon_pic, ConNum)
self.show_img(showContrast_pic)
# 锐度调整
def sharpnessPic(self):
needSharp_pic = self.img
s_num = float(self.i3.get())
ShNum = s_num / 100
showSharp_pic = self.picture.constractPic(needSharp_pic, ShNum)
self.show_img(showSharp_pic)
def open_style_img_and_run(self):
address = self.getAddress()
self.style_img = self.picture.open_pic(address)
content_img = self.img
self.style_img = self.style_img.resize((content_img.width, content_img.height))
# prompt
Prompt_win = tk.Toplevel()
Prompt_win.title('提示')
Prompt_win.geometry('230x150')
l1 = tk.Label(Prompt_win, text="output image生成中,保持终端打开...")
l1.place(y=30, x=25)
self.update()
result = modules.style_transfer(content_img, self.style_img, int(300 if len(self.inpt.get())==0 else self.inpt.get()))
self.show_img(result)
Prompt_win.destroy()
# 风格转换
def style_transfer(self):
Sty_win = tk.Toplevel()
Sty_win.title('风格转换')
Sty_win.geometry('300x200')
bt1 = tk.Button(Sty_win, text='选择风格图像并运行(主窗口显示图像为内容图像)', command=self.open_style_img_and_run)
bt1.place(y=60, x=25, width=250)
l1 = tk.Label(Sty_win, text="步数(越大越慢,默认300)")
l1.place(y=25, x=25)
self.inpt = tk.Entry(Sty_win, width=10)
self.inpt.place(y=25, x=150)
bt2 = tk.Button(Sty_win, text='完成', command=Sty_win.destroy)
bt2.place(y=150, x=130)
# 镜像操作窗口
def picture_mirror(self):
Mir_win = tk.Toplevel()
Mir_win.title('镜像操作')
Mir_win.geometry('300x150')
b1 = tk.Button(Mir_win, text='左右', command=self.MirrorImg_lr)
b1.place(y=30, x=100, width=75)
b2 = tk.Button(Mir_win, text='上下', command=self.MirrorImg_tb)
b2.place(y=60, x=100, width=75)
b3 = tk.Button(Mir_win, text='完成', command=Mir_win.destroy)
b3.place(y=110, x=100, width=40)
# 镜像左右调用展示
def MirrorImg_lr(self):
Mirror_img_lr = self.img
MittotImg_lrFinish = self.picture.MirrorPic_leftOrright(Mirror_img_lr)
self.show_img(MittotImg_lrFinish)
# 镜像上下调用展示
def MirrorImg_tb(self):
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):
Image._show(self.Fpic)
def show_hist(self):
#gethist = modules.showhist(self.img)
#self.show_img(gethist)
modules.showhist(self.img)
if __name__ == '__main__':
root = Win()
# 窗体主循环
root.mainloop()