人工智能与机器学习第8周作业
1. 深入了解SVM算法在解决线性不可分类时,对特征集进行多项式、核函数转换(升维)将其转换为线性可分类问题的思想。完成以下任务: 对照参考资料“支持向量机-课件-518.docx”,将其中的例子代码在Jupyter中重新做一遍。并将例子代码中采用多项式分类函数、高斯核函数对鸢尾花、月亮数据集进行SVM训练所得到最终分类决策函数,输出出来。
2. 以人脸识别(属于分类问题)为例,理解实际应用中的特征数据集提取。
1)用python3+opencv3.4+dlib库编程,打开摄像头,实时采集人脸并保存、绘制68个特征点;
2)不在原视频上绘制显示特征点,而是给人脸虚拟P上一付墨镜(提示:找到双眼特征点坐标值,以坐标中心点为圆心,用opencv函数绘制两个圆,并填充黑色)
目录
- SVM深入理解&人脸特征提取
- 一、SVM深入理解
- 1. 支持向量机
- 2.重做鸢尾花
- 1.多项式核
- 2.高斯核
- 二、人脸特征提取
- 1.安装dlib库和opencv
- 2.提取特征点
- 3.P上墨镜
- 三、总结
- 参考文献
一、SVM深入理解 1. 支持向量机
在上一篇博客中有引用百度百科的定义线性判别准则与线性分类编程实践
2.重做鸢尾花 1.多项式核- 导入包
## 导入包 from sklearn import datasets #导入数据集 from sklearn.svm import SVC #导入svm from sklearn.pipeline import Pipeline #导入python里的管道 import matplotlib.pyplot as plt from sklearn.preprocessing import StandardScaler#导入标准化 #多项式核svm from sklearn import datasets #导入数据集 from sklearn.svm import LinearSVC #导入线性svm from sklearn.pipeline import Pipeline #导入python里的管道 from matplotlib.colors import ListedColormap import matplotlib.pyplot as plt from sklearn.preprocessing import StandardScaler,PolynomialFeatures #导入多项式回归和标准化
- 定义
scaler=StandardScaler()# 标准化 scaler.fit(data_x)#计算训练数据的均值和方差 data_x=scaler.transform(data_x) #再用scaler中的均值和方差来转换X,使X标准化 liner_svc=LinearSVC(C=1e9,max_iter=100000)#线性svm分类器,iter是迭达次数,c值决定的是容错,c越大,容错越小 liner_svc.fit(data_x,data_y)
- 边界绘制函数
# 边界绘制函数
def plot_decision_boundary(model,axis):
x0,x1=np.meshgrid(
np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1),
np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1))
# meshgrid函数是从坐标向量中返回坐标矩阵
x_new=np.c_[x0.ravel(),x1.ravel()]
y_predict=model.predict(x_new)#获取预测值
zz=y_predict.reshape(x0.shape)
custom_cmap=ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
plt.contourf(x0,x1,zz,cmap=custom_cmap)
- 读取鸢尾花数据集
#读取鸢尾花数据集 data=datasets.load_iris() data_x=data.data data_y=data.target
- 显示鸢尾花数据集
plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1]) plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1]) data_x=data_x[data_y<2,:2]#只取data_y小于2的类别,并且只取前两个特征 data_y=data_y[data_y<2] plt.show()
- 规范化数据集
def PolynomialSVC(degree,c=10):#多项式svm
return Pipeline([
# 将源数据 映射到 3阶多项式
("poly_features", PolynomialFeatures(degree=degree)),
# 标准化
("scaler", StandardScaler()),
# SVC线性分类器
("svm_clf", LinearSVC(C=10, loss="hinge", random_state=42,max_iter=10000))
])
liner_svc.fit(data_x,data_y)
- 进行模型训练并画图
# 进行模型训练并画图
poly_svc=PolynomialSVC(degree=3)
poly_svc.fit(data_x,data_y)
plot_decision_boundary(poly_svc,axis=[-2.0,2.5,-2.5,3.0])#绘制边界
plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1],color='red')#画点
plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1],color='blue')
plt.show()
print('参数权重')
print(poly_svc.named_steps['svm_clf'].coef_)
print('模型截距')
print(poly_svc.named_steps['svm_clf'].intercept_)
- 结果
- 规范化数据集
def RBFKernelSVC(gamma=1.0):
return Pipeline([
('std_scaler',StandardScaler()),
('svc',SVC(kernel='rbf',gamma=gamma))
])
- 进行模型训练并画图
svc=RBFKernelSVC(gamma=100)#gamma参数很重要,gamma参数越大,支持向量越小 svc.fit(data_x,data_y) plot_decision_boundary(svc,axis=[-2.0,2.5,-2.5,3.0]) plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1],color='red')#画点 plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1],color='blue') plt.show()
- 结果
二、人脸特征提取 1.安装dlib库和opencv
-
安装dlib库
这里安装的是python3.8对应的cp38的版本
把安装的whl文件放到选择的路径,添加到环境变量的path里
命令语句pip install dlib-19.19.0-cp38-cp38-win_amd64.whl -
安装opencv
安装对应的版本
命令语句pip install opencv_python==3.4.11.45直接在命令行安装
由于是命令行安装且文件较大,所以是需要一些网速的,不然就会报一大片错 -
遇到的问题
由于本次安装dlib库和opencv的过程遇到了太多问题,这里取其中的一些提供解决方法
安装完opencv之后安装cv2命令:pip install opencv-contrib-python
完成之后发现无法引入cv2的包,报错:ModuleNotFoundError: No module named 'cv2'
原因是在本机的Python38环境下安装了cv2,但anaconda的jupyter依旧是39的版本,所以需要安装一个虚拟环境,在老师的帮助下安装了虚拟环境anaconda安装教程、管理虚拟环境配置到jupyterJupyter notebook选择运行代码的虚拟环境,解决问题。
使用脸部特征数据集
代码
# -*- coding: utf-8 -*-
"""
Created on Wed Oct 27 03:15:10 2021
@author: GT72VR
"""
#导入库
import numpy as np#数据处理库
import cv2#图像处理库
import dlib#人脸识别的库
import os
import sys
import random
# 存储位置
output_dir = 'D/faces'
size = 64
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 改变图片的亮度与对比度
def relight(img, light=1, bias=0):
w = img.shape[1]
h = img.shape[0]
#image = []
for i in range(0,w):
for j in range(0,h):
for c in range(3):
tmp = int(img[j,i,c]*light + bias)
if tmp > 255:
tmp = 255
elif tmp < 0:
tmp = 0
img[j,i,c] = tmp
return img
#使用dlib自带的frontal_face_detector作为我们的特征提取器
detector = dlib.get_frontal_face_detector()
# 打开摄像头 参数为输入流,可以为摄像头或视频文件
camera = cv2.VideoCapture(0)
#camera = cv2.VideoCapture('C:/Users/CUNGU/Videos/Captures/wang.mp4')
ok = True
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
while ok:
# 读取摄像头中的图像,ok为是否读取成功的判断参数
ok, img = camera.read()
# 转换成灰度图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
rects = detector(img_gray, 0)
for i in range(len(rects)):
landmarks = np.matrix([[p.x, p.y] for p in predictor(img,rects[i]).parts()])
for idx, point in enumerate(landmarks):
# 68点的坐标
pos = (point[0, 0], point[0, 1])
print(idx,pos)
# 利用cv2.circle给每个特征点画一个圈,共68个
cv2.circle(img, pos, 2, color=(0, 255, 0))
# 利用cv2.putText输出1-68
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, str(idx+1), pos, font, 0.2, (0, 0, 255), 1,cv2.LINE_AA)
cv2.imshow('video', img)
k = cv2.waitKey(1)
if k == 27: # press 'ESC' to quit
break
camera.release()
cv2.destroyAllWindows()
结果:
代码:
# 导入包
import numpy as np
import cv2
import dlib
import os
import sys
import random
def get_detector_and_predicyor():
#使用dlib自带的frontal_face_detector作为我们的特征提取器
detector = dlib.get_frontal_face_detector()
"""
功能:人脸检测画框
参数:PythonFunction和in Classes
in classes表示采样次数,次数越多获取的人脸的次数越多,但更容易框错
返回值是矩形的坐标,每个矩形为一个人脸(默认的人脸检测器)
"""
#返回训练好的人脸68特征点检测器
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
return detector,predictor
#获取检测器
detector,predictor=get_detector_and_predicyor()
def painting_sunglasses(img,detector,predictor):
#给人脸带上墨镜
rects = detector(img_gray, 0)
for i in range(len(rects)):
landmarks = np.matrix([[p.x, p.y] for p in predictor(img,rects[i]).parts()])
right_eye_x=0
right_eye_y=0
left_eye_x=0
left_eye_y=0
for i in range(36,42):#右眼范围
#将坐标相加
right_eye_x+=landmarks[i][0,0]
right_eye_y+=landmarks[i][0,1]
#取眼睛的中点坐标
pos_right=(int(right_eye_x/6),int(right_eye_y/6))
"""
利用circle函数画圆
函数原型
cv2.circle(img, center, radius, color[, thickness[, lineType[, shift]]])
img:输入的图片data
center:圆心位置
radius:圆的半径
color:圆的颜色
thickness:圆形轮廓的粗细(如果为正)。负厚度表示要绘制实心圆。
lineType: 圆边界的类型。
shift:中心坐标和半径值中的小数位数。
"""
cv2.circle(img=img, center=pos_right, radius=30, color=(0,0,255),thickness=1)#红色边框
cv2.circle(img=img, center=pos_right, radius=30, color=(0,0,0),thickness=-1)#黑色
for i in range(42,48):#左眼范围
#将坐标相加
left_eye_x+=landmarks[i][0,0]
left_eye_y+=landmarks[i][0,1]
#取眼睛的中点坐标
pos_left=(int(left_eye_x/6),int(left_eye_y/6))
cv2.circle(img=img, center=pos_left, radius=30, color=(0,0,255),thickness=1)#红色边框
cv2.circle(img=img, center=pos_left, radius=30, color=(0,0,0),thickness=-1)#黑色
camera = cv2.VideoCapture(0)#打开摄像头
ok=True
# 打开摄像头 参数为输入流,可以为摄像头或视频文件
while ok:
ok,img = camera.read()
# 转换成灰度图像
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#display_feature_point(img,detector,predictor)
painting_sunglasses(img,detector,predictor)#调用画墨镜函数
cv2.imshow('video', img)
k = cv2.waitKey(1)
if k == 27: # press 'ESC' to quit
break
camera.release()
cv2.destroyAllWindows()
结果:
三、总结 这次作业深入了解SVM算法一些线性分类的思想,加深了对opencv的理解和运用。但是在安装配置一些环境的时候往往会遇到很多问题,所以在安装一些环境的时候,安装一些稳定的版本很重要,其中可能有的问题会有人去摸索而不是需要你自己想办法从原理上解决。
参考文献
anaconda安装教程、管理虚拟环境
Jupyter notebook选择运行代码的虚拟环境
Dlib模型人脸特征检测原理及demo
ModuleNotFoundError: No module named ‘cv2’ (安装cv2)
python+OpenCv+dlib实现人脸68个关键点检测并标注



