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.

223 lines
8.8 KiB

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)