diff --git a/实验八/detect.py b/实验八/detect.py index e69de29..4db24f2 100644 --- a/实验八/detect.py +++ b/实验八/detect.py @@ -0,0 +1,78 @@ +import cv2 as cv +import numpy as np +import dlib +import joblib + + +# 画框函数 +def draw_rect(img, faces): + for face in faces: + cv.rectangle(img, (face.left(), face.top()), (face.right(), face.bottom()), (0, 0, 255), 32) + return img + + +# 检测人脸并画框 +def detect_face(img): + img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) + result = detector(img_gray, 1) + img_result = draw_rect(img, result) + return img_result + + +# 提取人脸特征 +def extract_face_feature(img): + faces = detector(img) + if len(faces) > 0: + face = faces[0] + landmarks = predictor(img, face) + face_descriptor = face_rec_model.compute_face_descriptor(img, landmarks) + return np.array(face_descriptor) + else: + return None + + +# 加载分类器 +classifier = joblib.load('models/classifier.pkl') + +# 读取测试图片 +positive_sample = cv.imread('cache/positive_test.jpg') +positive_sample_rgb = cv.cvtColor(positive_sample, cv.COLOR_BGR2RGB) + +negative_sample = cv.imread('cache/negative_test.jpg') +negative_sample_rgb = cv.cvtColor(negative_sample, cv.COLOR_BGR2RGB) + +# 加载dlib人脸检测模型 +detector = dlib.get_frontal_face_detector() +predictor = dlib.shape_predictor("models/shape_predictor_68_face_landmarks_GTX.dat") +face_rec_model = dlib.face_recognition_model_v1('models/dlib_face_recognition_resnet_model_v1.dat') + +# 检测人脸 +positive_result = detect_face(positive_sample) +negative_result = detect_face(negative_sample) + +# 计算人脸特征 +positive_feature = extract_face_feature(positive_sample_rgb) +positive_feature = np.array(positive_feature).reshape(1, -1) + +negative_feature = extract_face_feature(negative_sample_rgb) +negative_feature = np.array(negative_feature).reshape(1, -1) + +# 通过分类器预测 +positive_predict = classifier.predict(positive_feature) +negative_predict = classifier.predict(negative_feature) + +# 展示 +positive_result_resized = cv.resize(positive_result, + (int(positive_result.shape[1] * 0.1), int(positive_result.shape[0] * 0.1))) +positive_result_resized = cv.putText(positive_result_resized, str(positive_predict), (50, 50), cv.FONT_HERSHEY_SIMPLEX, + 1, (0, 0, 255), 2) + +negative_result_resized = cv.resize(negative_result, + (int(negative_result.shape[1] * 0.1), int(negative_result.shape[0] * 0.1))) +negative_result_resized = cv.putText(negative_result_resized, str(negative_predict), (50, 50), cv.FONT_HERSHEY_SIMPLEX, + 1, (0, 0, 255), 2) + +cv.imshow('positive_result', positive_result_resized) +cv.imshow('negative_result', negative_result_resized) +cv.waitKey(0) +cv.destroyAllWindows() diff --git a/实验八/train.py b/实验八/train.py index d7c8931..45622d7 100644 --- a/实验八/train.py +++ b/实验八/train.py @@ -8,88 +8,94 @@ from sklearn.model_selection import train_test_split from sklearn.svm import SVC from tqdm import tqdm + # 方法区 -## 转换为二值图和GRB图 +## 转换为二值图和RGB图 def img_cvt(img): img_gray = cv.cvtColor(img, cv2.COLOR_BGR2GRAY) - _,img_gray=cv.threshold(img_gray,127,255,cv.THRESH_BINARY) - img_gray = cv.blur(img_gray,(3,3)) + _, img_gray = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY) + img_gray = cv.blur(img_gray, (3, 3)) img_rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB) - return img_gray,img_rgb + return img_gray, img_rgb + + ## 提取人脸特征 def extract_face_feature(img): - faces=detector(img) - if len(faces)>0: - face=faces[0] - landmarks=predictor(img,face) - face_descriptor=face_rec_model.compute_face_descriptor(img,landmarks) + faces = detector(img) + if len(faces) > 0: + face = faces[0] + landmarks = predictor(img, face) + face_descriptor = face_rec_model.compute_face_descriptor(img, landmarks) return np.array(face_descriptor) else: return None + + ## 生成伪样品 def gen_negative_samples(features_dim=128): - return np.random.uniform(-1,1,features_dim) + return np.random.uniform(-1, 1, features_dim) + # 变量区 -dataset_video=cv.VideoCapture('cache/dataset.mp4') -datasets=[] -datasets_rgb=[] -features=[] -negative_samples=[] +dataset_video = cv.VideoCapture('cache/dataset.mp4') +datasets = [] +datasets_rgb = [] +features = [] +negative_samples = [] # 收集数据集 ## 采用视频的格式收集图片 -while(True): - ret,frame=dataset_video.read() +while (True): + ret, frame = dataset_video.read() if not ret: break datasets.append(frame) # 加载人脸检测模型 -detector=dlib.get_frontal_face_detector() -predictor=dlib.shape_predictor("models/shape_predictor_68_face_landmarks_GTX.dat") -face_rec_model=dlib.face_recognition_model_v1('models/dlib_face_recognition_resnet_model_v1.dat') +detector = dlib.get_frontal_face_detector() +predictor = dlib.shape_predictor("models/shape_predictor_68_face_landmarks_GTX.dat") +face_rec_model = dlib.face_recognition_model_v1('models/dlib_face_recognition_resnet_model_v1.dat') # 预处理数据集 -for dataset in tqdm(datasets,desc='正在预处理数据集'): - _,dataset_rgb = img_cvt(dataset) +for dataset in tqdm(datasets, desc='正在预处理数据集'): + _, dataset_rgb = img_cvt(dataset) datasets_rgb.append(dataset_rgb) # 求人脸特征 -for dataset in tqdm(datasets_rgb,desc='正在求人脸特征'): - face_descriptor=extract_face_feature(dataset) +for dataset in tqdm(datasets_rgb, desc='正在求人脸特征'): + face_descriptor = extract_face_feature(dataset) if face_descriptor is not None: features.append(face_descriptor) # 生成负样本 -for i in tqdm(range(len(features)*15),desc='正在生成负样本'): - negative_sample=gen_negative_samples() +for i in tqdm(range(len(features) * 2048), desc='正在生成负样本'): + negative_sample = gen_negative_samples() negative_samples.append(negative_sample) # 编码数据集 -positive_labels=[1]*len(features) -negative_labels=[0]*len(negative_samples) +positive_labels = [1] * len(features) +negative_labels = [0] * len(negative_samples) -samples=features+negative_samples -labels=positive_labels+negative_labels +samples = features + negative_samples +labels = positive_labels + negative_labels -X_train=np.array(samples) -Y_train=np.array(labels) +X_train = np.array(samples) +Y_train = np.array(labels) # 分离数据集和训练集 -X_train,X_test,Y_train,Y_test=train_test_split(X_train,Y_train,test_size=0.2,random_state=42,stratify=Y_train) +X_train, X_test, Y_train, Y_test = train_test_split(X_train, Y_train, test_size=0.2, random_state=42, stratify=Y_train) # 训练 print('正在训练分类器') -classifier=SVC(kernel='linear',C=1.0,random_state=42) -classifier.fit(X_train,Y_train) +classifier = SVC(kernel='linear', C=1.0, random_state=42) +classifier.fit(X_train, Y_train) # 评估分类器性能 -Y_pred=[] -for test_sample in tqdm(X_test,desc='评估分类器'): - Y_pred.append(classifier.predict(test_sample.reshape(1,-1))) -accuracy=accuracy_score(Y_test,Y_pred) -print(f'准确率:{accuracy*100:.2f}%') +Y_pred = [] +for test_sample in tqdm(X_test, desc='评估分类器'): + Y_pred.append(classifier.predict(test_sample.reshape(1, -1))) +accuracy = accuracy_score(Y_test, Y_pred) +print(f'准确率:{accuracy * 100:.5f}%') # 保存模型 -joblib.dump(classifier,'models/classifier.pkl') \ No newline at end of file +joblib.dump(classifier, 'models/classifier.pkl')