首先说明一下,这个项目并不是博主在实验室负责的项目,而是博主的一门两学分的课的大作业(张学工老师的模式识别基础,有兴趣的可以百度一下),所以并没有投入太多时间去弄,还有很多地方可以改进,后文会陆续提到,也会指明改进的方法。

然后博主只是个大三的学生,实现的一些不足还希望多包涵。

这个检测的程序主要是针对多人大图像的人脸检测(30-100人,1000*2000pixel以上),博主用一张1800*3600的图片在各个人脸检测的开源API上试了一下,检测率基本都是零,没错,是零。正常的API不会考虑如此大的图像和如此小的人脸,这正是这个作业所需要完成的工作。

先说几篇主要的参考文献:

(1) Efficient Non-Maximum Suppression,2006 ICPR.这篇论文主要的工作是提出了一种高效的非极大值抑制算法(NMS),本项目中,将利用此算法合并重复窗口(Bounding Box)。(2) Histograms of Oriented Gradients for Human Detection, 2005,CVPR这篇论文的主要工作是提出了HoG特征,并将其用于行人检测(HoG+SVM),取得了很好的效果,引用量5000+。(3) Aggregate Channel Features for Multi-view Face Detection,2014,IJCB这篇论文的主要工作时提出基于ACF(多通道)特征的人脸检测。这个团队在2015年发表了另一篇论文:A Convolutional Neural Network Combined with Aggregate Channel Feature for Face Detection,这篇是在14年的基础上加以改进的,在多个库上达到state-of-the-art。(4) Fast Feature Pyramids for Object Detection,2014,PAMI这篇论文的主要工作是分析论证了不同尺度下特征的联系。大致思想是,已知这一个尺度上的各个特征,就可以大致估计出相邻尺度上的各个特征,这样就不必将每个尺度都计算一遍,因此可以很大程度地加速程序的运行。论文中提出了ACF特征和ICF特征,并加以分析和对比。

论文内容很多,在此就不一一详释了。主要说一下本项目的大体思路:

通过调研相关文献,得知在人脸检测方面最为著名、应用最为广泛的方法为VJ模型,其主要思想是通过Adaboost分类器结合Harr特征进行人脸检测。但是这种方法的检测效果、系统的稳定性、系统的效率等诸多方面并不能令人满意。

随着研究的深入,越来越多的方法被提出,目前最为成功的方法是通过卷积神经网络进行人脸检测,即CNN。但是卷积神经网络形式多样,需要通过大量的样本和实验来确定最佳的网络结构,出于对项目完成时间的考虑,采取了一种折中的办法:

参考14年的论文 Aggregate Channel Features for Multi-view Face Detection 加以实现。

实现的大致思路:

(1)训练:将正、负样本归一化到80*80(负样本是负样本原图像随机选取的80*80的区域)。提取ACF特征(RGB,梯度直方图(HSV),HoG(HSV),共10个通道),通过软级联Adaboost(深度为2的决策树,个数分别为32,128,512,2048)进行训练,得到训练模型。(2)测试:对原图像进行尺度缩放/扩大,对每个80*80的区域(步长需设定)进行特征提取,通过训练得到的Adaboost模型进行分类。(3)工作展望:在 A Convolutional Neural Network Combined with Aggregate Channel Feature for Face Detection 中,是将以上的结果作为CNN的输入,进行进一步的细分类,可以达到更好的效果。

理论上来讲这种实现的方法可以达到42FPS的速度,但是由于第四篇论文博主还没太搞清楚,代码也没来得及写,所以目前版本的速度很慢,好在老师并不要求运行时间(毕竟我们不是搞优化的=。=)。

代码比较多,这里给出一些比较关键的实现(以下省略的软级联Adaboost,而改用最基本的决策树Adaboost)。

    function featureImag = FaceDetectionImage(RGBoriginalImag)
