Compare commits

..

2 Commits

53
.gitignore vendored

@ -0,0 +1,53 @@
# ---> Eagle
# Ignore list for Eagle, a PCB layout tool
# Backup files
*.s#?
*.b#?
*.l#?
*.b$?
*.s$?
*.l$?
# Eagle project file
# It contains a serial number and references to the file structure
# on your computer.
# comment the following line if you want to have your project file included.
eagle.epf
# Autorouter files
*.pro
*.job
# CAM files
*.$$$
*.cmp
*.ly2
*.l15
*.sol
*.plc
*.stc
*.sts
*.crc
*.crs
*.dri
*.drl
*.gpi
*.pls
*.ger
*.xln
*.drd
*.drd.*
*.s#*
*.b#*
*.info
*.eps
# file locks introduced since 7.x
*.lck

@ -0,0 +1,66 @@
import cv2
import sys
import os
import numpy as np
#仿射变化
def Affinevariation():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
# 图像放缩
src = cv2.resize(src, (256, 256))
# 获取图像shape
rows, cols = src.shape[: 2]
########Begin########
#设置图像仿射变化矩阵
post1 = np.float32([[50, 50], [200, 50], [50, 200]])
post2 = np.float32([[10, 100], [200, 50], [100, 250]])
M = cv2.getAffineTransform(post1, post2)
# 图像仿射变换
result = cv2.warpAffine(src, M, (rows, cols))
img = np.hstack([src, result])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
#图形扩展缩放、平移、旋转
def Graphics_extend_scale_pan_rotate():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
# 图像放缩
img = src
l, w, h = img.shape
# 放大图像至原来的两倍,使用双线性插值法
cv2.resize(img, (0, 0), 2, 2, cv2.INTER_LINEAR)
height, width, channel = img.shape
# 构建移动矩阵,x轴左移 10 个像素y轴下移 30 个
M = np.float32([[1, 0, 10], [0, 1, 30]])
img = cv2.warpAffine(img, M, (width, height))
# 构建矩阵旋转中心坐标为处理后图片长宽的一半旋转角度为45度缩放因子为1
M = cv2.getRotationMatrix2D((width / 2, height / 2), 45, 1)
dst = cv2.warpAffine(img, M, (width, height))
img = np.hstack([src, dst])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def main():
print("1.仿射变化 2.图形扩展缩放、平移、旋转")
myinput = input()
if myinput == '1':
Affinevariation()
elif myinput == '2':
Graphics_extend_scale_pan_rotate()
else:
print("wrong input!")

