from PIL import Image, ImageTk from PIL import ImageFilter 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 import numpy as np import cv2 as cv import matplotlib.pyplot as plt from tkinter import simpledialog import collections import os class wlw(object): """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=1.5, c=1.5): 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=30.0): 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=1.5): 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 # 对矩阵类型计算 # 进行数据截断,大于255的值要截断为255 Im16[Im16 > 255] = 255 # 数据类型转化 Im16 = np.round(Im16) Im16 = Im16.astype(np.uint8) return Image.fromarray(Im16) # 计算直方图 def showhist(image): def clczhifangtu(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] each = list(each)[1] hist_key.append(key) hist1.append(each) 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]) # 检查循环后的列表中是不是已经包含所有的灰度级 if len(hist_result) < 256: for i in range(0, 256 - len(hist_result)): hist_new.append([0]) hist_result = np.array(hist_result) return hist_result image = np.array(image) r, g, b = image[:, :, 0], image[:, :, 1], image[:, :, 2] hist_new_b = clczhifangtu(b) hist_new_g = clczhifangtu(g) hist_new_r = clczhifangtu(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 Add(img1, img2): # 图像相加函数 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 first = np.array(img1) second = np.array(img2) newimg = IMG_PLUS(first, second) return ImageTk.PhotoImage(Image.fromarray(newimg)) # 均值滤波 def filter1(img): def 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 l = simpledialog.askinteger(title='滤波核size', prompt='边长L', initialvalue=3, minvalue=0, maxvalue=99) img = filter(np.array(img), l) return ImageTk.PhotoImage(Image.fromarray(img)) # 中值滤波 def filter2(img): # 中值滤波处理函数 def 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 l = simpledialog.askinteger(title='滤波核size', prompt='边长L', initialvalue=3, minvalue=0, maxvalue=99) img = 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 face_detect(img, path): img = cv.imread(path) name = path.split('.')[0] print(img) if (img.ndim == 3): gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) else: gray = img face_cas = cv.CascadeClassifier('haarcascade_frontalface_default.xml') face_scale = face_cas.detectMultiScale(gray, 1.1, 5, 0, (100, 100), (400, 400)) print(face_scale) for (x, y, w, h) in face_scale: cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1) cv.putText(img, name, (x + 10, y - 10), cv.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 1) return Image.fromarray(img)