% 获得原图像的相应十幅特征图
% 输入:原图像,RGB
% 输出:特征图像:m*n*10
% HSV+RGB+RGB
% color:HSV
% gradMag:RGB
% gradHist:RGB
%%
featureImag = zeros(floor(size(RGBoriginalImag, 1)/4), floor(size(RGBoriginalImag, 2)/4), 10, 'single');
% 颜色特征
%原始RGB图像
RGBoriginalImag = im2single(RGBoriginalImag);
%rgb转hsv
HSVoriginalImag = rgb2hsv(RGBoriginalImag);
featureImag(:,:,1) = subSampling(HSVoriginalImag(:,:,1), 4);
featureImag(:,:,2) = subSampling(HSVoriginalImag(:,:,2), 4);
featureImag(:,:,3) = subSampling(HSVoriginalImag(:,:,3), 4);
%%
% 梯度特征
[M, O] = gradientMag(RGBoriginalImag, [], [], [], []);
featureImag(:,:,4) = subSampling(M, 4);
% figure;
%  imshow(gmagSubSampling);
%%
% HoG特征
% [M,O] = gradientMag(RGBoriginalImag, 3);
featureImag(:,:,5:10)=gradientHist(M,O,4,6);
% figure; montage2(H1);
function vector = getDetectionVector(featureImag, ii, jj)
% 输入:特征图:m*n*10
%      起始位置(ii, jj)
%输出:特征图对应的特征向量[row,column,~] = size(featureImag);
% 将特征图归一化为长宽均为20的倍数
divideFeatureImage = mat2cell(featureImag(ii:floor((row-ii+1)/20)*20+ii-1, jj:floor((column-jj+1)/20)*20+jj-1, :), ...ones(1,floor((row-ii+1)/20))*20, ones(1,floor((column-jj+1)/20))*20, ones(1,1)*10);
% size(imgArray) = [20,20,10,1204]
imgArray  =cell2array(divideFeatureImage);
% [1024,4000]
vector = reshape(permute(imgArray,[4,1,2,3]), size(imgArray,4), 4000);
    function pick = getBoundingBoxPick(boxes,overlap, thres)
% 输入:
%   boxes : n*5,i1,j1,i2,j2,score
%   overlap : 阈值
% 输出:
%   pick : 保留下来的坐标
if isempty(boxes)pick = [];
else% 获得每个box的坐标x1 = boxes(:,1);  y1 = boxes(:,2);x2 = boxes(:,3);  y2 = boxes(:,4);%获得每个box的分数boxesScore = boxes(:,end);boxesArea = (x2-x1+1).*(y2-y1+1);maxScore = max(boxesScore);%将分数从低到高排序[~,I] = sort(boxesScore);pick = [];%判断I是否非空while ~isempty(I)%获取I中最后的元素,也就是分数最高的box的下标last = length(I);i = I(last);%存入pick中,作为返回值pick = [pick; i];% 由于已经存入pick中了,所以需要抑制掉suppress = last;% 计算重叠部分for pos = 1:last-1j = I(pos);if boxesScore(j) < maxScore*thressuppress = [suppress; pos];end;% 获取坐标xx1 = max(x1(i), x1(j));yy1 = max(y1(i), y1(j));xx2 = min(x2(i), x2(j));yy2 = min(y2(i), y2(j));% 计算矩形区域的长和宽w = xx2-xx1+1;h = yy2-yy1+1;if w > 0 && h > 0% 计算重叠比例o = w * h / min(boxesArea(i),boxesArea(j));% 如果重叠比例大于阈值,则抑制if o > overlapsuppress = [suppress; pos];endendendI(suppress) = [];end
end
     function [totalBoxes, totalBoxCount] = faceDectionTest(Image, winSize, divideStep)
%%
% 检测主函数
load m32.mat
load m128.mat
load m512.mat
load m2048.mat%%
totalBoxes = zeros(10000000, 5, 'single');
totalBoxCount = 1;% 将输入图片归一化到合适尺寸,使得滑窗大小为20*20
% scale是归一尺度
scale = 20/winSize;
% 图像归一化originalImage = imresize(Image, scale, 'nearest');
% originalImage = imresize(Image, scale, 'bilinear');
detectionImage = FaceDetectionImage(originalImage);[imageRow, imageColumn, ~] = size(detectionImage);step = ceil(winSize/divideStep);for i = 1:step:winSizeifor j = 1:step:winSize%得到特征向量imgVector = double(getDetectionVector(detectionImage, i, j));%获得每个向量相应的分数vectorScore = adaBoostApply(imgVector, m2048);%获得分数大于0的向量的索引ind = find(vectorScore>0);[boxes, boxesCount] = getBoundingBox(ind, vectorScore, imageRow, imageColumn, winSize, i, j);totalBoxes(totalBoxCount:totalBoxCount+boxesCount-1, :) = boxes(1:boxesCount, :);totalBoxCount = totalBoxCount+boxesCount;end
end
totalBoxCount = totalBoxCount-1;
    figure;
Image = imread('./test/test (6).jpg');
Image = im2single(Image);
winSize = [12, 13, 15, 17, 20, 23, 27, 31, 35, 40, 47, 54, 62, 71];
% winSize = [13,16,20];
divideStep = 4;
totalBoxes = zeros(10000000, 5, 'single');
totalBoxCount = 1;for i = 1:length(winSize)ww = winSize(i);[boxes, boxesCount] = faceDectionTest(Image, ww, divideStep);totalBoxes(totalBoxCount:totalBoxCount+boxesCount-1, :) = boxes(1:boxesCount, :);totalBoxCount = totalBoxCount+boxesCount;
end
totalBoxCount = totalBoxCount-1;Boxes = totalBoxes(1:totalBoxCount,:);pick = getBoundingBoxPick(Boxes,0.25, 0.45);bb = Boxes(pick,:);Image = boxesDraw(Image, bb, size(bb, 1));
imshow(Image);

