实验七完成
This commit is contained in:
+2
-1
@@ -152,4 +152,5 @@ cython_debug/
|
|||||||
实验六/models/
|
实验六/models/
|
||||||
|
|
||||||
# dataset
|
# dataset
|
||||||
实验七/cache/
|
实验七/cache/
|
||||||
|
实验七/models/
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import cv2 as cv
|
||||||
|
import os
|
||||||
|
import tqdm
|
||||||
|
|
||||||
|
# 处理图像
|
||||||
|
def pretrain(img_path,output_path):
|
||||||
|
img=cv.imread(img_path, cv.IMREAD_GRAYSCALE)
|
||||||
|
img = cv.resize(img, (50, 50))
|
||||||
|
_,img=cv.threshold(img,127,255,cv.THRESH_BINARY)
|
||||||
|
img=cv.blur(img,(3,3))
|
||||||
|
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||||
|
cv.imwrite(output_path, img)
|
||||||
|
|
||||||
|
# 获取文件路径
|
||||||
|
def get_img_name(directory, extensions=None):
|
||||||
|
if extensions is None:
|
||||||
|
extensions = ['.png', '.jpg','.jpeg']
|
||||||
|
files = []
|
||||||
|
for root, dirs, file_names in os.walk(directory):
|
||||||
|
for file_name in file_names:
|
||||||
|
if any(file_name.lower().endswith(ext) for ext in extensions):
|
||||||
|
files.append(os.path.join(root, file_name))
|
||||||
|
return files
|
||||||
|
|
||||||
|
# 处理非人脸数据集
|
||||||
|
os.makedirs('cache/pretrained/non_face/', exist_ok=True)
|
||||||
|
non_face_files=get_img_name('cache/dataset/non_face/')
|
||||||
|
print('预处理非人脸数据中:')
|
||||||
|
for img_path in tqdm.tqdm(non_face_files):
|
||||||
|
pretrain(img_path, os.path.join('cache/pretrained/non_face', os.path.basename(img_path)))
|
||||||
|
|
||||||
|
# 处理人脸数据集
|
||||||
|
os.makedirs('cache/pretrained/face/', exist_ok=True)
|
||||||
|
face_files=get_img_name('cache/dataset/face/')
|
||||||
|
print('预处理人脸数据中:')
|
||||||
|
for img_path in tqdm.tqdm(face_files):
|
||||||
|
relative_path=os.path.relpath(img_path, 'cache/dataset/face/')
|
||||||
|
output_path=os.path.join('cache/pretrained/face', relative_path)
|
||||||
|
pretrain(img_path, output_path)
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import numpy as np
|
||||||
|
import cv2 as cv
|
||||||
|
import os
|
||||||
|
import tqdm
|
||||||
|
from sklearn.metrics import accuracy_score
|
||||||
|
from sklearn.model_selection import train_test_split
|
||||||
|
from sklearn.svm import SVC
|
||||||
|
from joblib import dump
|
||||||
|
|
||||||
|
|
||||||
|
# 加载图像
|
||||||
|
def load_dataset(directory):
|
||||||
|
files = []
|
||||||
|
for root, dirs, file_list in os.walk(directory):
|
||||||
|
for file in file_list:
|
||||||
|
files.append(os.path.join(root, file))
|
||||||
|
return files
|
||||||
|
|
||||||
|
# 提取特征
|
||||||
|
## 提取轮廓特征
|
||||||
|
def extract_contour_features(img):
|
||||||
|
contours, _ = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
|
||||||
|
contour = contours[0]
|
||||||
|
area = cv.contourArea(contour)
|
||||||
|
perimeter = cv.arcLength(contour, True)
|
||||||
|
return [area, perimeter]
|
||||||
|
|
||||||
|
## 提取形状特征
|
||||||
|
def extract_shape_features(contour):
|
||||||
|
x, y, w, h = cv.boundingRect(contour)
|
||||||
|
aspect_ratio = float(w) / h
|
||||||
|
rect_area = w * h
|
||||||
|
shape_factor = cv.contourArea(contour) / rect_area
|
||||||
|
return [aspect_ratio, shape_factor]
|
||||||
|
|
||||||
|
## 计算HU矩
|
||||||
|
def extract_hu_moments(contour):
|
||||||
|
moments = cv.moments(contour)
|
||||||
|
hu_moments = cv.HuMoments(moments)
|
||||||
|
return hu_moments.flatten()
|
||||||
|
|
||||||
|
## 特征向量构建
|
||||||
|
def extract_features(img_path):
|
||||||
|
img = cv.imread(img_path, cv.IMREAD_GRAYSCALE)
|
||||||
|
if img is None:
|
||||||
|
raise FileNotFoundError(f"无法加载图像: {img_path}")
|
||||||
|
|
||||||
|
_, img_bin = cv.threshold(img, 128, 255, cv.THRESH_BINARY)
|
||||||
|
contours, _ = cv.findContours(img_bin, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
|
||||||
|
if len(contours) == 0:
|
||||||
|
return [0] * 11
|
||||||
|
contour = contours[0]
|
||||||
|
contour_features = extract_contour_features(img_bin)
|
||||||
|
shape_features = extract_shape_features(contour)
|
||||||
|
hu_moments = extract_hu_moments(contour)
|
||||||
|
feature_vector = contour_features + shape_features + hu_moments.tolist()
|
||||||
|
return feature_vector + [0] * (11 - len(feature_vector))
|
||||||
|
|
||||||
|
# 加载数据集和标签
|
||||||
|
face_paths = load_dataset("cache/pretrained/face/")
|
||||||
|
face_train_data = [(path, True) for path in face_paths]
|
||||||
|
non_face_paths = load_dataset("cache/pretrained/non_face/")
|
||||||
|
non_face_train_data = [(path, False) for path in non_face_paths]
|
||||||
|
|
||||||
|
train_test_data = face_train_data + non_face_train_data
|
||||||
|
train_data, test_data = train_test_split(train_test_data, test_size=0.3)
|
||||||
|
|
||||||
|
# 提取特征和标签
|
||||||
|
X_train = np.vstack([extract_features(train_path) for train_path, _ in tqdm.tqdm(train_data, desc="数据集特征提取中:")])
|
||||||
|
X_test = np.vstack([extract_features(test_path) for test_path, _ in tqdm.tqdm(test_data, desc="测试集特征提取中:")])
|
||||||
|
|
||||||
|
Y_train = np.array([label for _, label in train_data])
|
||||||
|
Y_test = np.array([label for _, label in test_data])
|
||||||
|
|
||||||
|
|
||||||
|
# 训练分类器
|
||||||
|
classifier = SVC(kernel='linear', max_iter=10000)
|
||||||
|
classifier.fit(X_train, Y_train)
|
||||||
|
|
||||||
|
# 评估
|
||||||
|
Y_pred = classifier.predict(X_test)
|
||||||
|
|
||||||
|
accuracy = accuracy_score(Y_test, Y_pred)
|
||||||
|
print(f"准确率: {accuracy * 100:.2f}%")
|
||||||
|
|
||||||
|
# 保存模型
|
||||||
|
os.makedirs("models", exist_ok=True)
|
||||||
|
dump(classifier, "models/classifier.pkl")
|
||||||
+105
-10
@@ -1,16 +1,111 @@
|
|||||||
# 这是一个示例 Python 脚本。
|
import cv2 as cv
|
||||||
|
import numpy as np
|
||||||
|
from joblib import load
|
||||||
|
|
||||||
# 按 Shift+F10 执行或将其替换为您的代码。
|
classifier = load('models/classifier.pkl')
|
||||||
# 按 双击 Shift 在所有地方搜索类、文件、工具窗口、操作和设置。
|
|
||||||
|
# 预处理图像
|
||||||
|
def pre_detect(img):
|
||||||
|
pre_img = img.copy()
|
||||||
|
pre_img = cv.resize(pre_img, (50, 50))
|
||||||
|
pre_img = cv.cvtColor(pre_img, cv.COLOR_BGR2GRAY)
|
||||||
|
_, pre_img = cv.threshold(pre_img, 127, 255, cv.THRESH_BINARY)
|
||||||
|
pre_img = cv.blur(pre_img, (3, 3))
|
||||||
|
return pre_img
|
||||||
|
|
||||||
|
# 特征提取
|
||||||
|
def pre_detect(img):
|
||||||
|
pre_img = img.copy()
|
||||||
|
pre_img = cv.resize(pre_img, (50, 50))
|
||||||
|
pre_img = cv.cvtColor(pre_img, cv.COLOR_BGR2GRAY)
|
||||||
|
_, pre_img = cv.threshold(pre_img, 127, 255, cv.THRESH_BINARY)
|
||||||
|
pre_img = cv.blur(pre_img, (3, 3))
|
||||||
|
return pre_img
|
||||||
|
|
||||||
|
# 特征提取
|
||||||
|
def extract_contour_features(img):
|
||||||
|
contours, _ = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
|
||||||
|
if len(contours) == 0:
|
||||||
|
return [0, 0] # 如果没有轮廓,返回默认值
|
||||||
|
contour = contours[0]
|
||||||
|
area = cv.contourArea(contour)
|
||||||
|
perimeter = cv.arcLength(contour, True)
|
||||||
|
return [area, perimeter]
|
||||||
|
|
||||||
|
def extract_shape_features(contour):
|
||||||
|
x, y, w, h = cv.boundingRect(contour)
|
||||||
|
aspect_ratio = float(w) / h
|
||||||
|
rect_area = w * h
|
||||||
|
shape_factor = cv.contourArea(contour) / rect_area
|
||||||
|
return [aspect_ratio, shape_factor]
|
||||||
|
|
||||||
|
def extract_hu_moments(contour):
|
||||||
|
moments = cv.moments(contour)
|
||||||
|
hu_moments = cv.HuMoments(moments)
|
||||||
|
return hu_moments.flatten()
|
||||||
|
|
||||||
|
|
||||||
def print_hi(name):
|
def extract_features(img):
|
||||||
# 在下面的代码行中使用断点来调试脚本。
|
contours, _ = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
|
||||||
print(f'Hi, {name}') # 按 Ctrl+F8 切换断点。
|
if len(contours) == 0:
|
||||||
|
# 如果没有找到轮廓,返回 11 个零,保持特征数量一致
|
||||||
|
return [0] * 11
|
||||||
|
contour = contours[0]
|
||||||
|
|
||||||
|
# 提取轮廓特征
|
||||||
|
contour_features = extract_contour_features(img)
|
||||||
|
|
||||||
|
# 提取形状特征
|
||||||
|
shape_features = extract_shape_features(contour)
|
||||||
|
|
||||||
|
# 提取 Hu 矩
|
||||||
|
hu_moments = extract_hu_moments(contour)
|
||||||
|
|
||||||
|
# 合并所有特征为一个特征向量,确保总共有 11 个特征
|
||||||
|
feature_vector = contour_features + shape_features + hu_moments.tolist()
|
||||||
|
return feature_vector
|
||||||
|
|
||||||
|
|
||||||
# 按装订区域中的绿色按钮以运行脚本。
|
# 读取图像并进行预处理
|
||||||
if __name__ == '__main__':
|
img = cv.imread('test.jpg')
|
||||||
print_hi('PyCharm')
|
pre_img = pre_detect(img)
|
||||||
|
|
||||||
# 访问 https://www.jetbrains.com/help/pycharm/ 获取 PyCharm 帮助
|
features = extract_features(pre_img)
|
||||||
|
|
||||||
|
features = np.array(features).reshape(1, -1)
|
||||||
|
|
||||||
|
predict_label = classifier.predict(features)
|
||||||
|
|
||||||
|
cv.imshow('face? ' + str(predict_label[0]), img)
|
||||||
|
cv.waitKey(0)
|
||||||
|
cv.destroyAllWindows()
|
||||||
|
|
||||||
|
# 读取视频并进行检测
|
||||||
|
cap = cv.VideoCapture(1)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
ret, frame = cap.read()
|
||||||
|
if not ret:
|
||||||
|
break
|
||||||
|
|
||||||
|
# 预处理
|
||||||
|
pre_img = pre_detect(frame)
|
||||||
|
|
||||||
|
# 提取特征
|
||||||
|
features = extract_features(pre_img)
|
||||||
|
features=np.array(features).reshape(1, -1)
|
||||||
|
|
||||||
|
predict_label = classifier.predict(features)
|
||||||
|
|
||||||
|
# 在帧上显示预测结果
|
||||||
|
label_text = 'Face' if predict_label[0] else 'Non-Face'
|
||||||
|
cv.putText(frame, label_text, (50, 50), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv.LINE_AA)
|
||||||
|
|
||||||
|
# 展示
|
||||||
|
cv.imshow('video', frame)
|
||||||
|
|
||||||
|
if cv.waitKey(1) & 0xFF == ord('q'):
|
||||||
|
break
|
||||||
|
|
||||||
|
cap.release()
|
||||||
|
cv.destroyAllWindows()
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -13,6 +13,7 @@ rcParams['font.sans-serif'] = ['SimHei']
|
|||||||
rcParams['axes.unicode_minus'] = False
|
rcParams['axes.unicode_minus'] = False
|
||||||
|
|
||||||
# 预处理图像
|
# 预处理图像
|
||||||
|
img=cv.resize(img,(28,28))
|
||||||
_,img_classifier=cv.threshold(img, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
|
_,img_classifier=cv.threshold(img, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
|
||||||
img_classifier=cv.blur(img,(3,3))
|
img_classifier=cv.blur(img,(3,3))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user