MATLAB 图像处理 简单人脸检测(详细,你上你也行)

2023-11-02

1.人脸检测原理框图

整体思路是寻找图片中最大的连通域,将其认定为人脸。

第一个环节均值滤波,是为了减弱图像的相关细节部分,以免毛刺影响后期连通域的形成,二值化方便形态学处理,减少运算量。考虑到人脸有黑人和白人黄种人,黑人肤色较深,在二值化之后面部区域不容易形成较大的连通域,如果采取形态学边界提取的办法,就可以避免这个问题,形态学边界提取,只要结构元素够大,也可以形成较大的封闭连通域。

然后就是纵向闭合操作,这一步我选择采用竖向长条状的结构元素进行闭合运算,因为人的脸部和颈部以及头发和衣物等等都是纵向分布的,在进行形态学边界提取的时候,容易将这些靠近的成分割裂开来,这对连通域的判断极为不利,所以用竖向长条状的结构元素在在纵向进行闭合运算,将脸部上下部的区域重新连接起来。

紧接着我又用横向长条状结构元素进行横向腐蚀运算,这是因为,人的头部以下的身体部分存在有大量连通域的时候,容易对最大连通域的判决产生干扰,又因为下半部分,多半呈纵向分布,通过横向腐蚀可以将这些大块的连通域割裂开来,但是要注意的是,割裂程度不应太大,否则会使得上一步闭合操作丧失意义。

接着,由于背景杂物等因素,同样也会产生大量连通域,这会对最后结果的判决产生干扰,因此要予以剔除。

进行了层层筛选之后,在剩下的连通域里面挑一个最大的连通域,并且尺寸形状满足要求的用矩形框框起来作为人脸检测结果。

2 步骤

2.1 均值滤波

h = ones(9)/81;
I = uint8(conv2(I,h));
figure,imshow(I),title('线性均值滤波')

采用9x9模板进行线性均值滤波,因为后面调用gpuArray()函数转换对输入数据有要求,所以在进行了二维卷积之后重新将数据格式转换成8位无符号整形数据。

2.2 二值化

BW = imbinarize(I);
figure,imshow(BW),title('二值化')

直接调用imbinarize对图像进行二值化

2.3.形态学边界提取

B = ones(21);%结构元素
BW = -imerode(BW,B) + BW;
figure,imshow(BW),title('形态学边界提取')
BW = bwmorph(BW,'thicken');
figure,imshow(BW),title('加粗边界')
BW = not(bwareaopen(not(BW), 300));
figure,imshow(BW),title('把空洞填了')

结构元素采用21x21大小的全1矩阵,先调用imrode()进行腐蚀,再用原图减去腐蚀结果,得到边界。为了让边界更加明显,调用bmworph函数,传入’thicken’参数,意在将边界加粗加厚。最后为了把空洞就是连续的小黑色块填满,调用bwareaopen()函数,该函数是去除面积小于300的白块,为了去除黑块,先调用not(BW)给原来的二值图像取反,去掉取反后面积小于300的白块,再次取反,达到去掉面积小于300的黑块的目的。

2.4 纵向闭合与横向腐蚀

%进行形态学运算
B = strel('line',50,90);
BW = imdilate(BW,B);
BW = imerode(BW,B);
figure,imshow(BW),title('再闭操作之后')
B = strel('line',10,0);
BW = imerode(BW,B);
figure,imshow(BW),title('闭操作之后再腐蚀')
BW = gpuArray(BW);

调用strel()函数生成特定的结构元素,第一步调用strel(‘line’,50,90),意思是调用直线型结构元素,长度为50,角度90度,也就是竖直的长条形结构元素。接着利用B调用imdilate和imerode,先进行膨胀再进行腐蚀完成闭操作运算。下一步,继续生成横向长条形结构元素,进行腐蚀操作,注意这里的结构元素不宜面积太大,长度太长,否则会过度影响上一步的结果

最后为了循环过程中提升运算速度,将数据类型更改为gpuArray(),可以在GPU上进行计算,节省时间。

2.5 消除边界多余连通域