给出几张测试结果:

红框和绿框是博主尝试做了一下性别分类,但是效果很不好。

基于ACF多通道特征的人脸检测——从原理到实现相关推荐

  1. opencv实战3: CascadeClassifier+Haar特征进行人脸检测

    1.级联分类器CascadeClassifier OpenCV官方文档:https://docs.opencv.org/3.4.3/d5/d54/group__objdetect.html 分类器: ...

  2. 基于Pyramidbox实现的大规模人脸检测

    前言 今天来水一片文章,基于开源的Pyramidbox大规模人脸检测编写的PaddlePaddle教程,为了方便训练预测,本教程做了一定的修改.这个模型虽然大,但是符合大规模人群中也可以准确地检测到人 ...

  3. 基于Haar分类器的OpenCV人脸检测实例

    一.人脸的Haar特征分类器是什么 人脸的Haar特征分类器就是一个XML文件,该文件中会描述人脸的Haar特征值.当然Haar特征的用途可不止可以用来描述人脸这一种,用来描述眼睛,嘴唇或是其它物体也 ...

  4. OpenCV3实现人脸识别(一)——基于OpenCV3级联分类器实现人脸检测与眼睛检测

    前言 1.OpenCV官方训练好的人脸和眼睛的级联分类器,3.30的版本都放在opencv\sources\data这个文件夹下,在OpenCV这个文件夹中,主要有 Haar特征 和 LBP特征进行人 ...

  5. python 视频人脸替换_Python基于OpenCV实现视频的人脸检测

    本文实例为大家分享了基于OpenCV实现视频的人脸检测具体代码,供大家参考,具体内容如下 前提条件 1.摄像头 2.已安装Python和OpenCV3 代码 import cv2 import sys ...

  6. python视频人脸检测_Python基于OpenCV实现视频的人脸检测

    本文实例为大家分享了基于OpenCV实现视频的人脸检测具体代码,供大家参考,具体内容如下 前提条件 1.摄像头 2.已安装Python和OpenCV3 代码 import cv2 import sys ...

  7. 基于Android平台的简易人脸检测库

    代码地址如下: http://www.demodashi.com/demo/12135.html ViseFace 简易人脸检测库,不依赖三方库,可快速接入人脸检测功能. 项目依赖:compile ' ...

  8. 基于肤色高斯概率模型的人脸检测

    肤色高斯概率模型,主要将颜色空间从RGB转换为YCrCb,计算肤色的相似度,确定根据概率阈值筛选出肤色区域.但高斯概率模型中肤色均值及协方差矩阵需要提前确定,并且肤色均值对检测结果影响非常大,需要根据 ...

  9. 基于OpenCV的视频处理 - 人脸检测

    一个不知名大学生,江湖人称菜狗 original author: jacky Li Email : 3435673055@qq.com  Time of completion:2023.2.7 Las ...

最新文章

  1. java串口发送16进制_串口发送数据——字符串发送与十六进制发送的区别
  2. Maven快照机制(SNAPSHOT)
  3. 关于SAP S/4HANA里ABAP源代码管理功能的增强
  4. 图数据集之cora数据集介绍 --- 适用于GCN任务
  5. throwable_您想了解的所有Throwable
  6. 特斯拉联合苹果发难 要对小鹏汽车“窃密”员工动手了...
  7. linux时间和win10差8小时,[转载]Ubuntu16.04与Win10时间差8个小时问题解决方案
  8. ZeroMQ设置超时等待
  9. fseek函数、ftell函数、rewind函数详解
  10. cmd运行javac解析中文乱码
  11. 简洁UI好玩的文字转换emoji表情微信小程序源码下载支持句子词语转换
  12. 360视频:二十面体投影ISP
  13. android手机备份恢复出厂设置,安卓手机恢复出厂设置在哪里?史上最全版恢复过程详解...
  14. Problem : 救公主续
  15. windows屏幕分辨率获取方式
  16. JavaScript事件代理(事件委托)
  17. Composer 的常用命令
  18. 全网最详细金融APP测试功能点-测试用例,详细整理(全)
  19. 星光不问赶路人,时光不负有心人。
  20. Activity左边滑出,右边滑入的动画切换

热门文章

  1. 全网首款能模拟苹果IOS系统自带Safari浏览器的工具来了
  2. bugku 把猪困在猪圈里
  3. TFB cas:223569-31-1,聚合物光电材料
  4. 用友通新建账套显示不能登入到服务器,用友通打不开,出现登录失败
  5. YYText实现文本与下划线,删除线偏移
  6. 【计导非课系列】绪言——什么是“计导非课”系列?
  7. php while 无限循环,php - 在PAMI中发起呼叫-无限while循环 - 堆栈内存溢出
  8. 网站域名服务器加密,网站实现全站https加密可以防止DNS劫持吗?
  9. Linux -- 项目服务部署学习
  10. java身份证格式强校验