@ -0,0 +1,121 @@
import os
import cv2
import numpy as np
import sys
def robs():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
# 1. 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. Roberts算子
kernelx = np.array([[-1, 0], [0, 1]], dtype=int)
kernely = np.array([[0, -1], [1, 0]], dtype=int)
# 3. 卷积操作
x = cv2.filter2D(grayImage, cv2.CV_16S, kernelx)
y = cv2.filter2D(grayImage, cv2.CV_16S, kernely)
# 4. 数据格式转换
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Roberts = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
print(src.shape)
#单通道转为三通道
Roberts=cv2.cvtColor(Roberts, cv2.COLOR_GRAY2RGB)
img = np.hstack([src, Roberts])
cv2.imshow("(roberts)resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def sob():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
########## Begin ##########
# 1. 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. 求Sobel 算子
x = cv2.Sobel(grayImage, cv2.CV_16S, 1, 0) # 对x求一阶导
y = cv2.Sobel(grayImage, cv2.CV_16S, 0, 1) # 对y求一阶导
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
########## End ##########
Sobel = cv2.cvtColor(Sobel, cv2.COLOR_GRAY2RGB)
img = np.hstack([src, Sobel])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def lap():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
########## Begin ##########
# 1. 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. 高斯滤波
grayImage= cv2.GaussianBlur(grayImage, (5, 5), 0)
# 3. 拉普拉斯算法
dst = cv2.Laplacian(grayImage, cv2.CV_16S, ksize=3)
# 4. 数据格式转换
Laplacian = cv2.convertScaleAbs(dst)
Laplacian = cv2.cvtColor(Laplacian, cv2.COLOR_GRAY2RGB)
########## End ##########
img = np.hstack([src, Laplacian])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def _log():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
########## Begin ##########
# 1. 灰度转换
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. 边缘扩充处理图像并使用高斯滤波处理该图像
image = cv2.copyMakeBorder(img,2,2,2,2,borderType=cv2.BORDER_REPLICATE)
image = cv2.copyMakeBorder(img,2,2,2,2,borderType=cv2.BORDER_REPLICATE)
image = cv2.GaussianBlur(image,(3,3),0)
# 3. 使用Numpy定义LoG算子
m1=np.array([[0,0,-1,0,0],[0,-1,-2,-1,0],[-1,-2,16,-2,-1],[0,-1,-2,-1,0],[0,0,-1,0,0]])
image1=np.zeros(image.shape,dtype='float')
# 4. 卷积运算
# 为了使卷积对每个像素都进行运算,原图像的边缘像素要对准模板的中心。
# 由于图像边缘扩大了2像素因此要从位置2到行(列)-2
for i in range(2,image.shape[0]-2):
for j in range(2,image.shape[1]-2):
image1[i,j]=np.sum(m1*image[i-2:i+3,j-2:j+3,1])
# 5. 数据格式转换
image1 = cv2.convertScaleAbs(image1)
image1 = cv2.resize(image1, (img.shape[1], img.shape[0]))
img = np.hstack([src, image1])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def main():
print("1.Roberts算子 2.Sobel算子 3.Laplacian算子 4.log边缘算子")
myinput = input()
if myinput == '1':
robs()
elif myinput == '2':
sob()
elif myinput == '3':
lap()
elif myinput == '4':
_log()
else:
print("wrong input!")

@ -0,0 +1,380 @@
import sys
import cv2
import os
import numpy as np
def robs():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
#src = cv2.imread('./zero.jpg')
if ok:
img = src
########## Begin ##########
# 1. 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. Roberts算子
kernelx = np.array([[-1, 0], [0, 1]], dtype=int)
kernely = np.array([[0, -1], [1, 0]], dtype=int)
# 3. 卷积操作
x = cv2.filter2D(grayImage, cv2.CV_16S, kernelx)
y = cv2.filter2D(grayImage, cv2.CV_16S, kernely)
# 4. 数据格式转换
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Roberts = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
########## End ##########
print(src.shape)
#单通道转为三通道
Roberts=cv2.cvtColor(Roberts, cv2.COLOR_GRAY2RGB)
img = np.hstack([src, Roberts])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def sob():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
########## Begin ##########
# 1. 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. 求Sobel 算子
x = cv2.Sobel(grayImage, cv2.CV_16S, 1, 0) # 对x求一阶导
y = cv2.Sobel(grayImage, cv2.CV_16S, 0, 1) # 对y求一阶导
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
########## End ##########
Sobel = cv2.cvtColor(Sobel, cv2.COLOR_GRAY2RGB)
img = np.hstack([src, Sobel])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def pre():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
########## Begin ##########
# 1. 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
kernelx = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]], dtype=int)
kernely = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]], dtype=int)
x = cv2.filter2D(grayImage, cv2.CV_16S, kernelx)
y = cv2.filter2D(grayImage, cv2.CV_16S, kernely)
# 转uint8
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Prewitt = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
Prewitt = cv2.cvtColor(Prewitt, cv2.COLOR_GRAY2RGB)
########## End ##########
img = np.hstack([src, Prewitt])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def lap():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
########## Begin ##########
# 1. 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. 高斯滤波
grayImage= cv2.GaussianBlur(grayImage, (5, 5), 0)
# 3. 拉普拉斯算法
dst = cv2.Laplacian(grayImage, cv2.CV_16S, ksize=3)
# 4. 数据格式转换
Laplacian = cv2.convertScaleAbs(dst)
Laplacian = cv2.cvtColor(Laplacian, cv2.COLOR_GRAY2RGB)
########## End ##########
img = np.hstack([src, Laplacian])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def Blur():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
#source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
result = cv2.blur(img, (3, 3))
img = np.hstack([src, result])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def medianblur():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
result = cv2.medianBlur(img, 5)
img = np.hstack([src, result])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def gauss():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
cap.release()
if ok:
img = src
result = cv2.GaussianBlur(img, (3, 3), 0)
img = np.hstack([src, result])
cv2.imshow("resourse and result", img)
# 等待关闭
cv2.waitKey(0)
def ideal_high_filter(img, D0):
"""
生成一个理想高通滤波器并返回
"""
h, w = img.shape[:2]
filter_img = np.zeros((h, w))
u = np.fix(h / 2)
v = np.fix(w / 2)
for i in range(h):
for j in range(w):
d = np.sqrt((i - u) ** 2 + (j - v) ** 2)
filter_img[i, j] = 0 if d < D0 else 1
return filter_img
def butterworth_high_filter(img, D0, rank):
"""
生成一个Butterworth高通滤波器并返回
"""
h, w = img.shape[:2]
filter_img = np.zeros((h, w))
u = np.fix(h / 2)
v = np.fix(w / 2)
for i in range(h):
for j in range(w):
d = np.sqrt((i - u) ** 2 + (j - v) ** 2)
filter_img[i, j] = 1 / (1 + (D0 / d) ** (2 * rank))
return filter_img
def exp_high_filter(img, D0, rank):
"""
生成一个指数高通滤波器并返回
"""
h, w = img.shape[:2]
filter_img = np.zeros((h, w))
u = np.fix(h / 2)
v = np.fix(w / 2)
for i in range(h):
for j in range(w):
d = np.sqrt((i - u) ** 2 + (j - v) ** 2)
filter_img[i, j] = np.exp((-1) * (D0 / d) ** rank)
return filter_img
def filter_use(img, filter):
"""
将图像img与滤波器filter结合生成对应的滤波图像
"""
# 首先进行傅里叶变换
f = np.fft.fft2(img)
f_center = np.fft.fftshift(f)
# 应用滤波器进行反变换
S = np.multiply(f_center, filter) # 频率相乘——l(u,v)*H(u,v)
f_origin = np.fft.ifftshift(S) # 将低频移动到原来的位置
f_origin = np.fft.ifft2(f_origin) # 使用ifft2进行傅里叶的逆变换
f_origin = np.abs(f_origin) # 设置区间
f_origin = f_origin / np.max(f_origin.all())
return f_origin
def ideal_high():
cap = cv2.VideoCapture(0)
ok, frame = cap.read()
src = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cap.release()
if ok:
img = src
ideal_filter = ideal_high_filter(img, D0=40)
ideal_img = filter_use(img, ideal_filter)
cv2.imshow("resourse", src)
cv2.imshow("result", ideal_img)
# 等待关闭
cv2.waitKey(0)
def butterworth_high():
cap = cv2.VideoCapture(0)
ok, frame = cap.read()
src = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cap.release()
if ok:
img = src
butterworth_filter = butterworth_high_filter(img, D0=40, rank=2)
butterworth_img = filter_use(img, butterworth_filter)
cv2.imshow("resourse", src)
cv2.imshow("result", butterworth_img)
# 等待关闭
cv2.waitKey(0)
def exp_high():
cap = cv2.VideoCapture(0)
ok, frame = cap.read()
src = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cap.release()
if ok:
img = src
exp_filter = exp_high_filter(img, D0=40, rank=2)
exp_img = filter_use(img, exp_filter)
cv2.imshow("resourse", src)
cv2.imshow("result", exp_img)
# 等待关闭
cv2.waitKey(0)
def get_gray():
cap = cv2.VideoCapture(0)
ok, frame = cap.read()
src = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cap.release()
return src
def filter(img, D0, type, filter, N=2):
'''
频域滤波器
Args:
img: 灰度图片
D0: 截止频率
N: butterworth的阶数(默认使用二阶)
type: lp-低通 hp-高通
filter:butterworthidealGaussian即巴特沃斯理想高斯滤波器
Returns:
imgback滤波后的图像
'''
# 离散傅里叶变换
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
# 中心化
dtf_shift = np.fft.fftshift(dft)
rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2) # 计算频谱中心
mask = np.zeros((rows, cols, 2)) # 生成rows行cols列的二维矩阵
for i in range(rows):
for j in range(cols):
D = np.sqrt((i - crow) ** 2 + (j - ccol) ** 2) # 计算D(u,v)
if (filter.lower() == 'butterworth'): # 巴特沃斯滤波器
if (type == 'lp'):
mask[i, j] = 1 / (1 + (D / D0) ** (2 * N))
elif (type == 'hp'):
mask[i, j] = 1 / (1 + (D0 / D) ** (2 * N))
else:
assert ('type error')
elif (filter.lower() == 'ideal'): # 理想滤波器
if (type == 'lp'):
if (D <= D0):
mask[i, j] = 1
elif (type == 'hp'):
if (D > D0):
mask[i, j] = 1
else:
assert ('type error')
elif (filter.lower() == 'gaussian'): # 高斯滤波器
if (type == 'lp'):
mask[i, j] = np.exp(-(D * D) / (2 * D0 * D0))
elif (type == 'hp'):
mask[i, j] = (1 - np.exp(-(D * D) / (2 * D0 * D0)))
else:
assert ('type error')
fshift = dtf_shift * mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1]) # 计算像素梯度的绝对值
img_back = np.abs(img_back)
return img_back
def main():
print("1.空域的锐化 2.空域的平滑 3.频域的锐化 4.频域的平滑")
cin = input()
if cin == '1':
print("选择锐化的方式1.Roberts锐化 2.Sobel锐化 3.Laplacian锐化 4.Prewitt锐化")
myinput = input()
if myinput == '1':
robs()
elif myinput == '2':
sob()
elif myinput == '3':
lap()
elif myinput == '4':
pre()
else:
print("wrong input!")
elif cin == '2':
print("选择要使用的滤波器: 1.均值滤波 2.中值滤波 3.高斯滤波")
myinput = input()
if myinput == '1':
Blur()
elif myinput == '2':
medianblur()
elif myinput == '3':
gauss()
else:
print("Wrong input")
elif cin == '3':
print("选择要使用的滤波器: 1.理想高通滤波 2.巴特沃斯高通滤波 3.指数高通滤波器")
myinput = input()
if myinput == '1':
ideal_high()
elif myinput == '2':
butterworth_high()
elif myinput == '3':
exp_high()
else:
print("Wrong input!")
elif cin == '4':
print("选择要使用的滤波器: 1.理想低通滤波 2.巴特沃斯低通滤波 3.指数低通滤波器")
myinput = input()
if myinput == '1':
src = get_gray()
img = filter(src, 30, type='lp', filter='ideal')
cv2.imshow("resourse", src)
cv2.imshow("result", img)
# 等待关闭
cv2.waitKey(0)
elif myinput == '2':
src = get_gray()
img = filter(src, 30, type='lp', filter='butterworth')
cv2.imshow("resourse", src)
cv2.imshow("result", img)
# 等待关闭
cv2.waitKey(0)
elif myinput == '3':
src = get_gray()
img = filter(src, 30, type='lp', filter='gaussian')
cv2.imshow("resourse", src)
cv2.imshow("result", img)
cv2.waitKey(0)
else:
print("Wrong input!")
else:
print("Wrong input!")

