用HOG特征进行固定尺寸的人脸识别

# -*- coding: UTF-8 -*-
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from skimage import data, color, feature
from sklearn.datasets import fetch_lfw_people
import skimage.data
from itertools import chain # 用于组合样本
from skimage import data, transform
from sklearn.feature_extraction.image import PatchExtractor
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import cross_val_score
from sklearn.svm import LinearSVC
from sklearn.model_selection import GridSearchCV
sns.set()


def sliding_window(img, patch_size, istep=2, jstep=2, scale=1): # 然而当要预测照片的尺寸和学习模型学习的尺寸不一样时候,效果打折
print('patch_size:', patch_size)
Ni, Nj = (int(scale * s) for s in patch_size) # 找到缩略图像素框总长宽
print('sliding_window_img.shape: ', img.shape)
# print('Ni:', Ni)
# print('Nj:', Nj)
for i in range(0, img.shape[0] - Ni, istep): # 长度方向步进2
for j in range(0, img.shape[1] - Ni, jstep): # 宽度方向步进2
patch = img[i:i + Ni, j:j + Nj] # 新缩略图大小被步进窗口赋值
if scale != 1: # 不是1的话,则化为patch_size大小
patch = transform.resize(patch, patch_size)
yield (i, j), patch # 生成返回窗口坐标,HOG特征窗口对象


def extract_patches(img, N, patch_size, scale=1.0): # N是每个尺寸照片的训练样本数,patch_size是用来显示的尺度
print('img.shape:\n', img.shape)
# print('img[np.newaxis].shape:\n', img[np.newaxis].shape)
print('scale:\n', scale)
print('patch_size):\n', patch_size)
print('scale * np.array(patch_size):\n', scale * np.array(patch_size)) # 元组化为数组后扩大缩小尺寸
extracted_patch_size = tuple((scale * np.array(patch_size)).astype(int)) # 对原图数据放大缩小后,numpy.float64化为元组,抽出尺寸化为整形
print('extracted_patch_size:\n', extracted_patch_size)
# PatchExtractor类支持多幅图像作为输入
extractor = PatchExtractor(patch_size=extracted_patch_size, max_patches=N, random_state=0) # 能按照不同size抽出的抽出器
patches = extractor.transform(img[np.newaxis]) # img[np.newaxis]增加一个维度,eg: (872, 1000) -> (1, 872, 1000),抽出转换
# print('patches.shape:', patches.shape, 'scale:', scale) # N*(img.shape转换为缩略图的维度)
if scale != 1:
# 尺寸需要被改变,变为patch_size
patches = np.array([transform.resize(patch, patch_size) for patch in patches]) # 改变图片尺寸resize
# print('patches.shape', patches.shape, 'scale:', scale) # (N*patch_size)维
return patches


image = color.rgb2gray(data.chelsea()) # color.rgb2gray(): RGB转为灰度图; data.chelsea()代表小猫切尔西
print('feature.hog(image, visualize=True):\n', feature.hog(image, visualize=True)) # 输入图像, visualize:是否输出HOG image梯度图
hog_vec, hog_vis = feature.hog(image, visualize=True)
fig, ax = plt.subplots(1, 2, figsize=(12, 6), subplot_kw=dict(xticks=[], yticks=[]))
ax[0].imshow(image, cmap='gray')
print('image.shape: ', image.shape)
ax[0].set_title('input image')
ax[1].imshow(hog_vis)
print('hog_vis.shape: ', hog_vis.shape)
ax[1].set_title('visualization of HOG features')

faces = fetch_lfw_people()
positive_patches = faces.images # 获取含有人脸的图片作为正训练样本
print('positive_patches.shape:', positive_patches.shape)
imgs_to_use = ['camera', 'text', 'coins', 'moon', 'page', 'clock', 'immunohistochemistry', 'chelsea',
'coffee', 'hubble_deep_field']
# 把这些主题的照片都转换成灰度图
# print('getattr(data, name)', getattr(data, imgs_to_use[0]))
images = [color.rgb2gray(getattr(data, name)()) for name in imgs_to_use] # getattr(data, name)返回data对象的一个name属性,是函数对象
# 对所有负训练对象的图片做抽出缩略图操作,化为和正训练对象一样尺寸大小
# np.vstack()能去除冗余维度
negative_patches = np.vstack([extract_patches(im, 1000, positive_patches[0].shape, scale) for im in images for scale in [0.5, 1.0, 2.0]])
print('negative_patches.shape:', negative_patches.shape)

fig2, ax2 = plt.subplots(6, 10)
for i, axi in enumerate(ax2.flat):
axi.imshow(negative_patches[500 * i], cmap='gray')
axi.axis('off')

X_train = np.array([feature.hog(im) for im in chain(positive_patches, negative_patches)]) # 将正负样本组合,计算HOG特征
y_train = np.zeros(X_train.shape[0]) # 用0填充X_train样本数作为长度的数组
# print('X_train.shape:\n', X_train.shape)
# print('positive_patches.shape:\n', positive_patches.shape)
y_train[:positive_patches.shape[0]] = 1 # 设开始正样本结果为1
# print('X_train.shape: ', X_train.shape)
# cv的意思是验证5次结果
print('cross_val_score(GaussianNB(), X_train, y_train):', cross_val_score(GaussianNB(), X_train, y_train, cv=3))
grid = GridSearchCV(LinearSVC(), {'C': [0.0625, 0.125, 0.25, 0.5]}, cv=3)
grid.fit(X_train, y_train)
print('grid.best_score_: ', grid.best_score_)
print('grid.best_params_: ', grid.best_params_)
# 用最优参数得到最优评估器
model = grid.best_estimator_
model.fit(X_train, y_train)
model.fit(X_train, y_train)

fig3, ax3 = plt.subplots()
test_image = skimage.data.astronaut() # 给一个航天员作为未知新图输入
test_image = skimage.color.rgb2gray(test_image)
test_image = skimage.transform.rescale(test_image, 0.5) # 缩小到0.5倍
test_image = test_image[:160, 40:180] # 改成适应学习的尺寸
plt.imshow(test_image, cmap='gray')
plt.axis('off')
print('test_image.shape:', test_image.shape)
indices, patches = zip(*sliding_window(test_image, positive_patches[0].shape)) # indices:赋值矩形左下角坐标,patches:方框们
patches_hog = np.array([feature.hog(patch) for patch in patches]) # 计算生成器产生的HOG特征
print('patches_hog.shape:', patches_hog.shape)

labels = model.predict(patches_hog) # 预测有HOG特征的图
print('The total number of the pictures with human faces is: ', labels.sum()) # 这幅图能被确定到的人脸方框数量

fig4, ax4 = plt.subplots()
ax4.imshow(test_image, cmap='gray')
ax4.axis('off')

Ni, Nj = (positive_patches[0]).shape # 高,宽
indices = np.array(indices)

for i, j in indices[labels == 1]:
ax4.add_patch(plt.Rectangle((j, i), Nj, Ni, edgecolor='red', alpha=0.3, lw=2, facecolor='none'))
plt.show()

留下评论

通过 WordPress.com 设计一个这样的站点
从这里开始