cs231A Homework-4: Face Detection
1. Face Detection with HoG
本节作业主要利用HoG来计算特征,并且作为目标检测的一部分。
1.1 运行SVM训练输出边界盒子
函数:run_detector(im, clf, window_size, cell_size, block_size, nbins, thresh=1)
参数:
- im: 图片
- clf: svm对象,使用
decision_function()
确定对象是否为face - window_size: 滑动窗口的size数组
- cell_size: (cell_size, cell_size)包含pixels
- block_size: (block_size, block_size)包含的cells
- nbins: 直方图的bins
返回值:
- bboxes: (D * 4) 的边界盒子数组【xmin, ymin,width, height】
- scores: 每个边界盒子的SVM scores
实现:
- 使用
compute_hog_features()
计算HoG特征 - 对滑动窗口计算score,每次滑动的步长为n pixels,步长stride = (block_size * cell_size / 2)
- SVM得到的score大于1,就认为窗口为边界盒子
def run_detector(im, clf, window_size, cell_size, block_size, nbins, thresh=1):
H, W = im.shape
win_H, win_W = window_size
stride = int(block_size * cell_size / 2)
# 返回值
bboxes = []
scores = []
# 计算每个窗口是否为face
for i in range(0, W - win_W, stride):
for j in range(0, H - win_H, stride):
bbox = [i, j, win_W, win_H] # 窗口 [xmin ymin width height]
im_bbox = im[j:j+win_H, i: i+win_W]
feature_im = compute_hog_features(im_bbox, cell_size, block_size, nbins) # HoG
score_im = clf.decision_function(feature_im.flatten().reshape(1,-1)) # 先将HoG特征变为vector,然后进行判断是否为face特征
if score_im > thresh:
scores.append(score_im)
bboxes.append(bbox)
# 变换为numpy类型
bboxes = np.array(bboxes)
scores = np.array(scores)
return bboxes, scores
1.2 非最大化约束
在上一步执行的face窗口检测中,可能存在一个face侦测多个窗口的情况,对于每个窗口,都有一个score,因此对于同一个face的窗口,比较score,留下最高的窗口,移除剩下的窗口。
函数: non_max_suppression(bboxes, confidences)
参数:
bboxes:
窗口 (N, 4)- confidences: 每个窗口的SVM confidence信度 (N,1),即score
返回值:
- nmss_bboxes: 非重叠的窗口,即移除弱特征的窗口
实现:
- 首先sort 窗口confidence
- 然后移除重叠的窗口
def non_max_suppression(bboxes, confidences):
nms_bboxs = [] # 返回窗口
# 对confidences 排序
con_idx = np.argsort(-confidences.flatten()) # 从大到小排列
N = bboxes.shape[0]
for i in range(N):
bbox = bboxes[con_idx[i], :] # 一个窗口,[xmin, ymin, width, height]
if i == 0: # 第一个窗口,加入结果序列
nms_bboxs.append(bbox)
else: # 查看当前窗口是否和已有窗口重叠
# 计算窗口中心
cx = (2 * bbox[0] + bbox[2]) / 2
cy = (2 * bbox[1] + bbox[3]) / 2
isOverlap = False
for j in range(len(nms_bboxs)):
xmin, ymin, w, h = nms_bboxs[j][0], nms_bboxs[j][1],\
nms_bboxs[j][2], nms_bboxs[j][3]
xmax, ymax = (xmin + w), (ymin + h)
if xmin <= cx <= xmax and ymin <= cy <= ymax: # 两个窗口重叠
isOverlap = True
break
if not isOverlap: # 没有重叠
nms_bboxs.append(bbox)
nms_bboxs = np.array(nms_bboxs)
return nms_bboxs