@ -0,0 +1,218 @@
import os
import cv2
import numpy as np
import sys
import json
def inpaint():
cap = cv2.VideoCapture(0)
ok, src = cap.read()
# cap默认拍摄640*480的照片,现在破坏图片
for i in range(200, 300):
src[200, i] = 255
src[200 + 1, i] = 255
src[200 - 1, i] = 255
for i in range(150, 250):
src[i, 250] = 255
src[i, 250 + 1] = 255
src[i, 250 - 1] = 255
cap.release()
if ok:
img = src
height = img.shape[0]
width = img.shape[1]
#选择要修复的区域用paint表示
paint = np.zeros((height, width, 1), np.uint8)
for i in range(200, 300):
paint[200, i] = 255
paint[200 + 1, i] = 255
paint[200 - 1, i] = 255
for i in range(100, 300):
paint[i, 250] = 255
paint[i, 250 + 1] = 255
paint[i, 250 - 1] = 255
result = cv2.inpaint(img, paint, 3, cv2.INPAINT_TELEA)
img = np.hstack([src, result])
cv2.imshow("source and result", img)
# 等待关闭
cv2.waitKey(0)
def singleScaleRetinex(img, sigma):
retinex = np.log10(img) - np.log10(cv2.GaussianBlur(img, (0, 0), sigma))
return retinex
def multiScaleRetinex(img, sigma_list):
retinex = np.zeros_like(img)
for sigma in sigma_list:
retinex += singleScaleRetinex(img, sigma)
retinex = retinex / len(sigma_list)
return retinex
def colorRestoration(img, alpha, beta):
img_sum = np.sum(img, axis=2, keepdims=True)
color_restoration = beta * (np.log10(alpha * img) - np.log10(img_sum))
return color_restoration
def simplestColorBalance(img, low_clip, high_clip):
total = img.shape[0] * img.shape[1]
for i in range(img.shape[2]):
unique, counts = np.unique(img[:, :, i], return_counts=True)
current = 0
for u, c in zip(unique, counts):
if float(current) / total < low_clip:
low_val = u
if float(current) / total < high_clip:
high_val = u
current += c
img[:, :, i] = np.maximum(np.minimum(img[:, :, i], high_val), low_val)
return img
def MSRCR(img, sigma_list, G, b, alpha, beta, low_clip, high_clip):
img = np.float64(img) + 1.0
img_retinex = multiScaleRetinex(img, sigma_list)
img_color = colorRestoration(img, alpha, beta)
img_msrcr = G * (img_retinex * img_color + b)
for i in range(img_msrcr.shape[2]):
img_msrcr[:, :, i] = (img_msrcr[:, :, i] - np.min(img_msrcr[:, :, i])) / \
(np.max(img_msrcr[:, :, i]) - np.min(img_msrcr[:, :, i])) * \
255
img_msrcr = np.uint8(np.minimum(np.maximum(img_msrcr, 0), 255))
img_msrcr = simplestColorBalance(img_msrcr, low_clip, high_clip)
return img_msrcr
def automatedMSRCR(img, sigma_list):
img = np.float64(img) + 1.0
img_retinex = multiScaleRetinex(img, sigma_list)
for i in range(img_retinex.shape[2]):
unique, count = np.unique(np.int32(img_retinex[:, :, i] * 100), return_counts=True)
for u, c in zip(unique, count):
if u == 0:
zero_count = c
break
low_val = unique[0] / 100.0
high_val = unique[-1] / 100.0
for u, c in zip(unique, count):
if u < 0 and c < zero_count * 0.1:
low_val = u / 100.0
if u > 0 and c < zero_count * 0.1:
high_val = u / 100.0
break
img_retinex[:, :, i] = np.maximum(np.minimum(img_retinex[:, :, i], high_val), low_val)
img_retinex[:, :, i] = (img_retinex[:, :, i] - np.min(img_retinex[:, :, i])) / \
(np.max(img_retinex[:, :, i]) - np.min(img_retinex[:, :, i])) \
* 255
img_retinex = np.uint8(img_retinex)
return img_retinex
def MSRCP(img, sigma_list, low_clip, high_clip):
img = np.float64(img) + 1.0
intensity = np.sum(img, axis=2) / img.shape[2]
retinex = multiScaleRetinex(intensity, sigma_list)
intensity = np.expand_dims(intensity, 2)
retinex = np.expand_dims(retinex, 2)
intensity1 = simplestColorBalance(retinex, low_clip, high_clip)
intensity1 = (intensity1 - np.min(intensity1)) / \
(np.max(intensity1) - np.min(intensity1)) * \
255.0 + 1.0
img_msrcp = np.zeros_like(img)
for y in range(img_msrcp.shape[0]):
for x in range(img_msrcp.shape[1]):
B = np.max(img[y, x])
A = np.minimum(256.0 / B, intensity1[y, x, 0] / intensity[y, x, 0])
img_msrcp[y, x, 0] = A * img[y, x, 0]
img_msrcp[y, x, 1] = A * img[y, x, 1]
img_msrcp[y, x, 2] = A * img[y, x, 2]
img_msrcp = np.uint8(img_msrcp - 1.0)
return img_msrcp
def retinex():
with open('config.json', 'r') as f:
config = json.load(f)
cap = cv2.VideoCapture(0)
ok, src = cap.read()
img = src
cap.release()
if ok:
print("选择类别1..彩色恢复多尺度RetinexMSRCR 2.彩色恢复多尺度RetinexMSRCP 3.彩色恢复多尺度Retinex(AMSRCR)")
print("#Retinex对清晰的图像处理效果不佳适合用来处理光线不好有雾等这些类的图片#")
myinput = input()
if myinput == '1':
img_msrcr = MSRCR(
img,
config['sigma_list'],
config['G'],
config['b'],
config['alpha'],
config['beta'],
config['low_clip'],
config['high_clip']
)
img = np.hstack([src, img_msrcr])
cv2.imshow('resourse and result', img)
cv2.waitKey(0)
elif myinput == '3':
img_amsrcr = automatedMSRCR(
img,
config['sigma_list']
)
img = np.hstack([src, img_amsrcr])
cv2.imshow('resourse and result', img)
cv2.waitKey(0)
elif myinput == '2':
img_msrcp = MSRCP(
img,
config['sigma_list'],
config['low_clip'],
config['high_clip']
)
img = np.hstack([src, img_msrcp])
cv2.imshow('resourse and result', img)
cv2.waitKey(0)
else:
print("Wrong input!")
def main():
print("选择图像修复的算法 1.opencv中inpaint图像修复 2.模仿人类视觉系统的Retinex算法")
myinput = input()
if myinput == '1':
inpaint()
elif myinput == '2':
retinex()
else:
print("Wrong input!")