%最小化背景
%细分
div = 10;
r = floor(n1/div);%分成10块 行
c = floor(n2/div);%分成10块 列
x1 = 1;x2 = r;%对应行初始化
s = r*c;%块面积
%判断人脸是否处于图片四周,如果不是就全部弄黑
%figure
for i=1:div
    y1 = 1;y2 = c;%对应列初始化
    for j=1:div
        loc = find(BW(x1:x2,y1:y2)==0);%统计这一块黑色像素的位置
        num = length(loc);
        rate = num*100/s;%统计黑色像素占比
        if (y2<=0.2*div*c||y2>=0.8*div*c)||(x1<=r||x2>=r*div)
            if rate <=100
                BW(x1:x2,y1:y2) = 0;
            end
            %imshow(BW)
        else
            if rate <=25
                BW(x1:x2,y1:y2) = 1;
            end
            %imshow(BW)
        end%下一列
        y1 = y1 + c;
        y2 = y2 + c;
    end%下一行
    x1 = x1 + r;
    x2 = x2 + r;
end

对于周围多余的杂物产生的连通域,我选择先将整幅图像划分为很多小块,对一部分在图像边缘的小块全部置成黑色,对不在边缘的通过计算其中黑色像素比例来判定是否应该全部给成白色。因为图片中央可能还会存在一些细小空洞,这些空洞在每一小块占比不是很大但有可能影响连通性,如果一个小块里面大部分是白色就全部给成白色,方便后期判定最大连通域。

Div是均分比例,我这里设置成10,也就是将整个图像划分成100个小块。r就是在行方向上一个小块占多少像素,c就是在列方向上一个小块有多少像素。用两层循环来遍历每个小块,通过find(x1:x2,y1:y2)==0返回所有满足要求的像素的索引,索引长度就是黑色像素的个数。

通过条件判断是否在边界。


2.6 寻找最大连通域并画框

figure
subplot(1,2,1)
imshow(BW)
title('最终处理')
L = bwlabel(BW,8);%利用belabel函数对8连通域区间进行标号
BB = regionprops(L,'BoundingBox');%得到矩形框,框柱每一个连通域
BB = cell2mat(struct2cell(BB));
[s1,s2] = size(BB);
BB = reshape(BB,4,s1*s2/4)';
pickshape = BB(:,3)./BB(:,4);%
shapeind = BB(0.3<pickshape&pickshape<3,:);%筛选掉尺寸比例不合格
[~,arealind] = max(shapeind(:,3).*shapeind(:,4));
subplot(1,2,2)
imshow(rgb)
hold on
rectangle('Position',[shapeind(arealind,1),shapeind(arealind,2),shapeind(arealind,3),shapeind(arealind,3)],...
    'EdgeColor','g','Linewidth',2)
title('人脸检测')

经过消除边界多余连通域后得到的BW中剩下的连通域内存在着我们需要的那个对应人脸的连通域。一般情况下,对应人脸的那个连通域会是最大的连通域。

调用bwlabel(BW,8)函数给所有连通域标记,其中邻域规则采用8邻域,返回一个被标记过连通域的图像,第k个被标记的连通域所有像素值为k。

调用regionprops(L,’BoundingBox’)函数,传入参数L和’BoundingBox’,该函数用于获取图像的各种属性,传入’BoundingBox’返回的是一个结构体,每一个结构体内都包含了一个能框柱其对应连通域的最小方框。一个方框,用一个序列来描述[x,y,width,height],这个序列包含了方框左上角像素的坐标以及长和宽。

这三条语句,第一条用来将结构体转换成矩阵向量,方便计算。第二行获取这个矩阵的维度。由于BB刚转换成向量的时候,是一个行向量,每4个元素1组对应一个方框。为了后续计算方便,使用reshape()函数,将BB重构成一个矩阵,这个矩阵有4列,每一列对应方框的一个参数,比如坐标,长宽等等。每一行对应一个方框。

第一行计算长宽比,得到的pickshape向量的每一行对应每个方框的长宽比。由于有的方框明显过于扁平或者过于狭长,这种方框应该是要扔掉的。

所以第二行,通过逻辑表达式从BB内筛选出尺寸比例合格的方框,存在shapeind里面。
剩下的尺寸符合要求的方框里面要选出面积最大的那个,最后一行,得到面积最大的方框对应的索引。

把方框画出来。


3 检测结果

