基于相关系数的人脸图像中的人眼检测

原理

模板匹配法:

模板就是一副已知的小图像,而模板匹配就是在一副大图像中搜寻目标,已知该图中有要找的目标,且该目标同模板有相同的尺寸、方向和图像元素,通过一定的算法可以在图中找到目标,确定其坐标位置。

高速模板匹配法:

可以改进上面的方法,有几种改进方式。

  1. 序贯相似性检测SSDA法: 在模板和图像进行比对过程中,若两者差异已经超过了某个阈值,就直接进行下一次匹配。
  2. 粗精检索结合法: 粗检索:每次模板移动若干个像素,而不是一次只移动一个像素,确定出大致范围。缺点是有可能漏掉最佳匹配区域。 精检索:粗检索找出大致范围后,在范围内每次移动一个像素进行匹配
  3. 高精度定位的模板匹配: 一般的图像中有较强的自相关性,进行模板匹配计算的相似度在以对象物存在的地方为中心形成平缓的峰。这样,即使模板匹配时从图像对象物的真实位置稍微离开一点,也表现出相当高的相似度。上面介绍的粗精检索高速化恰好利用了这一点。但为了求得对象物在图像中的精确位置,总希望相似度分布尽可能尖锐一些。为了达到这一目的,人们提出基于图案轮廓的特征匹配方法。图案轮廓的匹配与一般的匹配法比较,相似度表现出更尖锐的分布,从而利于精确定位。

两个矩阵 $A,B$ 的相关性可用下面式子表示。 \(r=\frac{\sum_{m} \sum_{n}(A_{m n}-\bar{A})(B_{m n}-\bar{B})}{\sqrt{\left(\sum_{m} \sum_{n}(A_{m n}-\bar{A})^{2}\right)\left(\sum_{m} \sum_{n}(B_{m n}-\bar{B})^{2}\right.})}\) 上述式子可以用 $matlab$ 中的 $corr2(A,B)$ 函数实现。

根据模板图像和原图像比对相关系数可以确定眼睛的大致位置。下一步要准确确定瞳孔的位置,对已经识别的区域做以下步骤

  1. 均衡化,尽可能的减少环境光的影响。
  2. 二值化,将瞳孔区域灰度值变为255,其余部分灰度值为0。经过多次尝试,选择 25 为阈值时效果较好。
  3. 平滑处理,二值化后的图像不够理想,常有瞳孔部分外的小区域被保留,利用中值滤波即可,多次滤波后效果更好。
  4. 确定瞳孔位置,在平滑后的图像中找一个方差最小的位置。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
clear all;
close all;

f = imread('./img/test.jpg');
f = rgb2gray(f);
f = Identify_eye(f,left_eye,right_eye);
figure, imshow(f);

function [out] = Identify_eye(f, t, t2) % 传入图像和模板
    f = imresize(f,[200,150]);
    [J,K] = size(t); [J2,K2] = size(t2);
    [x,y] = Location(f,t);
    img = Draw_Eye_L(f, x, y, J, K);
    img = Draw_Pupil(img, x, y, J, K);
    
    [x2,y2] = Location(f,t2);
    img = Draw_Eye_L(img, x2, y2, J2, K2);
    img = Draw_Pupil(img, x2, y2, J2, K2);
    
    out = img;
end
function [x,y] = Location(f,t) % 定位眼睛坐标
    [M,N] = size(f); [J,K] = size(t);
    R = zeros(M-J+1,N-K+1);
    for x=1:M-J+1
        for y=1:N-K+1
            R(x,y) = corr2(f(x:x+J-1,y:y+K-1),t);
        end
    end
    [x,y] = find(R == max(max(R)), 1);
end
function [out] = Draw_Eye_L(a, x, y, M, N)
    x1 = x+M-1; y1 = y+N-1;
    a(x:x1,y) = 255; a(x:x1,y1) = 255;
    a(x, y:y1) = 255; a(x1, y:y1) = 255;
    out = a;
end
function [out] = Draw_Pupil(img, x, y, M, N) % 定位瞳孔
    eye = img(x:x+M-1, y:y+N-1);
    eye = histeq(eye);
    eye = medfilt2(medfilt2(imresize(imbinarize(eye, 25),1), [2,2]), [2,2]);
    eye(M-1:M, N-1:N) = 255;
    index = zeros(M,N);
    mn = inf;
    for i=1:M
        for j=1:N
            for x0=1:M
                for y0=1:N
                    index(i,j) = index(i,j) + (eye(x0,y0)==255)*((x0-i)^2+(y0-j)^2);
                end
            end
            if(index(i,j) < mn)
                mn = index(i,j);
                x1 = i; y1 = j;
            end
        end
    end
    x = x + x1 - 1; y = y + y1 - 1;
    img(x-1:x+1,y) = 255; img(x,y-1:y+1) = 255;
    out = img;
end
function [out] = imbinarize(img, D0) % 二值化
    [M, N] = size(img); out = zeros(M,N);
    for i=1:M
        for j=1:N
            if (img(i,j) < D0)
                out(i,j) = 0;
            else 
                out(i,j) = 255;
            end
        end
    end
end
# 使用单$作为行内数学公式分界符