@ -0,0 +1,72 @@
import os
import sys
import cv2
import numpy as np
import random as rng
def main():
img = cv2.imread('./image-se.jpg')
src = img
img[np.all(img == 255, axis=2)] = 0
kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]], dtype=np.float32)
Laplacian = cv2.filter2D(img, cv2.CV_32F, kernel)
imgres = np.float32(img) - Laplacian
imgres = np.clip(imgres, 0, 255)
imgres = np.uint8(imgres)
bw = cv2.cvtColor(imgres, cv2.COLOR_BGR2GRAY)
_, bw = cv2.threshold(bw, 40, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
dist = cv2.distanceTransform(bw, cv2.DIST_L2, 3)
cv2.normalize(dist, dist, 0, 1.0, cv2.NORM_MINMAX)
_, dist = cv2.threshold(dist, 0.4, 1.0, cv2.THRESH_BINARY)
kernel1 = np.ones((3, 3), dtype=np.uint8)
dist = cv2.dilate(dist, kernel1)
dist_8u = dist.astype('uint8')
contours, _ = cv2.findContours(dist_8u, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
markers = np.zeros(dist.shape, dtype=np.int32)
for i in range(len(contours)):
cv2.drawContours(markers, contours, i, (i + 1), -1)
cv2.circle(markers, (5, 5), 3, (255, 255, 255), -1)
cv2.watershed(imgres, markers)
mark = markers.astype('uint8')
colors = []
for conlour in contours:
colors.append((rng.randint(0, 256), rng.randint(0, 256), rng.randint(0, 256)))
dst = np.zeros((markers.shape[0], markers.shape[1], 3), dtype=np.uint8)
for i in range(markers.shape[0]):
for j in range(markers.shape[1]):
index = markers[i, j]
if index > 0 and index <= len(contours):
dst[i, j, :] = colors[index - 1]
img = np.hstack([src, dst])
cv2.imshow('Final Result', img)
cv2.waitKey(0)

@ -0,0 +1,145 @@
<<<<<<< HEAD
<<<<<<< HEAD
木兰宽松许可证, 第2版
木兰宽松许可证, 第2版
2020年1月 http://license.coscl.org.cn/MulanPSL2
您对“软件”的复制、使用、修改及分发受木兰宽松许可证第2版“本许可证”的如下条款的约束
0. 定义
“软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
“贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
“贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
“法人实体”是指提交贡献的机构及其“关联实体”。
“关联实体”是指对“本许可证”下的行为方而言控制、受控制或与其共同受控制的机构此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
1. 授予版权许可
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
2. 授予专利许可
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
3. 无商标许可
“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可但您为满足第4条规定的声明义务而必须使用除外。
4. 分发限制
您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
5. 免责声明与责任限制
“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
6. 语言
“本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
条款结束
如何将木兰宽松许可证第2版应用到您的软件
如果您希望将木兰宽松许可证第2版应用到您的新软件为了方便接收者查阅建议您完成如下三步
1 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
2 请您在软件包的一级目录下创建以“LICENSE”为名的文件将整个许可证文本放入该文件中
3 请将如下声明文本放入每个源文件的头部注释中。
Copyright (c) [Year] [name of copyright holder]
[Software Name] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
Mulan Permissive Software LicenseVersion 2
Mulan Permissive Software LicenseVersion 2 (Mulan PSL v2)
January 2020 http://license.coscl.org.cn/MulanPSL2
Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
0. Definition
Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
Contribution means the copyrightable work licensed by a particular Contributor under this License.
Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
Legal Entity means the entity making a Contribution and all its Affiliates.
Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, control means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
1. Grant of Copyright License
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
2. Grant of Patent License
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
3. No Trademark License
No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4.
4. Distribution Restriction
You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
5. Disclaimer of Warranty and Limitation of Liability
THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW ITS CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
6. Language
THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
END OF THE TERMS AND CONDITIONS
How to Apply the Mulan Permissive Software LicenseVersion 2 (Mulan PSL v2) to Your Software
To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps:
i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package;
iii Attach the statement to the appropriate annotated syntax at the beginning of each source file.
Copyright (c) [Year] [name of copyright holder]
[Software Name] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
=======
=======
>>>>>>> 49ebf0e483924c9d9622fba7337657b5b18ceaf7
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<<<<<<< HEAD
>>>>>>> 49ebf0e483924c9d9622fba7337657b5b18ceaf7
=======
>>>>>>> 49ebf0e483924c9d9622fba7337657b5b18ceaf7

@ -0,0 +1,143 @@
<<<<<<< HEAD
<<<<<<< HEAD
# 数字图像处理系统项目报告
#### 摘要
这个项目的华东师范大学软件工程学院数字图像处理的期末完整结课项目。由本人单独完成。这个项目主要实现了有以下的六个功能:
1.数字图像基础 2.边缘检测 3.图像增强 4.图像修复 5.图像分割 6.人脸识别
其中前五个功能基于opencv+python所实现的最后一个人脸识别是结合了机器学习的知识使用tensorflow+opencv+python
构建了卷积神经网络模型来实现的多人人脸识别功能。
#### 环境配置
1. python 3.6
2. tensorflow 2.1.0(安装cpu版本)
3. keras 2.3.1
4. scikit-learn 0.20.3
5. opencv-python 任意版本
6. numpy
7. pycharm 2021.3.3
#### 安装教程
不做赘述利用anaconda搭建一个新的虚拟环境来进行以上环境的一个一个的配置
#### 使用说明
执行项目中的main()函数来进行整个项目的运行,根据提示的文字来进行一系列的操作
FaceData为存储人脸数据的文件用来存放数据集
model为存储人脸识别模型的文件用来存放训练完的CNN模型
Wangwenhai 为本人的一段视频数据,用于收集数据
#### 正文
接下来将会对我如何实现的这系列功能做详细的介绍
#### 数字图像基础
图像的仿射变化:
使用cv2.warpAffine()函数,来实现图像的仿射变化。仿射变换可以通
过一系列的原子变换的复合来实现包括:平移(Translation)、缩放(Scale)、翻转(Flip)、
旋转(Rotation)和错切(Shear)这些功能。 至于如何具体实现这些功能则要取决于2*3的
变换矩阵 M的具体内容
图形的扩展缩放、平移、旋转:
这个功能的实现结合的图像的仿射变化其中缩放利用了cv2,resize()函数来实现对图像的缩放,
cv2.warpAffine()实现了图像的平移和利用了 cv2.getRotationMatrix2D()这个函数来构造旋转
是的变换矩阵来用于图像的仿射变化。是仿射变化的拓展和更多的实际应用。本功能实现的是图像的x轴左移
10个像素y轴下移30个。之后进行旋转中心坐标为处理后图片长宽的一半旋转角度为45度缩放因子为1的旋转。
#### 边缘检测
边缘检测目的是找到图像中亮度变化剧烈的像素点构成的集合。由此构建出来的轮廓来更好的实现精准的测量和
定位。图像边缘有两个要素:方向和幅度。沿着边缘走向的像素值变化比较平缓;而沿着垂直于边缘的走向,
像素值则变化得比较大。因此,我们采用一阶和二阶导数来描述和检测边缘。 我实现了以下四个算子:
一阶微分算子Roberts,Sobel算子
二阶微分算子LaplacianLaplacian-gauss算子
#### 图像增强
图像增强可以分为四个模块-空域的锐化,空域的平滑,频域的锐化,频域的平滑下面将分别介绍实现的方式
空域的锐化:锐化的作用一般是用来加强图像的轮廓和边缘,其本质是高通滤波器。锐化的结果是增强了边缘。
但是图像本身的层次和亮度已基本丢失。这里使用的方式与边缘检测雷同。
我使用的一阶微分算子Roberts算子Sobel算子Prewitt算子
二阶微分算子Laplacian算子
空域的平滑:图像平滑的目的是改善图像质量,尽量消除噪声对图像带来的影响,其本质是低通滤波。图像的
空域平滑实现起来很简单,只要将原图中的每一个点的灰度与它周围点的灰度进行加权和平均,作为新图中对
应点的灰度,就能实现滤波的效果。以下我使用了三种滤波器,分别是: 中值滤波器,均值滤波器,高斯滤波器
其中高斯滤波的效果最好,由于引入了加权系数,平滑的效果也是最好的。
频域的锐化:从频谱分析的角度看, 图像都是由决定图像反差的低频信号和决定图像细节的高频信号组
成。但数字化图像中高频信号部分总是掺杂有一定程度的噪声。因此, 在频率域中进行图像的锐
化处理实质上是加强需要的高频分量,并必须考虑到要在锐化图像的同时抑制噪声。频率域中滤波的数学表达式可写为
G(u,v)=H(u,v)⋅F(u,v)
上式中,F(u,v)是原始图像的Fouirer频谱,G(u,v)是锐化后图像的Fouirer频谱,H(u,v)是滤波器的转移函数。
我使用的三种滤波器: 1.理想高通滤波 2.巴特沃斯高通滤波 3.指数高通滤波器
频域的平滑:再频谱分析中,噪声往往有着较丰富的高频分量,此时就需要低通滤波来降噪。我是用了三种滤波器,
1.理想低通滤波 2.巴特沃斯低通滤波 3.指数低通滤波器
总而言之,平滑就是降噪,锐化就是突出边缘
#### 图像修复
图像就是利用那些已经被破坏的区域的边缘,根据这些图像留下的信息去推断被破坏的区域的信息内容,然后对
破坏区进行填补 以达到图像修补的目的。这里我是用了两种方式一种是opencv库中的cv2.inpaint()函数。
第二种则是模仿人类视觉系统的Retinex算法适合对光照条件不好有迷雾的图片做修复。下面是详细介绍
1.inpaint函数 在opencv种有dst = cv2.inpaintsrcmask, inpaintRadiusflags其中
其中src是原图像inpaintMask是掩膜是需要修复的部分inpaintRadius是算法需要考虑的每个点的圆形
邻域的半径flags则是使用的算法INPAINT_NS和INPAINT_TELEA。
2.Retinex算法Retinex理论的基础理论是物体的颜色是由物体对长波红色、中波绿色、 短波(蓝色)
光线的反射能力来决定的,而不是由反射光强度的绝对值来决定的,物体的色彩不受光照非均匀性的影响,具有一致性,
即retinex是以色感一致性颜色恒常性为基础的。下面介绍我实现的四类Retinex算法单尺度Retinex算法
MSR改进成多尺度加权平均的MSR算法彩色恢复多尺度MSRCR算法和色彩增益加权的AutoMSRCR算法。
SSR先将图像进行log变换然后将log图像进行高斯模糊最后利用原图和模糊之后的log图像做差分
MSR原始图像进行三次SSR高斯模糊选择1580200作为高斯模糊sigma参数对三次的SSR结果做平均即为MSR图像
MSRCRautoMSRCR对多尺度MSR结果做了色彩平衡归一化增益和偏差线性加权
#### 图像分割
图像分割的实现使用深度学习的知识会有更好的实现效果,这里我没有使用深度学习。我是使用 OpenCV 函数filter2D
执行一些拉普拉斯滤波以进行图像锐化来突出细节distanceTransform 以获得二值图像的派生(derived)表示,其中
每个像素的值被替换为其到最近背景像素的距离并执行一些图像形态学操作来提取峰值最后使用watershed分水岭算法
将图像中的对象与背景隔离。最终实现了图像的分割。
#### 人脸识别
写在前面人脸识别的数据必须是两个人以上只录入一个人的图像是无法开始训练的。训练的模型保存在model中若不想
使用电脑摄像头来拍摄图像可以修改gain_face中cv2.VideoCapture()的参数来从硬盘中读取数据)
这个部分使用了机器学习的知识利用CNN搭建了一个人脸识别模型只能识别多人单人不行下面介绍详细的流程
1.图片的获取这里我调用了电脑自带的摄像机来获取数据集每个人拍摄100张照片缩短训练时间可以在recognition_face.py
中修改images_num来改变每个人的照片数量。使用haarcascade_frontalface_alt2人脸识别器来捕捉人脸图片保存在Facedata
并且转为灰度图来 提高计算的效率。考虑到灰度图可能需要增强可以在gain_face.py最后面加上增强的代码
2.数据集的构建这里将所有获取的图像的大小都设计为128*128并且使用在Facedata这个文件中人脸数据文件夹的次序作为唯一标签。比
如 Wangwenhai这个文件是目录下的第1个文件那么Wangwenhai里的图像的标签就是1
3.人脸数据的训练我构建了一个18层的CNN模型用来训练数据并且使用了adam来作为模型的优化器由于我构建的是多分类模型。故使用
binary_crossentropy作为损失函数。同时我还定义一个生成器用于数据提升其返回一个生成器对象datagen来强化学习。最后由face_predict
函数来返回预测的结果。
4.人脸识别:利用模型返回的预测值来对摄像头扑捉到的图像做出预测
####总结
通过长达两个星期的学习我对计算机视觉这方面的知识有了更为深刻的理解对opencv的使用更加熟练。而最令我收获最多的是我完成了我的第一
个人脸识别的项目,算是对机器学习有了浅浅的入门。总而言之,这个项目由我单独完成,我从这个课程收获颇多。
=======
# digital_image_processing_final_project
>>>>>>> 49ebf0e483924c9d9622fba7337657b5b18ceaf7
=======
# digital_image_processing_final_project
>>>>>>> 49ebf0e483924c9d9622fba7337657b5b18ceaf7

Binary file not shown.

@ -0,0 +1,13 @@
{
"sigma_list": [
15,
80,
200
],
"G": 5.0,
"b": 25.0,
"alpha": 125.0,
"beta": 46.0,
"low_clip": 0.01,
"high_clip": 0.99
}

@ -0,0 +1,13 @@
import json
control={"sigma_list": [15, 80, 200],
"G" : 5.0,
"b" : 25.0,
"alpha" : 125.0,
"beta" : 46.0,
"low_clip" : 0.01,
"high_clip" : 0.99
}
json.dump(control,open('config.json','w'),indent=4)

@ -0,0 +1,11 @@
import os
def CreateFolder(path):
del_path_space = path.strip()
del_path_tail = del_path_space.rstrip('\\')
is_exists = os.path.exists(del_path_tail)
if not is_exists:
os.makedirs(del_path_tail)
return True
else:
return False

@ -0,0 +1 @@
Subproject commit 49ebf0e483924c9d9622fba7337657b5b18ceaf7

@ -0,0 +1,192 @@
import random
import os
import numpy as np
from sklearn.model_selection import train_test_split
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.optimizers import SGD
from keras.utils import np_utils
from keras.models import load_model
from keras import backend as K
from load_dataset import load_dataset, resize_image
IMAGE_SIZE = 128
class Dataset:
def __init__(self, path_name):
# 训练集
self.train_images = None
self.train_labels = None
# 验证集
self.valid_images = None
self.valid_labels = None
# 测试集
self.test_images = None
self.test_labels = None
# 数据集加载路径
self.path_name = path_name
# 图像种类
self.user_num = len(os.listdir(path_name))
# 当前库采用的维度顺序
self.input_shape = None
# 加载数据集并按照交叉验证的原则划分数据集并进行相关预处理工作
def load(self, img_rows= IMAGE_SIZE, img_cols= IMAGE_SIZE, img_channels=3):
# 数据种类
nb_classes = self.user_num
# 加载数据集到内存
images, labels = load_dataset(self.path_name)
train_images, valid_images, train_labels, valid_labels = train_test_split(images, labels, test_size=0.3,
random_state=random.randint(0, 100))
_, test_images, _, test_labels = train_test_split(images, labels, test_size=0.5,
random_state=random.randint(0, 100))
# 当前的维度顺序如果为'th'则输入图片数据时的顺序为channels,rows,cols否则:rows,cols,channels
# 这部分代码就是根据keras库要求的维度顺序重组训练数据集
if K.image_data_format() == "channels_first":
train_images = train_images.reshape(train_images.shape[0], img_channels, img_rows, img_cols)
valid_images = valid_images.reshape(valid_images.shape[0], img_channels, img_rows, img_cols)
test_images = test_images.reshape(test_images.shape[0], img_channels, img_rows, img_cols)
self.input_shape = (img_channels, img_rows, img_cols)
else:
train_images = train_images.reshape(train_images.shape[0], img_rows, img_cols, img_channels)
valid_images = valid_images.reshape(valid_images.shape[0], img_rows, img_cols, img_channels)
test_images = test_images.reshape(test_images.shape[0], img_rows, img_cols, img_channels)
self.input_shape = (img_rows, img_cols, img_channels)
# 输出训练集、验证集、测试集的数量
print(train_images.shape[0], 'train samples')
print(valid_images.shape[0], 'valid samples')
print(test_images.shape[0], 'test samples')
# 类别标签进行one-hot编码使其向量化在这里我们的类别只有两种经过转化后标签数据变为二维
train_labels = np_utils.to_categorical(train_labels, nb_classes)
valid_labels = np_utils.to_categorical(valid_labels, nb_classes)
test_labels = np_utils.to_categorical(test_labels, nb_classes)
# 像素数据浮点化以便归一化
train_images = train_images.astype('float32')
valid_images = valid_images.astype('float32')
test_images = test_images.astype('float32')
# 将其归一化,图像的各像素值归一化到0~1区间
train_images /= 255
valid_images /= 255
test_images /= 255
#保存
self.train_images = train_images
self.valid_images = valid_images
self.test_images = test_images
self.train_labels = train_labels
self.valid_labels = valid_labels
self.test_labels = test_labels
# CNN网络模型类
class Model:
def __init__(self):
self.model = None
# 建立模型
def build_model(self, dataset, nb_classes):
# 构建一个空的网络模型,它是一个线性堆叠模型,各神经网络层会被顺序添加,专业名称为序贯模型或线性堆叠模型
self.model = Sequential()
# 以下代码将顺序添加CNN网络需要的各层一个add就是一个网络层
self.model.add(Convolution2D(32, (3, 3), padding='same',input_shape=dataset.input_shape)) # 1 2维卷积层
self.model.add(Activation('relu')) # 2 激活函数层
self.model.add(Convolution2D(32, (3, 3))) # 3 2维卷积层
self.model.add(Activation('relu')) # 4 激活函数层
self.model.add(MaxPooling2D(pool_size=(2, 2))) # 5 池化层
self.model.add(Dropout(0.25)) # 6 Dropout层
self.model.add(Convolution2D(64, (3, 3), padding='same')) # 7 2维卷积层
self.model.add(Activation('relu')) # 8 激活函数层
self.model.add(Convolution2D(64, (3, 3))) # 9 2维卷积层
self.model.add(Activation('relu')) # 10 激活函数层
self.model.add(MaxPooling2D(pool_size=(2, 2))) # 11 池化层
self.model.add(Dropout(0.25)) # 12 Dropout层
self.model.add(Flatten()) # 13 Flatten层
self.model.add(Dense(512)) # 14 Dense层,又被称作全连接层
self.model.add(Activation('sigmoid')) # 15 激活函数层
self.model.add(Dropout(0.5)) # 16 Dropout层
self.model.add(Dense(nb_classes)) # 17 Dense层
self.model.add(Activation('softmax')) # 18 分类层,输出最终结果
# 输出模型概况
self.model.summary()
# 训练模型
def train (self, dataset, batch_size=5, nb_epoch=10, data_augmentation=True):
sgd = SGD(lr=0.01, decay=1e-6,
momentum=0.99, nesterov=True) # 采用SGD+momentum的优化器进行训练首先生成一个优化器对象
#adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.99, epsilon=1e-08, decay=0.0)
#使用adam优化器
self.model.compile(loss = 'categorical_crossentropy',
optimizer = 'sgd', metrics = ['accuracy'])
# 完成实际的模型配置工作
# 不使用数据提升,所谓的提升就是从我们提供的训练数据中利用旋转、翻转、加噪声等方法创造新的
# 训练数据,有意识的提升训练数据规模,增加模型训练量
if not data_augmentation:
self.model.fit(dataset.train_images,
dataset.train_labels,
batch_size=batch_size,
epochs=nb_epoch,
shuffle=True)
# 使用实时数据提升
else:
# 定义数据生成器用于数据提升其返回一个生成器对象datagendatagen每被调用一
# 次其生成一组数据顺序生成节省内存其实就是python的数据生成器
datagen = ImageDataGenerator(
featurewise_center=False, # 是否使输入数据去中心化均值为0
samplewise_center=False, # 是否使输入数据的每个样本均值为0
featurewise_std_normalization=False, # 是否数据标准化(输入数据除以数据集的标准差)
samplewise_std_normalization=False, # 是否将每个样本数据除以自身的标准差
zca_whitening=False, # 是否对输入数据施以ZCA白化
rotation_range=20, # 数据提升时图片随机转动的角度(范围为0180)
width_shift_range=0.2, # 数据提升时图片水平偏移的幅度单位为图片宽度的占比0~1之间的浮点数
height_shift_range=0.2, # 同上,只不过这里是垂直
horizontal_flip=True, # 是否进行随机水平翻转
vertical_flip=False) # 是否进行随机垂直翻转
# 计算整个训练样本集的数量以用于特征值归一化、ZCA白化等处理
datagen.fit(dataset.train_images)
# 利用生成器开始训练模型
self.model.fit_generator(datagen.flow(dataset.train_images, dataset.train_labels,
batch_size=batch_size),
steps_per_epoch=np.ceil(dataset.train_images.shape[0]/batch_size),
nb_epoch=nb_epoch,
validation_data=(dataset.train_images, dataset.train_labels),
)
MODEL_PATH = './aggregate.face.model.h5'
def save_model(self, file_path=MODEL_PATH):
self.model.save(file_path)
def load_model(self, file_path=MODEL_PATH):
self.model = load_model(file_path)
def evaluate(self, dataset):
score = self.model.evaluate(dataset.test_images, dataset.test_labels, verbose=1)
print("%s: %.2f%%" % (self.model.metrics_names[1], score[1] * 100))
# 识别人脸
def face_predict(self, image):
# 依然是根据后端系统确定维度顺序
if K.image_data_format() == "channels_first" and image.shape != (1, 3, IMAGE_SIZE, IMAGE_SIZE):
image = resize_image(image)
# 尺寸必须与训练集一致都应该是IMAGE_SIZE x IMAGE_SIZE
image = image.reshape((1, 3, IMAGE_SIZE, IMAGE_SIZE))
# 与模型训练不同这次只是针对1张图片进行预测
elif K.image_data_format() == "channels_last" and image.shape != (1, IMAGE_SIZE, IMAGE_SIZE, 3):
image = resize_image(image)
image = image.reshape((1, IMAGE_SIZE, IMAGE_SIZE, 3))
# 浮点并归一化
image = image.astype('float32')
image /= 255
# 给出输入属于各个类别的概率
result_probability = self.model.predict_proba(image)
print(result_probability)
if max(result_probability[0]) >= 0.8:
result = self.model.predict_classes(image)
print(result)
return result[0]
else:
return -1

@ -0,0 +1,84 @@
import cv2
import os
import sys
import numpy as np
from createfold import CreateFolder
def CatchPICFromVideo (window_name, camera_idx, catch_pic_num, path_name, usr_name):
#camera_idx代表摄像头编号0即为系统默认
#检查输入路径是否存在——不存在就创建
CreateFolder(path_name)
cv2.namedWindow(window_name)
#cap = cv2.VideoCapture('./Qianyaxuan/Qianyaxuan.mp4')
cap = cv2.VideoCapture('./Wangwenhai/Wangwenhai.mp4')
# 设置分辨率
#cap = cv2.VideoCapture(camera_idx)
cap.set(3, 1920)
cap.set(4, 1080)
# 告诉OpenCV使用人脸识别分类器
classfier = cv2.CascadeClassifier("./haarcascade_frontalface_alt2.xml")
#记录已拍摄的照片数目
num = 0
while True:
ok, frame = cap.read() # 读取一帧数据
if not ok:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#将当前桢图像转换成灰度图像
# 人脸检测1.2和2分别为图片缩放比例和需要检测的有效点数
faceRects = classfier.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=2, minSize=(32, 32))
for (x, y, w, h) in faceRects:
#单独框出每一张人脸
#将当前帧保存为图片
img_name = '%s/%d.jpg' % ("./FaceData/"+usr_name, num)
#保存灰度人脸图
cv2.imwrite(img_name, gray[y:y+h, x:x+w])
num += 1
#画出矩形框的时候稍微比识别的脸大一圈
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10),(0, 255, 0),1)
#显示当前捕捉到了多少人脸图片
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame, 'num:%d' % (num), (x + 30, y + 30), font, 1, (255, 0, 255), 1)
# 超过指定最大保存数量结束程序
cv2.imshow(window_name, frame)
if num >= catch_pic_num:
break
#按键盘Q中断采集
if cv2.waitKey(5) & 0xFF == ord('q'):
break
# 释放摄像头并销毁所有窗口
print("拍摄完成,训练中......")
cap.release()
cv2.destroyAllWindows()

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@ -0,0 +1,74 @@
import sys
import numpy as np
import os
import cv2
IMAGE_SIZE = 128
def resize_image(image,height = IMAGE_SIZE,width = IMAGE_SIZE):
top,bottom,left,right = 0,0,0,0
#获取图像大小
h,w,_ = image.shape
#对于长宽不一的,取最大值
longest_edge = max(h,w)
#计算较短的边需要加多少像素
if h < longest_edge:
dh = longest_edge - h
top = dh // 2
bottom = dh - top
elif w < longest_edge:
dw = longest_edge - w
left = dw // 2
right = dw - left
else:
pass
#定义填充颜色
BLACK = [0,0,0]
#给图像增加边界使图片长、宽等长cv2.BORDER_CONSTANT指定边界颜色由value指定
constant_image = cv2.copyMakeBorder(image,top,bottom,left,right,cv2.BORDER_CONSTANT,value=BLACK)
return cv2.resize(constant_image,(height,width))
#读取数据
images = [] #数据集
labels = [] #标注集
def read_path(path_name):
for dir_item in os.listdir(path_name):
full_path = path_name + '\\' + dir_item
if os.path.isdir(full_path):
read_path(full_path)
else:
#判断是人脸照片
if dir_item.endswith('.jpg'):
image = cv2.imread(full_path)
image = resize_image(image)
images.append(image)
labels.append(path_name)
return images,labels
#为每一类数据赋予唯一的标签值
def label_id(label,users,user_num):
for i in range(user_num):
if label.endswith(users[i]):
return i
#从指定位置读数据
def load_dataset(path_name):
users = os.listdir(path_name)
user_num = len(users)
images,labels = read_path(path_name)
images_np = np.array(images)
#每个图片夹都赋予一个固定唯一的标签
labels_np = np.array([label_id(label,users,user_num) for label in labels])
return images_np,labels_np