图 15rgb图像转换成灰度图像                 图 16线性均值滤波结果

可以看到,均值滤波使得图像变模糊了细节减少

图 17二值化结果                                    图 18形态学边界提取结果

以看到边界被成功提取了出来,在人脸部形成了一个比较大的连通域


可以看到,进行边界加粗和空洞添补之后,眼睛部分的黑块被消除了,这使得脸部连通域更大了

注意观察图片左边的相分离的白块,在纵向闭操作之后连在了一起,同时脸部连通域进一步扩大,然后横向腐蚀在尽量维持脸部连通域大小的情况下减小了图片下方连通域。

可以看到效果还可以。还有其他的测试结果

图 24测试样例

图 25测试样例

图 26测试样例

图 27测试样例

图 28测试样例

图 29测试样例

图 30测试样例

这里注意到,黑人同样也被检测到了

4 完整代码

---%%%完整代码
rgb = imread('f.jpg');
I = rgb2gray(rgb);
[n1,n2] = size(I);
%灰度图
figure,imshow(I),title('灰度图')
tic
h = ones(9)/81;
I = uint8(conv2(I,h));
figure,imshow(I),title('线性均值滤波')
BW = imbinarize(I);
figure,imshow(BW),title('二值化')
B = ones(21);%结构元素
BW = -imerode(BW,B) + BW;
figure,imshow(BW),title('形态学边界提取')
BW = bwmorph(BW,'thicken');
figure,imshow(BW),title('加粗边界')
BW = not(bwareaopen(not(BW), 300));
figure,imshow(BW),title('把空洞填了')
%进行形态学运算
B = strel('line',50,90);
BW = imdilate(BW,B);
BW = imerode(BW,B);
figure,imshow(BW),title('再闭操作之后')
B = strel('line',10,0);
BW = imerode(BW,B);
figure,imshow(BW),title('闭操作之后再腐蚀')
%%BW = gpuArray(BW);%%将数据载入gpu可以加速,电脑不一定支持

%最小化背景
%细分
div = 10;
r = floor(n1/div);%分成10块 行
c = floor(n2/div);%分成10块 列
x1 = 1;x2 = r;%对应行初始化
s = r*c;%块面积
%判断人脸是否处于图片四周,如果不是就全部弄黑
%figure
for i=1:div
    y1 = 1;y2 = c;%对应列初始化
    for j=1:div
        loc = find(BW(x1:x2,y1:y2)==0);%统计这一块黑色像素的位置
        num = length(loc);
        rate = num*100/s;%统计黑色像素占比
        if (y2<=0.2*div*c||y2>=0.8*div*c)||(x1<=r||x2>=r*div)
            if rate <=100
                BW(x1:x2,y1:y2) = 0;
            end
            %imshow(BW)
        else
            if rate <=25
                BW(x1:x2,y1:y2) = 1;
            end
            %imshow(BW)
        end%下一列
        y1 = y1 + c;
        y2 = y2 + c;
    end%下一行
    x1 = x1 + r;
    x2 = x2 + r;
end

figure
subplot(1,2,1)
imshow(BW)
title('最终处理')
L = bwlabel(BW,8);%利用belabel函数对8连通域区间进行标号
BB = regionprops(L,'BoundingBox');%得到矩形框,框柱每一个连通域
BB = cell2mat(struct2cell(BB));
[s1,s2] = size(BB);
BB = reshape(BB,4,s1*s2/4)';
pickshape = BB(:,3)./BB(:,4);%
shapeind = BB(0.3<pickshape&pickshape<3,:);%筛选掉尺寸比例不合格
[~,arealind] = max(shapeind(:,3).*shapeind(:,4));
subplot(1,2,2)
imshow(rgb)
hold on
rectangle('Position',[shapeind(arealind,1),shapeind(arealind,2),shapeind(arealind,3),shapeind(arealind,3)],...
    'EdgeColor','g','Linewidth',2)
