• 指纹识别源代码(2)-特征点提取



        上图为上一步拿到的图像预处理之后的细化图。在这个基础之上我们进行下一步操作。
        指纹特征提取的主要目的是计算指纹核心点(Core)和细节点(Minutia)的特征信息。在提取指纹核心点时,采用的是Poincare Index算法,该算法的思路是在指纹图像某像素点区域内,按围绕该点的闭合曲线逆时针方向旋转一周,计算方向角度旋转变化量的和,最后以计算结果来寻找核心点。计算过程中如果某像素点的Poincare Index值为π则判定为核心点,然后便提取该点的坐标与方向场信息,记为P(Cx, Cy, θc)。
        对于指纹的细节点特征,在本设计中只要求提取指纹脊线端点(Ending)和脊线分叉(Bifurcation)两种细节点。在细化的指纹图像中,这两种细节点的形态如图2和图3所示:



        在提取指纹细节点时,首先为细化图像中的每个像素点P建立一个8邻域像素区,如图4所示。其中P1~P8为像素点P周围的邻近环绕像素点。P1~P8中黑色点的值设为1,白色点的值设为0。


    图4 8邻域像素图

    根据Crossing Number (CN)理论,在8邻域像素图中按照公式1计算像素点的CN值。例如在图2和图3中,8领域像素区域内中心点的CN值分别为1和3。

     
        最后按上述方法对细化指纹图像中的所有像素点进行CN值计算,当CN值为1时,可判定所检测的P点为脊线端点,当CN值为3时,则可判定P点为脊线分叉点。检测到细节点之后返回该点的坐标(x,y),并根据CN的值返回细节点的类型T,然后再读取该点的方向角θ。因此,在本算法中一个指纹细节点的具体特征最后用M(x, y, θ ,T)算子来表征。(请注意,代码中,以及下文没有除以2)

        把找到的端点位置存储在txy(Nx3),第一列存储x的位置,第二列存储y的位置,第三列标识点的类别,如果为交叉点则值为6,如果端点则值为2.然后对纹线再次进行光滑处理。

    %找出细化后图像的所有端点
    %将一个点的八个邻域依次两两相减并取绝对值,并将所有结果相加,从细化图像的特征来说
    %和为2时为端点 和为6时为交叉点
    function txy=point(thin)
    count=1;
    txy(count,:)=[0,0,0];
    %取行数和列数的最小值
    siz=min(size(thin,1),size(thin,2))
    for x=40:siz-40
        for y=40:siz-40
            if(thin(y,x))
                CN=0;
                for i=1:8
                    CN=CN+abs(p(thin,y,x,i)-p(thin,y,x,i+1));
                end
                if (CN==2)
                    txy(count,:)=[x,y,2];
                    count=count+1;
                end
                if(CN==6)
                    txy(count,:)=[x,y,6];
                    count=count+1;
                end
            end
        end
    end
    
    for i=1:count-1
        x(i)=txy(i,1);
        y(i)=txy(i,2);
    end
    imshow(double(thin));
    % hold on 通知后面将要绘图
    hold on;
    plot(x,y,'.');

        找到每个端点,使其沿着纹线的方向移动五个像素,如果在五个像素之内遇到交叉点则此点为毛刺,去除此点。判断离端点num个距离内是否有另一个端点的函数为walk判断的主要方法先将该点置为0然后根据八领域点和;和为0或大于2则证明该点距离num内有端点,然后循环向前遍历。

    function [w,pxy]=guanghua(thin,txy)
    %纹线光滑处理.原理:找到每个端点,使其沿着纹线的方向移动5个像素,如果在5个像素之内遇到交叉点,则认为此端点为毛刺,,去除此点
    for j=1:5
        txy=point(thin);
        %txy第三列为2的变为1 否则变为0
        pxy=txy(find(txy(:,3)==2),:);
        %求取行数
        n=size(pxy,1);
        for i=1:n
            error=0;
            error=walk(thin,pxy(i,1),pxy(i,2),5);
            if error==1;
                thin(pxy(i,2),pxy(i,1))==0;
            end
        end
    end
    w=thin;
    imshow(w);
    %判断离端点num距离内是否有另一端点
    function [error,a,b]=walk(thin,x0,y0,num)
    error=0;
    thin(x0,y0)=0;
    t1=0;
    for n=1:num
        if error==1
            break
        else
            x=x0;
            y=y0;
            %判断该点八邻域点和该点的和 来找出想要的点
            for x=x0-1:x0+1
                if error==1
                    break;
                else
                    for y=y0-1:y0+1
                        t1=(sum(sum(thin(y0-1:y0+1,x0-1:x0+1))));
                        %=0代表一个断点(独立的点) dayu2代表不是端点
                   
                        if(t1==0||t1>2)
                            error=1;
                            a=x0;
                            b=y0;
                            break;
                        else
                            % x,y还是y,x
                            if (thin(y,x)==1&&(x-x0)^2+(y-y0)^2~=0)
                                if(t1>2)
                                    error=1;
                                    break;
                                else thin(y,x)=0;
                                    x0=x;
                                    y0=y;
                                    a=x0;
                                    b=y0;
                                    plot(x0,y0,'r.');
                                end
                            end
                        end
                    end
                end
            end
        end
    end

        光滑处理后的特征点比以前少了。但是我们采集指纹时由于采集器的关系,图像的边缘会有很多端点,这已然会影响后续的识别工作,所以我们需要在特征点中去除这些端点,cut函数主要做这些工作,边缘的主要特征就是黑色多白色少,也就是均值小,所以我主要里用灰度图的分区域(31*31)求均值如果灰度值小于70则在该区域的特征点去除,然后会得到更少的特征点.

    %去除图像边缘的端点
    
    function txy=cut(thin,txy)
    % thin=thin1;
    % txy=txy1;
    %声明一个8*8的矩阵
    s(8,8)=0;
    delta(8,8)=0;
    n=size(txy,1);
    for i=1:8
        for j=1:8
            %声明一个数组集合 m{1,2}=3   m=[] [3]
    %          m{2,5}=6
    % 
    % m = 
    % 
    %     [1,2,3]    [3]    []    []     []
    %     []     []    []    []    [6]
    
    % 每次取31*31 先从上到下 再从做到右
            mp{i,j}=thin(1+31*(i-1):31+31*(i-1),1+31*(j-1):31+31*(j-1));
            s(i,j)=sum(sum(mp{i,j}))/(31*31);
            mp{i,j}=(mp{i,j}-s(i,j)).^2
            delta(i,j)=sum(sum(mp{i,j}));
    %         边缘 黑色多 白色少
            if delta(i,j)<=70
                for k=1:n
                    if (txy(k,1)>=1+31*(i-1)&&txy(k,1)<31+31*(i-1)&&txy(k,2)>=1+31*(j-1)&&txy(k,2)<=31+31*(j-1)&&txy(k,3)==2)
                        txy(k,:)=[0,0,0];
                    end
                end
            end
        end
    end
    % find()查询非零元素所在的位置
    txy=txy(find(txy(:,1)),:);
    plot(txy(:,1),txy(:,2),'ro');
    

        但这些点依然不够少说明不够特殊,下面定义了combine(thin,r,txy,num)函数可以找出周围半径为r个像素的圆内没有任何端点和交叉点,沿纹线走num个距离没有交叉点和端点,comine为walk和single_point函数的综合,walk函数上面已经介绍,single_point函数主要是找出独特的点作为特征点,原理是根据两个端点之间的距离。求每个端点距离其他端点的距离,找取距离大于r的端点。执行完combine后会得到更少的端点(实验结果为3个端点)。

    % 综合walk和single_point函数,通过执行[pxy3,error2]=combine(thin,r,txy,num)可以找出周围半径为r个像素的院内没有任何交叉点或端点,并且沿纹线走num个
    % 距离内没有任何哟个交叉点或端点
    function [pxy3,error2]=combine(thin,r,txy,num)
    error=0;
    [pxy2,error]=single_point(txy,r);
    n=size(pxy2,1);
    k=1;
    erroe2=0;
    for i=1:n
        [error,a,b]=walk(thin,pxy2(i,1),pxy2(i,2),num);
        if error~=1
            pxy3(k,1)=pxy2(i,1);
            pxy3(k,2)=pxy2(i,2);
            pxy3(k,3)=pxy2(i,3);
            k=k+1;
            error2=0;
            plot(pxy2(i,1),pxy2(i,2),'r+');
        end
    end



  • 相关阅读:
    linux下挂载硬盘出错的解决方法
    linux下解压缩文件中文乱码问题的解决
    VLC播放器的快捷键(shutcut)
    PGSQL 日期时间的比较
    PGSQL 字符串作为查询参数的处理
    pqsql 防注入
    js字符数组转化为数字数组
    js去除字符串的前后空白
    使用gravatar生成头像
    js删除数组的某个元素
  • 原文地址:https://www.cnblogs.com/mrcharles/p/11879800.html
Copyright © 2020-2023  润新知