@ -0,0 +1,31 @@
import numpy as np
import cv2
import os
import sys
import Digital_image_basics
import Edge_detection
import Image_enhancement
import Image_repair
import Image_segmentation
import recognition_face
if __name__ == '__main__':
print("选择你要实现的功能")
print("1.数字图像基础 2.边缘检测 3.图像增强 4.图像修复 5.图像分割 6.人脸识别")
myinput = input()
if myinput == '1':
Digital_image_basics.main()
elif myinput == '2':
Edge_detection.main()
elif myinput == '3':
Image_enhancement.main()
elif myinput == '4':
Image_repair.main()
elif myinput == '5':
Image_segmentation.main()
elif myinput == '6':
recognition_face.main()
else:
print("wrong input!")

@ -0,0 +1,100 @@
import cv2
import os
import gain_face
from face_train import Model, Dataset
def main():
judge = False
while True:
print("是否录入人脸信息(Yes or No)?,请输入英文名")
input_ = input()
if input_ == 'Yes':
# 员工姓名(要输入英文)
new_user_name = input("请输入您的姓名:")
print("请看摄像头!")
judge = True
# 采集员工图像的数量自己设定,越多识别准确度越高,但训练速度贼慢
window_name = 'Information Collection' # 图像窗口
camera_id = 0 # 相机的ID号
images_num = 200 # 采集图片数量
path = './FaceData/' + new_user_name # 图像保存位置
gain_face.CatchPICFromVideo(window_name, camera_id, images_num, path, new_user_name)
elif input_ == 'No':
break
else:
print("错误输入请输入Yes或者No")
# 加载模型
if judge == True:
user_num = len(os.listdir('./FaceData/'))
dataset = Dataset('./FaceData/')
dataset.load()
model = Model()
# 先前添加的测试build_model()函数的代码
model.build_model(dataset, nb_classes=user_num)
# 测试训练函数的代码
model.train(dataset)
model.save_model(file_path='./model/aggregate.face.model.h5')
else:
model = Model()
model.load_model(file_path='./model/aggregate.face.model.h5')
# 框住人脸的矩形边框颜色
color = (255, 255, 255)
# 捕获指定摄像头的实时视频流
cap = cv2.VideoCapture(0)
# 人脸识别分类器本地存储路径
cascade_path = "./haarcascade_frontalface_alt2.xml"
# 循环检测识别人脸
while True:
ret, frame = cap.read() # 读取一帧视频
if ret is True:
# 图像灰化,降低计算复杂度
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
else:
continue
# 使用人脸识别分类器,读入分类器
cascade = cv2.CascadeClassifier(cascade_path)
# 利用分类器识别出哪个区域为人脸
faceRects = cascade.detectMultiScale(frame_gray, scaleFactor=1.2, minNeighbors=2, minSize=(32, 32))
for (x, y, w, h) in faceRects:
# 截取脸部图像提交给模型识别这是谁
image = frame[y: y + h, x: x + w]
faceID = model.face_predict(image)
print(faceID)
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, thickness=1)
for i in range(len(os.listdir('./FaceData/'))):
if i == faceID:
# 文字提示是谁
cv2.putText(frame, os.listdir('./FaceData/')[i], (x + 30, y + 30), cv2.FONT_HERSHEY_SIMPLEX, 1,
color, 2)
cv2.imshow("recognition! press 'Q' to quit", frame)
# 等待10毫秒看是否有按键输入
k = cv2.waitKey(10)
# 如果输入q则退出循环
if k & 0xFF == ord('q'):
break
# 释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()
Loading…
Cancel
Save