title('人脸检测')
toc

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MATLAB 图像处理 简单人脸检测(详细,你上你也行) 的相关文章

  • 黑白随机着色的六角格子

    我正在尝试绘制一个 10 000 x 10 000 随机半黑半白的六边形格子 我不知道如何将该格子的六边形随机填充为黑色和白色 这是我真正想要从这段代码中得到的示例 但我无法做到 https i stack imgur com RkdCw
  • matlab中的正则逻辑回归代码

    我正在尝试正则化 LR 在 matlab 中使用以下公式很简单 成本函数 J theta 1 m sum y i log h x i 1 y i log 1 h x i lambda 2 m sum theta j 梯度 J theta t
  • 如何使用 MATLAB 的 substruct 函数创建表示使用“end”的引用的结构?

    我想使用substruct http www mathworks com help matlab ref substruct html函数创建一个结构体以供使用subsref 目的是使用索引字符串subsref而不是通常的 符号 因为我正在
  • glpk.LPX 向后兼容性?

    较新版本的glpk没有LPXapi 旧包需要它 我如何使用旧包 例如COBRA http opencobra sourceforge net openCOBRA Welcome html 与较新版本的glpk 注意COBRA适用于 MATL
  • “Desort”向量(撤消排序)

    在Matlab中 sort返回排序后的向量和索引向量 显示哪个向量元素已移动到以下位置 v ix sort u Here v是一个包含所有元素的向量u 但已排序 ix是一个向量 显示每个元素的原始位置v in u 使用 Matlab 的语法
  • 检测数据集中线性行为的算法

    我已经发布了一个关于对数据集的一部分进行多项式拟合的算法 https stackoverflow com q 17595932 2320757前一段时间收到一些建议去做我想做的事 但我现在面临另一个问题 我尝试应用答案中建议的想法 我的目标
  • Matlab Builder JA - 将 Matlab 编译成 Java jar - 免费版本?

    请记住 我对 Matlab 一无所知 Matlab Builder JA 允许开发人员构建 Matlab 应用程序并将其导出到 Java jar 中 太棒了 我只需要生成一个 jar 然后就可以从其他 java 代码中使用它 有谁知道单罐包
  • 如何在 MATLAB 中绘制纹理映射三角形?

    我有一个三角形 u v 图像中的坐标 我想在 3D 坐标处绘制这个三角形 X Y Z 与图像中的三角形进行纹理映射 Here u v X Y Z都是具有三个元素的向量 代表三角形的三个角 我有一个非常丑陋 缓慢且令人不满意的解决方案 其中我
  • matlab中求和函数句柄

    Hi我试图对两个函数句柄求和 但它不起作用 例如 y1 x x x y2 x x x 3 x y3 y1 y2 我收到的错误是 对于 function handle 类型的输入参数 未定义函数或方法 plus 这只是一个小例子 实际上我实际
  • 如何知道Matlab中系统命令执行过程中经过的时间?

    我有一个运行系统脚本的 Matlab 代码 该脚本可能会因命令运行而停止 我想知道是否有一种方法可以让程序知道它是否花费了很长时间并执行其他操作 这是代码 tic status cmdout system iperfcmd The prog
  • 将 Matlab 的 datenum 格式转换为 Python

    我刚刚开始从 Matlab 迁移到 Python 2 7 在读取 mat 文件时遇到一些问题 时间信息以 Matlab 的日期数字格式存储 对于那些不熟悉它的人 日期序列号将日历日期表示为自固定基准日期以来已经过去的天数 在 MATLAB
  • 小矩阵乘以大矩阵

    我试图将小矩阵 假设为 2x2 中的每个元素与大矩阵 假设为 4x4 中的每个位置逐个元素相乘 所以我想要 1 2 3 4 1 0 3 0 1 0 1 2 3 4 0 0 0 0 0 0 x 1 2 3 4 1 0 3 0 1 2 3 4
  • 在 MATLAB 2014b 及更高版本中使用画家渲染器进行三角形分割面片

    MATLAB 的新图形引擎 HG2 无法使用画家渲染器正确打印补丁 hist randn 1 1000 colorbar Location SouthOutside print test pdf dpdf 生成的补丁 无论是由hist or
  • Matlab:从一定范围内不重复的随机整数

    我想获得一个包含在范围内且不重复的随机整数的数组 我使用了 randperm 15 3 输出是 8 10 12 这个函数不使用范围 我只想从 10 中随机取值 例如 如果您有统计工具箱 则可以使用randsample https www m
  • 在Matlab中,是否可以终止脚本,但将其所有内部变量保存到工作区?

    我正在运行一个脚本 但它花费的时间太长 所以我想终止该脚本 然而 它计算了很多数据 我理想情况下不想扔掉这些数据 有没有替代方案ctrl C用什么将内部函数变量保存到工作区 理想情况下我正在寻找一个Matlab键盘快捷键如ctrl C 但如
  • 使用循环绘制多个结果

    我想使用 for 循环绘制原始和窗口的结果 10 50 100 全部在一个图中这是我得到的情节 https i stack imgur com wAixM png below is my code Read data in data csv
  • 高斯 RBM 在一个简单的例子上失败了

    我想对具有连续输入变量的受限玻尔兹曼机有一个具体的了解 我正在尝试设计一个最简单的示例 以便可以轻松跟踪行为 所以 就在这里 输入数据是二维的 每个数据点均取自两个对称正态分布 sigma 0 03 之一 其中心间隔良好 15 倍 sigm
  • 如何使用 Mikolajczyk 的特征检测器/描述符评估框架?

    我正在尝试使用事实上的标准评估我的 SURF 描述符实现的正确性Mikolajczyk 等人的框架 阿尔 http www robots ox ac uk vgg research affine 我使用 OpenCV 来检测和描述 SURF
  • 如何从图像中去除颗粒状细节[重复]

    这个问题在这里已经有答案了 我用过adapthisteq以提高前景物体的可见度 然而 这似乎产生了颗粒状的噪点细节 如何从图像中去除这些颗粒状细节 我尝试过高斯模糊imgaussfilt虽然它确实消除了一些颗粒状细节 但图像中细胞的形状变得
  • 错误:超出了程序允许的最大变量大小。使用 sub2ind 时

    请建议如何解决这个问题 nNodes 50400 adj sparse nNodes nNodes adj sub2ind nNodes nNodes ind ind 1 1 ind is a vector of indices Maxim

