一、肤色分析(skin.m)
Anil K.Jain提出的基于YCbCr颜色空间的肤色模型,根据当前点的Cb Cr值判断是否为肤色。
- % Anil K.Jain提出的基于YCbCr颜色空间的肤色模型
- % 根据当前点的Cb Cr值判断是否为肤色
- function result = skin(Y,Cb,Cr)
- % 参数
- a = 25.39;
- b = 14.03;
- ecx = 1.60;
- ecy = 2.41;
- sita = 2.53;
- cx = 109.38;
- cy = 152.02;
- xishu = [cos(sita) sin(sita);-sin(sita) cos(sita)];
- % 如果亮度大于230,则将长短轴同时扩大为原来的1.1倍
- if(Y > 230)
- a = 1.1*a;
- b = 1.1*b;
- end
- % 根据公式进行计算
- Cb = double(Cb);
- Cr = double(Cr);
- t = [(Cb-cx);(Cr-cy)];
- temp = xishu*t;
- value = (temp(1) - ecx)^2/a^2 + (temp(2) - ecy)^2/b^2;
- % 大于1则不是肤色,返回0;否则为肤色,返回1
- if value > 1
- result = 0;
- else
- result = 1;
- end
二、眼睛粗略定位(findeye.m)
- % 判断二值图像中是否含有可能是眼睛的块
- % bImage----二值图像
- % x---------矩形左上角顶点X坐标
- % y---------矩形左上角顶点Y坐标
- % w---------矩形宽度
- % h---------矩形长度
- % 如果有则返回值eye等于1,否则为0
- function eye = findeye(bImage,x,y,w,h)
- % 根据矩形相关属性得到二值图像中矩形区域中的数据
- % 存放矩形区域二值图像信息
- part = zeros(h,w);
- % 二值化
- for i = y:(y+h)
- for j = x:(x+w)
- if bImage(i,j) == 0
- part(i-y+1,j-x+1) = 255;
- else
- part(i-y+1,j-x+1) = 0;
- end
- end
- end
- [L,num] = bwlabel(part,8);
- % 如果区域中有两个以上的矩形则认为有眼睛
- if num < 2
- eye = 0;
- else
- eye = 1;
- end
三、人脸检测(facedetection.m)
- function facedetection(img_name)
- % 读取RGB图像
- I = imread(img_name);
- % 转换为灰度图像
- gray = rgb2gray(I);
- % 将图像转化为YCbCr颜色空间
- YCbCr = rgb2ycbcr(I);
- % 获得图像宽度和高度
- heigth = size(gray,1);
- width = size(gray,2);
- % 根据肤色模型将图像二值化
- for i = 1:heigth
- for j = 1:width
- Y = YCbCr(i,j,1);
- Cb = YCbCr(i,j,2);
- Cr = YCbCr(i,j,3);
- if(Y < 80)
- gray(i,j) = 0;
- else
- if(skin(Y,Cb,Cr) == 1)
- gray(i,j) = 255;
- else
- gray(i,j) = 0;
- end
- end
- end
- end
- % 二值图像形态学处理
- SE=strel('arbitrary',eye(5));
- %gray = bwmorph(gray,'erode');
- % imopen先腐蚀再膨胀
- gray = imopen(gray,SE);
- % imclose先膨胀再腐蚀
- %gray = imclose(gray,SE);
- imshow(gray);
- % 取出图片中所有包含白色区域的最小矩形
- [L,num] = bwlabel(gray,8);
- STATS = regionprops(L,'BoundingBox');
- % 存放经过筛选以后得到的所有矩形块
- n = 1;
- result = zeros(n,4);
- figure,imshow(I);
- hold on;
- for i = 1:num
- box = STATS(i).BoundingBox;
- x = box(1); %矩形坐标x
- y = box(2); %矩形坐标y
- w = box(3); %矩形宽度w
- h = box(4); %矩形高度h
- % 宽度和高度的比例
- ratio = h/w;
- ux = uint8(x);
- uy = uint8(y);
- if ux > 1
- ux = ux - 1;
- end
- if uy > 1
- uy = uy - 1;
- end
- % 可能是人脸区域的矩形应满足以下条件:
- % 1、高度和宽度必须都大于20,且矩形面积大于400
- % 2、高度和宽度比率应该在范围(0.6,2)内
- % 3、函数findeye返回值为1
- if w < 20 || h < 20 || w*h < 400
- continue
- elseif ratio < 2 && ratio > 0.6 && findeye(gray,ux,uy,w,h) == 1
- % 记录可能为人脸的矩形区域
- result(n,:) = [ux uy w h];
- n = n+1;
- end
- end
- % 对可能是人脸的区域进行标记
- if size(result,1) == 1 && result(1,1) > 0
- rectangle('Position',[result(1,1),result(1,2),result(1,3),result(1,4)],'EdgeColor','r');
- else
- % 如果满足条件的矩形区域大于1则再根据其他信息进行筛选
- for m = 1:size(result,1)
- m1 = result(m,1);
- m2 = result(m,2);
- m3 = result(m,3);
- m4 = result(m,4);
- % 标记最终的人脸区域
- if m1 + m3 < width && m2 + m4 < heigth
- rectangle('Position',[m1,m2,m3,m4],'EdgeColor','r');
- end
- end
- end
四、主函数(main.m)
- %清理窗口
- close all
- clear all
- clc
- % 输入图像名字
- img_name = input('请输入图像名字(图像必须为RGB图像,输入0结束):','s');
- % 当输入0时结束
- while ~strcmp(img_name,'0')
- % 进行人脸识别
- facedetection(img_name);
- img_name = input('请输入图像名字(图像必须为RGB图像,输入0结束):','s');
- end