双峰阈值分割法提取人眼
人眼区域分割(1)初步通过求人脸的灰度投影曲线,得到人脸矩阵从行角度变化的规律:波谷一定包含人眼的部分,波峰到波谷的阶跃最大的部分一般为眼睛到鼻尖的部分。
思路:
通过人脸的灰度变化规律提取包含人眼部分的ROI图片,此时眼睛作为前景,而皮肤作为背景,可通过双峰找到阈值来分割ROI图片,则以最大限度保留人眼的部分。
##步骤:
1. 提取ROI图片
下图为人眼的灰度投影曲线(已滤波后),红色为波峰,黑色为波谷。同时也可较明显的说明人脸灰度变化的规律。则选定第一个出现的波峰M,选定与波谷阶跃最大的波峰为第二个点N,这两个点对应的横坐标为将提取的人眼矩阵的行坐标。
通过上述处理可以得到ROI图片如下图,该方法试验了一定数量的图片截取效果比较好,前提是要对曲线进行正确的滤波,从而滤过小幅波动,影响波峰波谷的确定。这里采用的滤波为高斯滤波。
此为我选择的滤波模板
sigma=5;
window=double(uint8(3*sigma)2+1);%窗口大小一半为3sigma
H=fspecial(‘gaussian’,window,sigma);
2. 确定双峰分割的阈值
这里想利用双峰确定分割图片的阈值,双峰确定阈值的基本原理是:灰度图片前景和背景相差明显,则会在灰度直方图上呈现明显的双峰,而根据双峰中的波谷则可以确定分割前景和背景的阈值,但其实在过程中发现会有许多因素影响如眼镜,以及头发的干扰可能不能准确的说ROI图片为明显的前景与背景区分明显的图片了,但这里试着写一下这种确定阈值的方法。
2.1求灰度直方图
灰度直方图是灰度级的函数,描述图像中该灰度级的像素个数(或该灰度级像素出现的频率):其横坐标是灰度级,纵坐标表示图像中该灰度级出现的个数(频率)。
####2.2 滤波后求曲线中峰值最高的两个波峰为双峰,求取双峰的波谷为阈值,数学方法即可得到。
将处理好的结果画出来则得到下图,其中红色为灰度函数的曲线,蓝色为高斯滤波的曲线,黄色的为波峰值,蓝色的为找到的波谷值
###3.二值化
根据求出的阈值进行二值化,阈值化将感兴趣的区域即前景像素点设为255,背景设为0.
##总结:
上述方法针对干扰较小如没有很多头发遮挡以及眼镜的情况下,效果还可以,但是这种方法十分依赖曲线滤波的效果。
代码:
对曲线进行求波峰波谷利用matlab里的函数
%对ROI图进行灰度直方图计算,从灰度直方图中得到固定阈值的信息,从而进行阈值化
clear;
close all;
% filestring='zlroi\';
% filestr=dir([filestring,'*.png']);
% objstring='zlbw\';
% for numofimg=1:length(filestr)
% imgname=[filestring,filestr(numofimg).name];
% ROI=imread(imgname);
ROI=imread('ROI\2.jpg');
MedROI=medfilt2(ROI,[9,9]);
[row,col]=size(MedROI);
figure;
imshow(MedROI);
title('ROI');
%出现多峰,则显然所选的阈值不准确
for k=0:255%下标索引必须为正整数类型或逻辑类型
y(k+1)=0;
for i=1:row
for j=1:col
if(MedROI(i,j)==k)
y(k+1)=y(k+1)+1;
end
end
end
end
x=0:1:255;
%求波峰之间的波谷效果不好
sigma=4;
window=double(uint8(3*sigma)*2+1);%窗口大小一半为3*sigma
H=fspecial('gaussian',window,sigma);
G=imfilter(y,H,'replicate');%高斯滤波
[pks,locs] = findpeaks(G);
temp=pks;
[maxpeak,maxloc]=max(temp);
temp(maxloc)=0;
[maxsec,maxsecloc]=max(temp);
new=zeros(1,255);
a=locs(maxloc);
b=locs(maxsecloc);
if(a>b)
new(b:a)=G(b:a);
else new(a:b)=G(a:b);
end
[min,minloc]=findpeaks(-new);
[minpeak,minpeakloc]=max(min);
choice=minloc(minpeakloc);
figure;
title('灰度直方图');
plot(x,y,'r');%画出未过滤的直方图
hold on;
plot(x,G,'b');%画出已经过滤的直方图
hold on;
plot(locs,pks,'yellow*');%用d标出已经过滤的峰值
plot(1:255,new,'black')%画出截取的两个峰值的之间的曲线
plot(choice,y(choice),'blue*');%画出截取的曲线的波谷
%阈值处理
for i=1:row
for j=1:col
if(MedROI(i,j)>choice)MedROI(i,j)=0;
else MedROI(i,j)=255;
end
end
end
%imwrite(MedROI,[objstring,num2str(numofimg),'.png']);
figure;
title('二值化图像');
imshow(MedROI);
%end
%还要进行腐蚀膨胀
%
% morgh=bwmorph(MedROI,'dilate',2);
% figure;
% imshow(morgh);
% title('腐蚀膨胀');
% figure;
% contour=bwperim(morgh);
% imshow(contour);
%
% title('轮廓');
%中值滤波不行参数过大效果直线
% x=0:1:255;
% y=medfilt2(y,[4,4]);
% plot(x,y,'r');
%对灰度函数图进行线性拟合,曲线拟合阶数不能过高,越高反而误差越大,而且阶数不能超过255
% x=1:1:256;
% figure;
% plot(x,y,'r');
% title('灰度函数曲线图');
% % for i=2:2:256
% % fit(i/2)=y(i)+y(i-1);
% % end
% [p,s]=polyfit(x,y,23);
% sum=polyval(p,x,1);
% figure;
% plot(x,sum,'blue');
% title('灰度函数曲线图');
% % sum=0;
% % for i=1:46
% % sum=sum+p(i)*y(i);
% % end
##结论:
双峰滤波法还是更适合于两个峰明显突出,而且双峰之间有明显的平缓的波谷。