随机推荐

  • Linux(阿里云)禅道部署

    开源版本下载地址 底部 禅道18 1 禅道开源项目管理软件 本人选择安 Linux一键安装 csdn下载链接 https www zentao net dl zentao 18 1 ZenTaoPMS 18 1 zbox 64 tar gz
  • Windows10 安装Geant4-支持Release/Debug版本

    1 预先下载的软件 数据包 1 安装CMake 2 安装Visual Studio 可在官网安装社区版 免费 3 下载官网 https geant4 web cern ch support download 中的Source File zi
  • 为了在 Windows 11 上启用 IE ,我撸了个修复工具

    网管小贾的博客 www sysadm cc Windows 11 正式版已于前不久官宣发布了 好不好用呢 我想八成的人都是冲着尝鲜去的 所以说好用的不少 说不好用的也是大有人在 对我们来说 不管是真的好用还是真的不好用 那完全是见仁见智的个
  • 生活中哪些地方运用计算机网络,计算机网络技术在生活中应用.doc

    计算机网络技术在生活中应用 计算机网络技术在生活中应用 摘 要 近年来 计算机网络技术得以飞速发展 也在很大程度上改变了人们的生活方式 它可以说是人类发展历程中的新突破 进入二十一世纪之后 社会逐渐向着网络化的方向发展 计算机网络技术逐渐成
  • 2021水流向何处

    只要房价不涨 不用担心钱被稀释 钱不值钱 说白了就是货更加值钱了 货变贵了 这个货可以是白菜萝卜 可以是汽车 也可以是房子 汽车等工业品明显是更加不值钱 变便宜了 白菜萝卜等需要大量纯粹劳动力的货 是变贵了 但是人民工资水平的上涨能够更上它
  • springboot+mybatis+redis+thymeleaf Web项目搭建 开箱即用

    手动搭建了一个springboot mybatis redis thymeleaf的Web后台项目 因此写篇博客记录下搭建的完整过程 文章最后有完整代码地址 首先简单介绍下用到的技术框架及用途 1 springboot框架 项目主体结构 2
  • 简单递归(最大公约数,阶乘)

    include
  • Centos6.8安装glib-2.32.1

    Centos6 8安装glib 2 32 1遇到的问题及解决方法 1 glib 2 32 1下载网址 http ftp gnome org pub gnome sources glib 2 32 glib 2 32 1 tar xz 2 执
  • OpenWrt系统安全改进<三> --- Web UI密码错误控制

    OpenWrt系统安全改进 lt 二 gt 中所做的尝试 是为了增强用户登录的鉴权机制 密码输错三次就禁用用户一段时间 PAM可以实现对用户登录的控制 但是进一步操作中发现WebUI的登录并没有支持PAM 前功尽弃 了解了一下OpenWrt
  • jmeter 安装部署

    1 软件安装 1 1 Windows安装 1 1 1 软件下载 进入官网 http jmeter apache org 直接下载zip包 下载后直接解压 eg我的解压路径如下 D Program Files apache jmeter 5
  • GitHub拉取报错remote: Support for password authentication was removed on August 13, 2021

    问题描述 今天从GitHub上拉取我自己的私有仓库 结果报错说自21年8月13日后不在支持用户名密码方式验证 如图所示 解决方案 通过查看别人博客原博主以及官网阅读 得知可以通过创建个人访问令牌 personal access token
  • 【附源码】Python小游戏 ——开心消消乐

    目录 前言 开发工具 环境搭建 效果展示 选择关卡首页 游戏界面 过关 代码展示 模块导入 主函数 声音类 树类 元素类 数组类 前言 今天主要是给大家拿牌一个小游戏 开心消消乐 看看有没有小伙伴能够通过呀 开发工具 Python版本 3
  • 网络无法访问互联网是什么原因

    很多用户在使用手机或电脑连接网络时 明明可以正常连接 但却无法访问互联网 网络无法访问互联网是什么意思 无法连接到互联网是指当前只可访问本地网络的资源 没办法正常上外网 访问网页 上 QQ 微信等 网络无法访问互联网是什么原因 网络无法访问
  • Python的Logging模块

    1 日志的相关概念 日志是指记录系统或应用程序运行状态 事件和错误信息的文件或数据 在计算机系统中 日志通常用于故障排除 性能分析 安全审计等方面 日志可以记录各种信息 如系统启动和关闭时间 应用程序的运行状态 用户登录和操作记录 网络通信
  • 6.英文字母排序 (20分)

    题目内容 编写一个程序 当输入不超过 个字符组成的英文文字时 计算机将这个句子中的字母按英文字典字母顺序重新排列 排列后的单词的长度要与原始句子中的长度相同 并且要求只对 到 的字母重新排列 其它字符保持原来的状态 输入描述 一个字符串 包
  • python安装程序已停止工作_python.exe已经停止工作

    昨天 我成功地将sip pyqt4和vtk 包括python的绑定 安装在64位windows7虚拟机上 在 但是 当我执行 import vtk 操作时 会弹出一个对话框 import vtk python exe已经停止工作 在 事件查
  • CGAN原理及tensorflow代码

    1 首先说明一下CGAN的意义 GAN的原始模型有很多可以改进的缺点 首当其中就是 模型不可控 从上面对GAN的介绍能够看出 模型以一个随机噪声为输入 显然 我们很难对输出的结构进行控制 例如 使用纯粹的GAN 我们可以训练出一个生成器 输
  • 关于超过js的number类型最大值(9007199254740992),的解决办法

    bug经过 点击修改无法展示信息 修改时调用queryOne 以id long 为值 页面传过去的id 1480042498255640 00 在数据库中该id 148004249825564012 即错误的id 根本原因 js的numbe
  • DPText-DETR: 基于动态点query的场景文本检测,更高更快更鲁棒

    针对场景文本检测任务 近期基于DEtection TRansformer DETR 框架预测控制点的研究工作较为活跃 在基于DETR的检测器中 query的构建方式至关重要 现有方法中较为粗糙的位置先验信息构建导致了较低的训练效率以及性能
  • MATLAB 图像处理 简单人脸检测(详细,你上你也行)

    1 人脸检测原理框图 整体思路是寻找图片中最大的连通域 将其认定为人脸 第一个环节均值滤波 是为了减弱图像的相关细节部分 以免毛刺影响后期连通域的形成 二值化方便形态学处理 减少运算量 考虑到人脸有黑人和白人黄种人 黑人肤色较深 在二值化之