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