指纹识别技术主要分三个步骤:指纹预处理、特征提取、指纹分类与匹配。

无论是指纹分类还是指纹匹配,都需要提取指纹的有效特征,而特征提取的性能很大程度上要依赖于指纹图像的质量。在实际应用中,由于采集条件和采集设备的因素,采集到的指纹图像质量比较差,容易导致很多问题,影响后续处理的效果。因此,指纹图像的预处理是关系到指纹识别系统性能好坏的一个关键。

预处理主要分以下四个步骤:

  1. 指纹图像灰度归一化和均衡化

    归一化的目的,在于消除指纹采集过程中由于传感器自身的噪声以及因为手指压力不同而造成的灰度差异,将指纹图像的对比度和灰度调整到一个固定的级别上,为后续处理提供一个较为统一的图像规格。均衡化是对图像中像素个数多的灰度级进行展宽,对像素个数少的灰度级进行缩减。

  2. 指纹图像分割

    其目标就是根据特征提取的需要,把指纹图像中质量很差、在后续处理中很难恢复的图像区域与有效区域分开,使后续处理能够集中在有效区域;能提高特征提取的精确度;能大大减少指纹预处理的时间。

  3. 指纹图像二值化

    二值化的目的是把灰度指纹图像变成0、1取值的二值图像

  4. 二值化后处理及细化

    由于灰度滤波的不完全性,而且在二值化过程中有时会引入新的噪声,需要对图像进行滤波处理。采用加权中值滤波的方法,根据前景点的不同方向选用不同的权值模板进行滤波,以便于消除纹线上的孔洞和缺口。二值化后的纹线仍然有一定

    宽度,需要细化为单个像素宽度的骨架。细化算法很多,这里采用骨架提取技术。

  5. clc;
    
    close all;
    
    global immagine n_bands h_bands n_arcs h_radius h_lato n_sectors matrice num_disk
    
    %immagine 双精度类型的灰度图
    
    n_bands=4;
    
    h_bands=20;
    
    n_arcs=16;
    
    h_radius=12;
    
    h_lato=h_radius+(n_bands*h_bands*2)+16;
    
    if mod(h_lato,2)==0
    
        h_lato=h_lato-1;
    
    end
    
    n_sectors=n_bands*n_arcs;%多少行数据量
    
    matrice=zeros(h_lato);
    
    for ii=1:(h_lato*h_lato)
    
        matrice(ii)=whichsector(ii);
    
    end
    
    num_disk=8;%8个方向
    
    % 1--> add database
    
    % 0--> recognition
    
    % ok=0;
    
    chos=0;
    
    possibility=6;%有6个菜单,分别为'选择图像并加入数据库','指纹识别','删除数据库','可视化指纹图像','可视化Gabor滤波','退出'
    
     
    
    messaggio='Insert the number of set: each set determins a class. This set should include a number of images for each person, with some variations in expression and in the lighting.';
    
     
    
    while chos~=possibility,
    
        chos=menu('指纹识别系统','选择图像并加入数据库','指纹识别','删除数据库','可视化指纹图像','可视化Gabor滤波','退出');
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        % 计算指纹编码并添加到数据库
    
        if chos==1
    
            clc;
    
            close all;
    
            selezionato=0;%选择标志
    
            while selezionato==0
    
                [namefile,pathname]=uigetfile({'*.bmp;*.tif;*.tiff;*.jpg;*.jpeg;*.gif','IMAGE Files (*.bmp,*.tif,*.tiff,*.jpg,*.jpeg,*.gif)'},'选在灰度图');%打开一个灰度图
    
                if namefile~=0 %文件存在
    
                    [img,map]=imread(strcat(pathname,namefile));%读取文件
    
                    selezionato=1;
    
                else
    
                    disp('选择灰度图');
    
                end
    
                if (any(namefile~=0) && (~isgray(img)))%文件不存在或不是灰度图
    
                    disp('选择灰度图');
    
                    selezionato=0;
    
                end
    
            end
    
            
    
            immagine=double(img);
    
            
    
            if isa(img,'uint8')%如果img是uint8
    
                graylevmax=2^8-1;%计算大小
    
            end
    
            if isa(img,'uint16')
    
                graylevmax=2^16-1;
    
            end
    
            if isa(img,'uint32')
    
                graylevmax=2^32-1;
    
            end
    
            fingerprint = immagine;
    
            
    
            N=h_lato;
    
            
    
            [BinarizedPrint,XofCenter,YofCenter]=centralizing(fingerprint,0);%二值化图像,计算中心点
    
            [CroppedPrint]=Cropping(XofCenter,YofCenter,fingerprint);%图像修剪
    
            [NormalizedPrint,vector]=sector_norm(CroppedPrint,0);%扇形,归一化输入图像        
    
            
    
            for (angle=0:1:num_disk-1)    
    
                gabor=gabor2d_sub(angle,num_disk);%Gabor滤波
    
                ComponentPrint=conv2fft(NormalizedPrint,gabor,'same');
    
                [disk,vector]=sector_norm(ComponentPrint,1);    
    
                finger_code1{angle+1}=vector(1:n_sectors);
    
            end       
    
            
    
            img=imrotate(img,180/(num_disk*2));%以一定角度对图像进行旋转
    
            fingerprint=double(img);
    
            
    
            [BinarizedPrint,XofCenter,YofCenter]=centralizing(fingerprint,0);
    
            [CroppedPrint]=Cropping(XofCenter,YofCenter,fingerprint);
    
            [NormalizedPrint,vector]=sector_norm(CroppedPrint,0);
    
            
    
            for (angle=0:1:num_disk-1)    
    
                gabor=gabor2d_sub(angle,num_disk);
    
                ComponentPrint=conv2fft(NormalizedPrint,gabor,'same');
    
                [disk,vector]=sector_norm(ComponentPrint,1);    
    
                finger_code2{angle+1}=vector(1:n_sectors);
    
            end
    
            % 增加指纹编号到数据库
    
            if (exist('database.dat')==2)
    
                load('database.dat','-mat');
    
                fingerprint_number=fingerprint_number+1;
    
                data{fingerprint_number,1}=finger_code1;
    
                data{fingerprint_number,2}=finger_code2;
    
                save('database.dat','data','fingerprint_number','-append');
    
            else
    
                fingerprint_number=1;
    
                data{fingerprint_number,1}=finger_code1;
    
                data{fingerprint_number,2}=finger_code2;
    
                save('database.dat','data','fingerprint_number');
    
            end
    
            
    
            message=strcat('指纹增加成功。编号:',num2str(fingerprint_number));
    
            msgbox(message,'指纹编数据库','信息');
    
        end % chos 1
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        % 指纹识别
    
        if chos==2
    
            clc;
    
            close all;
    
            selezionato=0;
    
            while selezionato==0
    
                [namefile,pathname]=uigetfile({'*.bmp;*.tif;*.tiff;*.jpg;*.jpeg;*.gif','IMAGE Files (*.bmp,*.tif,*.tiff,*.jpg,*.jpeg,*.gif)'},'选择灰度图');
    
                if namefile~=0
    
                    [img,map]=imread(strcat(pathname,namefile));
    
                    selezionato=1;
    
                else
    
                    disp('选择灰度图');
    
                end
    
                if (any(namefile~=0) && (~isgray(img)))
    
                    disp('选择灰度图');
    
                    selezionato=0;
    
                end
    
            end
    
            
    
            immagine=double(img);
    
            
    
            if isa(img,'uint8')
    
                graylevmax=2^8-1;
    
            end
    
            if isa(img,'uint16')
    
                graylevmax=2^16-1;
    
            end
    
            if isa(img,'uint32')
    
                graylevmax=2^32-1;
    
            end
    
            fingerprint = immagine;
    
            
    
            N=h_lato;
    
            
    
            [BinarizedPrint,XofCenter,YofCenter]=centralizing(fingerprint,0);%二值化
    
            [CroppedPrint]=Cropping(XofCenter,YofCenter,fingerprint);%裁剪
    
            [NormalizedPrint,vector]=sector_norm(CroppedPrint,0);%归一化
    
            
    
            % 存储每个特征向量d的入口
    
            vettore_in=zeros(num_disk*n_sectors,1);
    
            for (angle=0:1:num_disk-1)    
    
                gabor=gabor2d_sub(angle,num_disk);
    
                ComponentPrint=conv2fft(NormalizedPrint,gabor,'same');
    
                [disk,vector]=sector_norm(ComponentPrint,1);    
    
                finger_code{angle+1}=vector(1:n_sectors);
    
                vettore_in(angle*n_sectors+1:(angle+1)*n_sectors)=finger_code{angle+1};
    
            end     
    
           
    
            % 计算输入值文编号
    
            % 检查数据库
    
            if (exist('database.dat')==2)
    
                load('database.dat','-mat');
    
                %---- 分配内存 -----------------------------------
    
                %...
    
                vettore_a=zeros(num_disk*n_sectors,1);
    
                vettore_b=zeros(num_disk*n_sectors,1);
    
                best_matching=zeros(fingerprint_number,1);
    
                valori_rotazione=zeros(n_arcs,1);
    
                % 开始检查 ---------------------------------------
    
                for scanning=1:fingerprint_number
    
                    fcode1=data{scanning,1};
    
                    fcode2=data{scanning,2};
    
                    for rotazione=0:(n_arcs-1)
    
                        p1=fcode1;
    
                        p2=fcode2;
    
                        % ruoto i valori dentro disco
    
                        for conta_disco=1:num_disk%取出每列数据
    
                            disco1=p1{conta_disco};
    
                            disco2=p2{conta_disco};
    
                            for old_pos=1:n_arcs
    
                                new_pos=mod(old_pos+rotazione,n_arcs);
    
                                if new_pos==0
    
                                    new_pos=n_arcs;
    
                                end
    
                                for conta_bande=0:1:(n_bands-1)%取该列每行
    
                                    disco1r(new_pos+conta_bande*n_arcs)=disco1(old_pos+conta_bande*n_arcs);
    
                                    disco2r(new_pos+conta_bande*n_arcs)=disco2(old_pos+conta_bande*n_arcs);
    
                                end
    
                            end
    
                            p1{conta_disco}=disco1r;
    
                            p2{conta_disco}=disco2r;
    
                        end
    
                        % ruoto i dischi circolarmente
    
                        for old_disk=1:num_disk
    
                            new_disk=mod(old_disk+rotazione,num_disk);
    
                            if new_disk==0
    
                                new_disk=num_disk;
    
                            end
    
                            pos=old_disk-1;
    
                            vettore_a(pos*n_sectors+1:(pos+1)*n_sectors)=p1{new_disk};
    
                            vettore_b(pos*n_sectors+1:(pos+1)*n_sectors)=p2{new_disk};                    
    
                        end
    
                        d1=norm(vettore_a-vettore_in);
    
                        d2=norm(vettore_b-vettore_in);
    
                        if d1<d2
    
                            val_minimo=d1;
    
                        else
    
                            val_minimo=d2;
    
                        end
    
                        valori_rotazione(rotazione+1)=val_minimo;
    
                    end
    
                    [minimo,posizione_minimo]=min(valori_rotazione);
    
                    best_matching(scanning)=minimo;
    
                end
    
                [distanza_minima,posizione_minimo]=min(best_matching);
    
                beep;
    
                message=strcat('与数据库中最相似的指纹是 : ',num2str(posizione_minimo)');% 具有',num2str(distanza_minima),'个实例');
    
                msgbox(message,'数据库信息','信息');            
    
            else
    
                message='数据库为空. 不能匹配.';
    
                msgbox(message,'指纹编号数据库错误','错误');    
    
            end
    
            
    
        end % chos 2
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        % 删除数据库  
    
        if chos==3
    
            clc;
    
            close all;
    
            if (exist('database.dat')==2)
    
                button = questdlg('你确定要删除数据库吗?');
    
                if strcmp(button,'Yes')
    
                    delete('database.dat');
    
                    msgbox('数据库删除成功。','数据库删除','信息');
    
                end
    
            else
    
                warndlg('数据库为空!','警告')
    
            end
    
        end % chos 3
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        % 可视化指纹图像    
    
        if chos==4
    
            clc;
    
            close all;
    
            selezionato=0;
    
            while selezionato==0
    
                [namefile,pathname]=uigetfile({'*.bmp;*.tif;*.tiff;*.jpg;*.jpeg;*.gif','IMAGE Files (*.bmp,*.tif,*.tiff,*.jpg,*.jpeg,*.gif)'},'Chose GrayScale Image');
    
                if namefile~=0
    
                    [img,map]=imread(strcat(pathname,namefile));
    
                    selezionato=1;
    
                else
    
                    disp('选择灰度图');
    
                end
    
                if (any(namefile~=0) && (~isgray(img)))
    
                    disp('选择灰度图');
    
                    selezionato=0;
    
                end
    
            end
    
            figure('name','选择图像');
    
            imshow(img);
    
        end % chos 4
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        %--------------------------------------------------------------------------
    
        % 可视化Gabor滤波
    
        if chos==5
    
            clc;
    
            close all;
    
            figure('name','Gabor滤波');
    
            mesh(gabor2d_sub(0,num_disk));
    
        end % chos 5 
    
    end % end while
    
    • 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.
    • 74.
    • 75.
    • 76.
    • 77.
    • 78.
    • 79.
    • 80.
    • 81.
    • 82.
    • 83.
    • 84.
    • 85.
    • 86.
    • 87.
    • 88.
    • 89.
    • 90.
    • 91.
    • 92.
    • 93.
    • 94.
    • 95.
    • 96.
    • 97.
    • 98.
    • 99.
    • 100.
    • 101.
    • 102.
    • 103.
    • 104.
    • 105.
    • 106.
    • 107.
    • 108.
    • 109.
    • 110.
    • 111.
    • 112.
    • 113.
    • 114.
    • 115.
    • 116.
    • 117.
    • 118.
    • 119.
    • 120.
    • 121.
    • 122.
    • 123.
    • 124.
    • 125.
    • 126.
    • 127.
    • 128.
    • 129.
    • 130.
    • 131.
    • 132.
    • 133.
    • 134.
    • 135.
    • 136.
    • 137.
    • 138.
    • 139.
    • 140.
    • 141.
    • 142.
    • 143.
    • 144.
    • 145.
    • 146.
    • 147.
    • 148.
    • 149.
    • 150.
    • 151.
    • 152.
    • 153.
    • 154.
    • 155.
    • 156.
    • 157.
    • 158.
    • 159.
    • 160.
    • 161.
    • 162.
    • 163.
    • 164.
    • 165.
    • 166.
    • 167.
    • 168.
    • 169.
    • 170.
    • 171.
    • 172.
    • 173.
    • 174.
    • 175.
    • 176.
    • 177.
    • 178.
    • 179.
    • 180.
    • 181.
    • 182.
    • 183.
    • 184.
    • 185.
    • 186.
    • 187.
    • 188.
    • 189.
    • 190.
    • 191.
    • 192.
    • 193.
    • 194.
    • 195.
    • 196.
    • 197.
    • 198.
    • 199.
    • 200.
    • 201.
    • 202.
    • 203.
    • 204.
    • 205.
    • 206.
    • 207.
    • 208.
    • 209.
    • 210.
    • 211.
    • 212.
    • 213.
    • 214.
    • 215.
    • 216.
    • 217.
    • 218.
    • 219.
    • 220.
    • 221.
    • 222.
    • 223.
    • 224.
    • 225.
    • 226.
    • 227.
    • 228.
    • 229.
    • 230.
    • 231.
    • 232.
    • 233.
    • 234.
    • 235.
    • 236.
    • 237.
    • 238.
    • 239.
    • 240.
    • 241.
    • 242.
    • 243.
    • 244.
    • 245.
    • 246.
    • 247.
    • 248.
    • 249.
    • 250.
    • 251.
    • 252.
    • 253.
    • 254.
    • 255.
    • 256.
    • 257.
    • 258.
    • 259.
    • 260.
    • 261.
    • 262.
    • 263.
    • 264.
    • 265.
    • 266.
    • 267.
    • 268.
    • 269.
    • 270.
    • 271.
    • 272.
    • 273.
    • 274.
    • 275.
    • 276.
    • 277.
    • 278.
    • 279.
    • 280.
    • 281.
    • 282.
    • 283.
    • 284.
    • 285.
    • 286.
    • 287.
    • 288.
    • 289.
    • 290.
    • 291.
    • 292.
    • 293.
    • 294.
    • 295.
    • 296.
    • 297.
    • 298.
    • 299.
    • 300.
    • 301.
    • 302.
    • 303.
    • 304.
    • 305.
    • 306.
    • 307.
    • 308.
    • 309.
    • 310.
    • 311.
    • 312.
    • 313.
    • 314.
    • 315.
    • 316.
    • 317.
    • 318.
    • 319.
    • 320.
    • 321.
    • 322.
    • 323.
    • 324.
    • 325.
    • 326.
    • 327.
    • 328.
    • 329.
    • 330.
    • 331.
    • 332.
    • 333.
    • 334.
    • 335.
    • 336.
    • 337.
    • 338.
    • 339.
    • 340.
    • 341.
    • 342.
    • 343.
    • 344.
    • 345.
    • 346.
    • 347.
    • 348.
    • 349.
    • 350.
    • 351.
    • 352.
    • 353.
    • 354.
    • 355.
    • 356.
    • 357.
    • 358.
    • 359.
    • 360.
    • 361.
    • 362.
    • 363.
    • 364.
    • 365.
    • 366.
    • 367.
    • 368.
    • 369.
    • 370.
    • 371.
    • 372.
    • 373.
    • 374.
    • 375.
    • 376.
    • 377.
    • 378.
    • 379.
    • 380.
    • 381.
    • 382.
    • 383.
    • 384.
    • 385.
    • 386.
    • 387.
    • 388.
    • 389.
    • 390.
    • 391.
    • 392.
    • 393.
    • 394.
    • 395.
    • 396.
    • 397.
    • 398.
    • 399.
    • 400.
    • 401.
    • 402.
    • 403.
    • 404.
    • 405.
    • 406.
    • 407.
    • 408.
    • 409.
    • 410.
    • 411.
    • 412.
    • 413.
    • 414.
    • 415.
    • 416.
    • 417.
    • 418.
    • 419.
    • 420.
    • 421.
    • 422.
    • 423.
    • 424.
    • 425.
    • 426.
    • 427.
    • 428.
    • 429.
    • 430.
    • 431.
    • 432.
    • 433.
    • 434.
    • 435.
    • 436.
    • 437.
    • 438.
    • 439.
    • 440.
    • 441.
    • 442.
    • 443.
    • 444.
    • 445.
    • 446.
    • 447.
    • 448.
    • 449.
    • 450.
    • 451.
    • 452.
    • 453.
    • 454.
    • 455.
    • 456.
    • 457.
    • 458.
    • 459.
    • 460.
    • 461.
    • 462.
    • 463.
    • 464.
    • 465.
    • 466.
    • 467.
    • 468.
    • 469.
    • 470.
    • 471.
    • 472.
    • 473.
    • 474.
    • 475.
    • 476.
    • 477.
    • 478.
    • 479.
    • 480.
    • 481.
    • 482.
    • 483.
    • 484.
    • 485.
    • 486.
    • 487.
    • 488.
    • 489.
    • 490.
    • 491.
    • 492.
    • 493.
    • 494.
    • 495.
    • 496.
    • 497.
    • 498.
    • 499.
    • 500.
    • 501.
    • 502.
    • 503.
    • 504.
    • 505.
    • 506.
    • 507.
    • 508.
    • 509.
    • 510.
    • 511.
    • 512.
    • 513.
    • 514.
    • 515.
    • 516.
    • 517.
    • 518.
    • 519.
    • 520.
    • 521.
    • 522.
    • 523.
    • 524.
    • 525.
    • 526.
    • 527.
    • 528.
    • 529.
    • 530.
    • 531.
    • 532.
    • 533.
    • 534.
    • 535.
    • 536.
    • 537.
    • 538.
    • 539.
    • 540.
    • 541.
    • 542.
    • 543.
    • 544.
    • 545.
    • 546.
    • 547.
    • 548.
    • 549.
  6. 【图像识别】基于模板匹配实现指纹识别_指纹识别