day07-特征值矩阵-识别图片中的物体-视频捕捉-人脸定位-人脸识别的分类器
6.特征值矩阵(描述矩阵)
特征值矩阵 = STAR特征点(位置,大小)+SIFT(方向)
代码示例:desc.py
import cv2 as cv
import matplotlib.pyplot as mp
original = cv.imread('../../day01/data/table.jpg')
cv.imshow('or ',original)
gray = cv.cvtColor(original,cv.COLOR_BGR2GRAY)
cv.imshow('gr ',gray)
star = cv.xfeatures2d.StarDetector_create()
keystar = star.detect(gray)
sift = cv.xfeatures2d.SIFT_create() #需使用3.4.2.16版本:pip install opencv-contrib-python==3.4.2.16
_,desc = sift.compute(gray,keystar)
print(desc.shape)
mp.matshow(desc,cmap='jet',fignum='Desc')
mp.title('Desc',fontsize=20)
mp.xlabel('Feature',fontsize=14)
mp.ylabel('Sample',fontsize=14)
mp.tick_params(which='both',top=False,labeltop=False,
labelbottom=True,labelsize=10)
mp.tight_layout()
mp.show()
cv.waitKey()
7.识别图片中的物体
代码示例:obj.py
import cv2 as cv
import os
import warnings
import numpy as np
import hmmlearn.hmm as hl
warnings.filterwarnings('ignore',category=DeprecationWarning)
np.seterr(all='ignore')
def search_obj(directory):
directory = os.path.normpath(directory)
if not os.path.isdir(directory):
raise IOError("目录不存在:"+ directory)
obj = {}
for curdir,subdirs,files in os.walk(directory): #遍历目录
for jpeg in (file for file in files if file.endswith('.jpg')):
path = os.path.join(curdir,jpeg)
label = path.split(os.path.sep)[-2]#获得图片当前目录名称
if label not in obj:
obj[label] = []
obj[label].append(path)
return obj
train_objs = search_obj('../../day01/data/objects/training')
train_x,train_y = [],[]
for label,filenames in train_objs.items():
descs = np.array([])
for filename in filenames:
image = cv.imread(filename)
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
h,w = gray.shape[:2] #取得图片高度(行)和宽度(列)
f = 200 / min(h,w) #方便统一尺寸,以高宽最小值作为缩放小比例
gray = cv.resize(gray,None,fx=f,fy=f)#高宽等比缩放图片
star = cv.xfeatures2d.StarDetector_create()
keypoints = star.detect(gray)
sift = cv.xfeatures2d.SIFT_create()
_,desc = sift.compute(gray,keypoints)
if len(descs) == 0:
descs = desc
else:
descs = np.append(descs,desc,axis=0)
train_x.append(descs)
train_y.append(label)
models = {}
for descs,label in zip(train_x,train_y):
model = hl.GaussianHMM(n_components=4,covariance_type='diag',n_iter=1000)
models[label] = model.fit(descs) #训练模型
#以下测试模型
test_objs = search_obj('../../day01/data/objects/testing')
test_x,test_y,test_img = [],[],[]
for label,filenames in test_objs.items():
test_img.append([])
descs = np.array([])
for filename in filenames:
image = cv.imread(filename)
test_img[-1].append(image)
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
h,w = gray.shape[:2] #取得图片高度(行)和宽度(列)
f = 200 / min(h,w) #方便统一尺寸,以高宽最小值作为缩放小比例
gray = cv.resize(gray,None,fx=f,fy=f)#高宽等比缩放图片
star = cv.xfeatures2d.StarDetector_create()
keypoints = star.detect(gray)
sift = cv.xfeatures2d.SIFT_create()
_,desc = sift.compute(gray,keypoints)
if len(descs) == 0:
descs = desc
else:
descs = np.append(descs,desc,axis=0)
test_x.append(descs)
test_y.append(label)
pred_test_y = []#保存预测/测试结果
for descs in test_x:
best_score,best_label = None,None
for label,model in models.items():
score = model.score(descs)
if (best_score is None) or (best_score < score):
best_score,best_label = score,label
pred_test_y.append(best_label)
#以下输出预测结果
i = 0
for label,pred_label,images in zip(test_y,pred_test_y,test_img):
for image in images:
i += 1
cv.imshow('{}-{} {} {}'.format(i,label,
'==' if label == pred_label else '!=',pred_label),image)
cv.waitKey()
十七、人脸识别
1.视频捕捉
捕捉设备-->图像帧
代码示例:vidcap.py
import cv2 as cv
vc = cv.VideoCapture(0) #视频捕捉,设备ID为从0开始的整数,0,是第一个,1是第二个,也可同时打开多摄像头
while True:
frame = vc.read()[1] #获得一个图片帧
cv.imshow('VideoCapture',frame)
if cv.waitKey(33) == 27: #27:是esc键。33表示等待33毫秒,相当于每秒连续显示33张图片
break
vc.release()#一般摄像头是独占式,用完需释放
cv.destroyAllWindows()#释放隐藏窗口
2.人脸定位
哈儿级联人脸定位
cv.CascadeClassifier(xml参数文件)对象检测,如无参数文件,自动调用该函数分配初始参数
cv.CascadeClassifier('./face.xml')#脸部定位器
cv.CascadeClassifier('./eye.xml')#眼睛定位器
cv.CascadeClassifier('./nose.xml')#鼻子定位器
fd.detectMultiScale(原图,图片最小尺寸,抓取图片最大数量)级联分类器
获得人脸轮廓集合,每张图片一个元组,元组内包括脸的左边点坐标,顶点坐标,宽度,高度,形成元组列表返回。
图片最小尺寸:指原图的最小尺寸(厘米),低于尺寸不抓取。
抓取图片最大数量:指有效图片的数量。
ed.detectMultiScale(face,1.3,5)#在脸中定位眼睛,返回眼睛的外切矩形
nd.detectMultiScale(face,1.3,5)#在脸中定位鼻子,返回鼻子的外切矩形
cvEllipse(img, CvPoint center, CvSize axes, double angle,
double start_angle, double end_angle, CvScalar color,
int thickness=1, int line_type=8, int shift=0 )
Ellipse绘制椭圆圆弧和椭圆扇形
center--椭圆圆心坐标。axes--轴(半径)的长度。
angle--偏转的角度。start_angle--圆弧起始角的角度。
end_angle--圆弧终止角的角度。color--线条的颜色。
thickness--线条的粗细程度。
line_type--线条的类型,8 (or 0) - 8-connected line(8邻接)连接线。
4 - 4-connected line(4邻接)连接线。
shift--圆心坐标点和数轴的精度。
代码示例:haar.py
import cv2 as cv
# CascadeClassifier哈儿级联人脸定位器 face.xm为参数文件
fd = cv.CascadeClassifier('../../day01/data/haar/face.xml')#脸部定位器
ed = cv.CascadeClassifier('../../day01/data/haar/eye.xml')#眼睛定位器
nd = cv.CascadeClassifier('../../day01/data/haar/nose.xml')#鼻子定位器
vc = cv.VideoCapture(0) #视频捕捉,设备ID为从0开始的整数,0,是第一个,1是第二个,也可同时打开多摄像头
while True:
frame = vc.read()[1] #获得一个图片帧
# detectMultiScale级联分类器,人脸轮廓集合,1.3图片大小(厘米)下限,5,最多获取图片数量
faces = fd.detectMultiScale(frame,1.3,5) #获得每张矩形框脸的元组(左顶宽高四个点),形成元组列表返回。
for l,t,w,h in faces:
a , b = int(w/2),int(h/2) #用于在大图中绘制脸部的椭圆框
cv.ellipse(frame,(l+a,t+b),(a,b),0,0,360,(255,0,255),2)
face = frame[t:t+h,l:l+w] #将脸部取出
eyes = ed.detectMultiScale(face,1.3,5)#在脸中定位眼睛,返回眼睛的外切矩形
for l,t,w,h in eyes:
a, b = int(w / 2), int(h / 2) # 用于在脸的图片上绘制眼睛的椭圆框
cv.ellipse(face, (l + a, t + b), (a, b), 0, 0, 360, (0, 255, 0), 2)
nose = nd.detectMultiScale(face,1.3,5)#在脸中定位鼻子,返回鼻子的外切矩形
for l,t,w,h in nose:
a, b = int(w / 2), int(h / 2) # 用于在脸的图片上绘制鼻子的椭圆框
cv.ellipse(face, (l + a, t + b), (a, b), 0, 0, 360, (255, 0, 0), 2)
cv.imshow('VideoCapture',frame)
if cv.waitKey(33) == 27: #27:是esc键。33表示等待33毫秒,相当于每秒连续显示33张图片
break
vc.release()#一般摄像头是独占式,用完需释放
cv.destroyAllWindows()#释放隐藏窗口
3.简单人脸识别
OpenCV的LBPH:局部二值模式直方图
代码示例:face.py
import cv2 as cv
import os
import numpy as np
import sklearn.preprocessing as sp
fd = cv.CascadeClassifier('../../day01/data/haar/face.xml')
def search_faces(directory):
directory = os.path.normpath(directory)
if not os.path.isdir(directory):
raise IOError("目录不存在:"+ directory)
faces = {}
for curdir,subdirs,files in os.walk(directory): #遍历目录
for jpeg in (file for file in files if file.endswith('.jpg')):
path = os.path.join(curdir,jpeg)
label = path.split(os.path.sep)[-2]#获得图片当前目录名称
if label not in faces:
faces[label] = []
faces[label].append(path)
return faces
train_faces = search_faces('../../day01/data/faces/training')
codec = sp.LabelEncoder()#标签编码器
codec.fit(list(train_faces.keys()))#转换为编码字典
train_x,train_y = [],[]
for label,filenames in train_faces.items():
for filename in filenames:
image = cv.imread(filename)
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
#比minSize(像素)还小的尺寸,忽略。
faces = fd.detectMultiScale(gray,1.1,3,minSize=(100,100)) #定位脸部
for l,t,w,h in faces:
train_x.append(gray[t:t+h,l:l+w])#外切脸部
train_y.append(codec.transform([label])[0])
train_y = np.array(train_y)
model = cv.face.LBPHFaceRecognizer_create()#局部二值模式直方图人脸识别器
model.train(train_x,train_y)#训练模型
#以下模型测试/预测
test_faces = search_faces('../../day01/data/faces/testing')
test_x,test_y,test_img = [],[],[]
for label,filenames in test_faces.items():
for filename in filenames:
image = cv.imread(filename)
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
#比minSize(像素)还小的尺寸,忽略。
faces = fd.detectMultiScale(gray,1.1,2,minSize=(100,100)) #定位脸部
for l,t,w,h in faces:
test_x.append(gray[t:t+h,l:l+w])#外切脸部
test_y.append(codec.transform([label])[0])
a,b = int(w/2),int(h/2)
cv.ellipse(image,(l+a,t+b),(a,b),0,0,360,(255,0,255),2)
test_img.append(image)
test_y = np.array(test_y)
#输出预测结果
pred_test_y = []
for face in test_x:
pred_code = model.predict(face)[0]
pred_test_y.append(pred_code)
escape = False
while not escape:
for code,pred_code,image in zip(test_y,pred_test_y,test_img):
label,pred_label = codec.inverse_transform([code,pred_code])
text = '{} {} {}'.format(label,'=='if code == pred_code else '!=',
pred_label)
cv.putText(image,text,(10,60),cv.FONT_HERSHEY_SIMPLEX,2,(255,255,255),6)
cv.imshow('waiting...',image)
if cv.waitKey(1000)==27:
escape = True
break
4.基于通用分类器的人脸识别
1).显示数据集
代码示例:face1.py
import sklearn.datasets as sd
import matplotlib.pyplot as mp
faces = sd.fetch_olivetti_faces('../../day01/data/')
x, y = faces.data , faces.target
#print(x.shape,x.dtype,y.shape,set(y))
mp.figure('Olivette',facecolor='black')
mp.subplots_adjust(left=0.04,bottom=0.04,right=0.96,top=0.96,
wspace=0,hspace=0)#设定各子图边距与间隔,按百分数计算
rows,cols = 10,40
for row in range(rows):
for col in range(cols):
mp.subplot(rows,cols,row * cols + col + 1)
if row==0:
mp.title(str(col),fontsize=8,color='limegreen')
if col == 0:
mp.ylabel(str(row),fontsize=8,color='limegreen')
mp.xticks(())
mp.yticks(())
image = x[y==col][row].reshape(64,64)
mp.imshow(image,cmap='gray')
mp.show()
2).用SVM分类器实现人脸识别
代码示例:face2.py
import sklearn.datasets as sd
import sklearn.model_selection as ms
import sklearn.svm as svm
import sklearn.metrics as sm
import matplotlib.pyplot as mp
faces = sd.fetch_olivetti_faces('../../day01/data/')
x, y = faces.data , faces.target
#print(x.shape,x.dtype,y.shape,set(y))
train_x,test_x,train_y,test_y = ms.train_test_split(x,y,test_size=0.2,random_state=7)
model = svm.SVC(class_weight='balanced')
model.fit(train_x,train_y)
pred_test_y = model.predict(test_x)
cm = sm.confusion_matrix(test_y,pred_test_y)
cr = sm.classification_report(test_y,pred_test_y)
print(cr)#打印输出分类报告 #结果很差,F1打分为9%,数据问题?
mp.figure('Confusion_matrix',facecolor='black')
mp.title('Confusion_matrix',fontsize=20)
mp.xlabel('Predicted',fontsize=14)
mp.ylabel('TrueClass',fontsize=14)
mp.tick_params(labelsize=10)
mp.imshow(cm ,interpolation= 'nearest',cmap='gray')
mp.show()
3).主成分分析(PCA)降维
代码示例:pca1.py numpy 降维
import numpy as np
#原始样本
A = np.mat('3 2000;2 3000;4 5000;5 8000;1 2000',dtype=float)
print('A=',A,sep='\n')
#降维:归一化缩放,每列均值为0,范围在0-1之间
mu = A.mean(axis=0) #求各列平均值
s = A.max(axis=0) - A.min(axis=0)
X = (A - mu ) /s
print('X=',X,sep='\n')
#协方差矩阵
SIGMA = X.T * X
print(SIGMA)
#奇异值分解
U,S,V = np.linalg.svd(SIGMA)
print('U=',U,sep='\n')
#主成分特征矩阵
U_reduce = U[:,0]
print('U_reduce',U_reduce,sep='\n')
#获得降维样本
Z = X * U_reduce
print('Z=',Z,sep='\n')
#降维样本恢复
#1、恢复归一缩放样本(近似恢复)
X_approx = Z * U_reduce.T
print('X_approx',X_approx,sep='\n')
#2、近似恢复原样本A
A_approx = np.multiply(X_approx,s) + mu
print('A_approx',A_approx,sep='\n')
代码示例:pca2.py sklearn.decomposition
import numpy as np
import sklearn.pipeline as pl
import sklearn.preprocessing as sp
import sklearn.decomposition as dc #降维工具
#原始样本
A = np.mat('3 2000;2 3000;4 5000;5 8000;1 2000',dtype=float)
print('A=',A,sep='\n')
#构建PCA模型
#MinMaxScaler做归一化缩放
#PCA(n_components=1)降维
model = pl.Pipeline([('scaler',sp.MinMaxScaler()),('pca',dc.PCA(n_components=1))])
#降维样本
Z = model.fit_transform(A)
print('Z=',Z,sep='\n')
#近视恢复到原始样本
A_approx = model.inverse_transform(Z)
print('A_approx',A_approx,sep='\n')
4).还原率
进过PCA降维后的样本,再进行逆向还原,与原始样本相比的误差
代码示例:face3.py
import sklearn.datasets as sd
import sklearn.decomposition as dc
import matplotlib.pyplot as mp
faces = sd.fetch_olivetti_faces('../../day01/data/')
x, y = faces.data , faces.target
#print(x.shape,x.dtype,y.shape,set(y))
ncps = range(10,410,10)
evrs = []
for ncp in ncps:
model = dc.PCA(n_components=ncp)
model.fit_transform(x)
evr = model.explained_variance_ratio_.sum() #还原率误差
evrs.append(evr)
mp.figure('explained_variance_ratio',facecolor='black')
mp.title('explained_variance_ratio',fontsize=20)
mp.xlabel('n_components',fontsize=14)
mp.ylabel('explained_variance_ratio',fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(ncps,evrs,c='dodgerblue',label='explained_variance_ratio')
mp.legend()
mp.show()
代码示例:face4.py
import sklearn.datasets as sd
import sklearn.decomposition as dc
import matplotlib.pyplot as mp
faces = sd.fetch_olivetti_faces('../../day01/data/')
x, y = faces.data , faces.target
#print(x.shape,x.dtype,y.shape,set(y))
mp.figure('explained_variance_ratio',facecolor='black')
mp.subplots_adjust(left=0.04,bottom=0.04,right=0.96,top=0.96,
wspace=0,hspace=0)#设定各子图边距与间隔,按百分数计算
rows,cols = 11,40
for row in range(rows):
if row > 0 :
ncp = 140 - (row -1) * 15
model = dc.PCA(n_components=ncp)
model.fit(x)
for col in range(cols):
mp.subplot(rows,cols,row * cols + col + 1)
if row==0:
mp.title(str(col),fontsize=8,color='limegreen')
if col == 0:
mp.ylabel(str(ncp) if row > 0 else 'orig',fontsize=8,color='limegreen')
mp.xticks(())
mp.yticks(())
if row > 0:
pca_x = model.transform([x[y==col][0]])
ipca_x = model.inverse_transform(pca_x) #还原
image = ipca_x.reshape(64,64)
else:
image = x[y==col][0].reshape(64,64)
mp.imshow(image,cmap='gray')#显示还原后的图片
mp.show()
5).用PCA降维改善基于SVM分类器的人脸识别效果
代码示例:face5.py 与face2.py对比后,效果大幅提升
import sklearn.datasets as sd
import sklearn.decomposition as dc
import sklearn.model_selection as ms
import sklearn.svm as svm
import sklearn.metrics as sm
import matplotlib.pyplot as mp
faces = sd.fetch_olivetti_faces('../../day01/data/')
x, y = faces.data , faces.target
#print(x.shape,x.dtype,y.shape,set(y))
model = dc.PCA(n_components=140)
pca_x = model.fit_transform(x)
#print(x.shape,pca_x.shape)
train_x,test_x,train_y,test_y = ms.train_test_split(pca_x,y,test_size=0.2,random_state=7)
model = svm.SVC(class_weight='balanced')
model.fit(train_x,train_y)
pred_test_y = model.predict(test_x)
cm = sm.confusion_matrix(test_y,pred_test_y)
cr = sm.classification_report(test_y,pred_test_y)
print(cr)#打印输出分类报告 #结果很差,F1打分为9%,数据问题?
mp.figure('Confusion_matrix',facecolor='black')
mp.title('Confusion_matrix',fontsize=20)
mp.xlabel('Predicted',fontsize=14)
mp.ylabel('TrueClass',fontsize=14)
mp.tick_params(labelsize=10)
mp.imshow(cm ,interpolation= 'nearest',cmap='gray')
mp.show()
6).核主成分分析(KPCA)
先升维 再降维
对于在原始维度空间无法线性分割的样本,利用核函数升高
维度,力图在更高纬度空间线性可分,而后再选择适当的与
原始维度相同的空间做反向投影,得到低纬度空间线性可分的样本集。
代码示例:kpca.py
import sklearn.datasets as sd
import sklearn.decomposition as dc
import matplotlib.pyplot as mp
x,y = sd.make_circles(n_samples=500,factor=0.2,noise=0.04)
model = dc.KernelPCA(kernel='rbf',gamma=1) #升维
kpca_x = model.fit_transform(x)[:,:x.shape[1]]
mp.figure('Original',facecolor='lightgray')
mp.title('Original',fontsize=20)
mp.xlabel('x',fontsize=14)
mp.ylabel('y',fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(x[:,0],x[:,1],c=y,cmap='brg',alpha=0.5,s=60)
mp.figure('KPCA',facecolor='lightgray')
mp.title('KPCA',fontsize=20)
mp.xlabel('x',fontsize=14)
mp.ylabel('y',fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(kpca_x[:,0],kpca_x[:,1],c=y,cmap='brg',alpha=0.5,s=60)
mp.show()
python MachinelEarning机器学习笔记day07
最新推荐文章于 2020-07-14 14:07:15 发布