基于MATLAB/FPGA的指纹识别算法仿真与优化

1.软件版本

MATLAB2013b,vivado2019.2

2.本算法理论知识

指纹识别技术是指使用取像设备读取指纹图像,通过识别软件提取出指纹图像中的特征数据,然后根据匹配算法得到的结果鉴别指纹所有人身份的生物特征识别技术。指纹识别系统主要涉及三大步骤:指纹图像预处理、特征提取、特征匹配三个部分,其中预处理部分又可分为归一化、图像滤波增强、二值化和细化等几个步骤。系统流程框图如图1-1所示。下面对这三个个部分做一下简单的介绍。

【指纹识别】基于MATLAB/FPGA的指纹识别算法仿真实现_特征提取

  1. 指纹的基本特征

指纹其实是比较复杂的。与人工处理不同,许多生物识别技术公司并不直接存储指纹的图象。多年来在各个公司及其研究机构产生了许多数字化的算法(美国有关法律认为,指纹图象属于个人隐私,因此不能直接存储指纹图象)。但指纹识别算法最终都归结为在指纹图象上找到并比对指纹的特征。

指纹识别系统中,通常采用全局和局部两种层次的结构特征。两枚指纹可能具有相同的全局特征,但局部特征却不可能完全相同。

  1. 全局特征

全局特征是指那些用人眼直接就可以观察到的特征,包括:基本纹路图案环型(loop),弓型(arch),螺旋型(whorl)如图2-1所示。其他的指纹图案都基于这三种基本图案。仅仅依靠图案类型来分辨指纹是远远不够的,这只是一个粗略的分类,但通过分类使得在大数据库中搜寻指纹更为方便。

【指纹识别】基于MATLAB/FPGA的指纹识别算法仿真实现_特征点_02

模式区是指指纹上包括了总体特征的区域,即从模式区就能够分辨出指纹是属于那一种类型的。有的指纹识别算法只使用模式区的数据。Secure Touch的指纹识别算法使用了所取得的完整指纹而不仅仅是模式区进行分析和识别,如图2所示。

【指纹识别】基于MATLAB/FPGA的指纹识别算法仿真实现_指纹识别_03

图2模式区

核心点位于指纹纹路的渐进中心,它在读取指纹和比对指纹时作为参考点。许多算法是基于核心点的,既只能处理和识别具有核心点的指纹。核心点对于Secure Touch的指纹识别算法很重要,但没有核心点的指纹它仍然能够处理,如图3所示。

【指纹识别】基于MATLAB/FPGA的指纹识别算法仿真实现_特征点_04

图3核心点

三角点位于从核心点开始的第一个分叉点或者断点、或者两条纹路会聚处、孤立点、折转处,或者指向这些奇异点。三角点提供了指纹纹路的计数跟踪的开始之处,如图4所示。

【指纹识别】基于MATLAB/FPGA的指纹识别算法仿真实现_特征点_05

指模式区内指纹纹路的数量。在计算指纹的纹数时,一般先在连接核心点和三角点,这条连线与指纹纹路相交的数量即可认为是指纹的纹数,如图2-5所示。

【指纹识别】基于MATLAB/FPGA的指纹识别算法仿真实现_特征点_06

细节特征提取的方法分为两种:一种是从灰度图像中提取特征,另一种是从细化二值图像中提取特征。直接从灰度图像中提取特征的算法一般是对灰度指纹纹线进行跟踪,根据跟踪结果寻找特征的位置和判断特征的类型。这种方法省去了复杂的指纹图像预处理过程,但是特征提取的算法却十分复杂,而且由于噪声等因素影响,特征信息(位置、方向等)也不够准确。目前大多数系统采用第二种方法,从细化二值图像中提取特征,该方法比较简单,在得到可靠的细化二值图像后,只需要一个3×3的模板就可以将端点和分叉点提取出来。

特征点提取的好坏将直接影响匹配的结果。现实中,指纹输入时,由于汗渍、干燥、按压力度不同等影响,得到的指纹图像大都含有断纹、褶皱、模糊、灰度不均匀等质量问题,虽然经过预处理,图像质量会有所改观,但预处理算法对各个指纹的适应性和有效性也会不同,并且会引入新的噪声,因此得到的细化二值图像往往含有大量的伪特征点。伪特征点不仅会影响匹配的速度,严重的会影响整个识别的正确率。所以提取特征点后要进行去伪处理,尽可能滤除伪特征点、保留真特征点。实践中发现,伪特征点的数量一般占总特征数量的一半以上,所以去伪是必不可少的过程。去伪过程可以在两个阶段进行:一是在特征提取之前对细化二值图像进行平滑、去除毛刺、连接断纹等操作,然后提取特征作为真特征;另一种是在特征提取之后,根据特征之间的相互关系,尽可能准确的识别伪特征点并滤除它们。前者直接对图像进行修补,操作比较复杂,容易引入新的伪特征;后者对特征提取后的数据进行判断,识别比较麻烦,但是速度较快本文采用第二种方法,即从已提取的特征点中滤除伪特征,保留真特征。

3.部分核心代码

登录后复制

`timescale 1ns / 1ps//// Company: // Engineer:       ThinkSpark(CJY)// // Create Date:    10:46:32 08/21/2009 // Design Name: // Module Name:    spisensor // Project Name: // Target Devices: // Tool versions: // Description: //// Dependencies: //// Revision: // Revision 0.01 - File Created// Additional Comments: ////`define effectvalue   1module spisensor(//Output                 cmd2tx_din_w,         rd_data_cmd_w,         send_rd_spidata_cmd_n_w,                 clk180,        //spi transfer enable         SCK_CPOL_0,               //clk for slave         send_n_w,                                tx_rd_en_w,                 tx_wr_en_w,                 rx_wr_en_w,                 locked_out0,                 clk_24MHz,         div10_cnt_w,         sck_cnt8_w,         //Input         rx_full_n,         rx_first_n,         rx_empty_n,                  clk,                //system clock         rst                              );   output [7:0]     cmd2tx_din_w;output [7:0]     rd_data_cmd_w;output           SCK_CPOL_0;output           clk180;output           send_n_w;output           tx_wr_en_w;output           tx_rd_en_w;output           rx_wr_en_w;output           locked_out0;output           clk_24MHz;output [3:0]     div10_cnt_w;output [2:0]     sck_cnt8_w;output           send_rd_spidata_cmd_n_w;input            clk;input            rst;input            rx_full_n;input            rx_empty_n;input            rx_first_n;reg   [7:0]      cmdpad[31:0];    //filled with commands to be sent to slave after initializationreg   [7:0]      rd_data_cmd_pad[1:0];reg   [7:0]      cmd2tx_din;reg   [7:0]      rd_data_cmd;reg   [3:0]      div10_cnt;      //the time while div10_cnt=0 and div10_cnt=0- equals to an SCK period reg   [2:0]      sck_cnt8;       //sck_cnt8=7 indicates that 8bits have been transferredreg   [3:0]      dcm_rst_delaycnt;reg   [1:0]      rd_spidata_cmd_cnt;reg              rd_spidata_cmd_cnt_en;reg              send_rd_spidata_cmd_n;reg              rd_data_cmd_rd_en;reg   [15:0]     bytecnt;reg   [5:0]      incr;reg              tx_wr_en;reg              tx_rd_en;reg              rx_wr_en;reg              transmision_done;reg              addr;reg              delaycnt_ctrl_n;reg              transfer_n;    //data transfer enable bit,active lowreg              send_n;        //data send enable bit,active lowreg              recv_n;        //data receive enable bit,active lowreg    [7:0]     pre_state;reg    [7:0]     nx_state;wire             clk0_out0;wire             locked_out0;wire             clk0_out1;wire             locked_out1;wire             clk_24MHz;wire             clk180;wire             SCK_CPOL_0;wire             SCK_CPOL_1;wire             send_n_w;//wire             transfer_n_w;wire             tx_rd_en_w;wire             tx_wr_en_w;wire             rx_wr_en_w;wire  [7:0]      cmd2tx_din_w; wire  [3:0]      div10_cnt_w;wire  [2:0]      sck_cnt8_w; wire             send_rd_spidata_cmd_n_w;       parameter        idle                     = 8'b00000000,                 cmd2fifo                 = 8'b00000001,                 sensor_initial           = 8'b00000010,         rd_sensor                = 8'b00000100,         rd_spistat               = 8'b00001000,         rd_spidata               = 8'b00010000,         send_data2uart           = 8'b00100000,         last_data2uart           = 8'b01000000,         spi_stop                 = 8'b10000000;                     dcm0 mydcm0 (    .CLKIN_IN(clk),     .RST_IN(transfer_n),     .CLKFX_OUT(SCK_CPOL_1),     .CLKFX180_OUT(SCK_CPOL_0),        .CLK0_OUT(),     .LOCKED_OUT(locked_out0)    );    dcm1 mydcm1 (    .CLKIN_IN(clk),     .CLKFX_OUT(clk_24MHz),        .CLK0_OUT(),     .CLK180_OUT(clk180),     .LOCKED_OUT(locked_out1)    );//assign transfer_n_w =transfer_n; assign tx_wr_en_w=tx_wr_en;assign tx_rd_en_w=tx_rd_en;assign rx_wr_en_w=rx_wr_en;assign send_n_w  =send_n;assign cmd2tx_din_w=cmd2tx_din;assign rd_data_cmd_w = rd_data_cmd;assign div10_cnt_w = div10_cnt;assign sck_cnt8_w  = sck_cnt8;assign send_rd_spidata_cmd_n_w = send_rd_spidata_cmd_n;//initialize cmdpad and transfer data in pad to Tx_fifoalways @(posedge clk)begin   if(rst == `effectvalue)   begin   cmdpad[0] <= 8'h75;   cmdpad[1] <= 8'h7F;   cmdpad[2] <= 8'h76;   cmdpad[3] <= 8'h02;   cmdpad[4] <= 8'h77;   cmdpad[5] <= 8'h01;   cmdpad[6] <= 8'h11;   cmdpad[7] <= 8'h00;   cmdpad[8] <= 8'h21;   cmdpad[9] <= 8'h00;   cmdpad[10] <= 8'h20;   cmdpad[11] <= 8'h00;   cmdpad[12] <= 8'h50;      cmdpad[13] <= 8'h00;   cmdpad[14] <= 8'h00;   cmdpad[15] <= 8'h00;   end   end   always @(posedge clk)begin   if(rst == `effectvalue)      begin       rd_data_cmd_pad[0] <= 8'h20;     rd_data_cmd_pad[1] <= 8'h00;    endendalways @(posedge clk)begin   if(rst == `effectvalue)      cmd2tx_din <= 8'b0;   else          cmd2tx_din <= cmdpad[incr];end//address point to data be wrote to Tx_fifo always @(posedge clk)begin   if(rst == `effectvalue)      incr <= 6'b0;      else if(incr == 31)        incr <= 31 ;   else         incr <= incr + 1;   end//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//transfer_n-\________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________//clk        |--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|//div10_cnt   [  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ]    //SCK       XXXXXXX________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________///sck_cnt8         [00000000000000000000000000000000000000000000000000000][1111111111111111111111111111111111111111111111111111111111][2222222222222222222222222222222222222222222222222222222222][3333333333333333333333333333333333333333333333333333333333][4444444444444444444444444444444444444444444444444444444444][5555555555555555555555555555555555555555555555555555555555][6666666666666666666666666666666666666666666666666666666666][7777777777777777777777777777777777777777777777777777777777][0000000000000000000000000000000000000000000000000000000000][11111111111111111111111111111111111111]//tx_rd_en      ------|_____|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\_____/----------------------------------------------------------------------------------//tx_shifterOOOOOOOOOOOOOOOOOOO[            d7 d6 d5 d4 d3 d2 d1 d0      ][         d6 d5 d4 d3 d2 d1 d0 0                           ][                  d5 d4 d3 d2 d1 d0 0 0                   ][                  d4 d3 d2 d1 d0 0 0 0                    ][                    d3 d2 d1 d0 0 0 0 0                   ][                        d2 d1 d0 0 0 0 0 0                ][                  d1  d0  0  0  0  0  0  0                ][                      d0  0  0  0  0  0  0  0                               ][     d7 d6 d5 d4 d3 d2 d1 d0            ][           d6 d5 d4 d3 d2 d1 d0 0 ] //MOSI     OOOOOOOOOOOOOO000000000000000000[----------------------------d7----------------------------][----------------------------d6----------------------------][----------------------------d5----------------------------][----------------------------d4----------------------------][----------------------------d3----------------------------][----------------------------d2----------------------------][----------------------------d1----------------------------][----------------------------d0----------------------------][----------------------------d7----------------------------][--d6--]//MISO  XXXXX[----------------------------D7-----------------------------][----------------------------D6----------------------------][----------------------------D5----------------------------][----------------------------D4----------------------------][----------------------------D3----------------------------][----------------------------D2----------------------------][----------------------------D1----------------------------][----------------------------D0----------------------------][----------------------------D7----------------------------][----------------------------D7--------//rx_shifter0000000000000000000000000000000[                        0 0 0 0 0 0 0 D7                  ][                        0 0 0 0 0 0 D7 D6                 ][                       0 0 0 0 0 D7 D6 D5                 ][                        0 0 0 0 D7 D6 D5 D4               ][                      0 0 0 D7 D6 D5 D4 D3                ][                    0 0 D7 D6 D5 D4 D3 D2                 ][                       0 D7 D6 D5 D4 D3 D2 D1             ][                     D7 D6 D5 D4 D3 D2 D1 D0              ][                        0 0 0 0 0 0 0 D7                  ] //rx_wr_en------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\_____/-----------------------------------------------------------------//----------------------------------------------------------------------------------------//----------------------------------------------------------------------------------------//the time while div10_cnt=0 and div10_cnt=0- equals to an SCK period   always @(posedge clk)begin   if( (rst == `effectvalue) || (transfer_n == 1'b1) )      div10_cnt <= 4'b0;   else if(div10_cnt == 9)      div10_cnt <= 4'b0;   else if(locked_out0 == 1'b1)      div10_cnt <= div10_cnt + 1;end  //----------------------------------------------------------------------------------------  //3bits counter for SCK cycles, one counting cycle indicates one Byte transmission done always @ (posedge clk)begin   if( (rst == `effectvalue) || (transfer_n == 1'b1) )      sck_cnt8 <= 3'b0;   else if( (div10_cnt == 9) && (locked_out0 == 1'b1) )          //?????????????????????      sck_cnt8 <= sck_cnt8 + 1;   end//--------------------------------------------------------------------------------------------------//------------control reading from tx_fifo and writing to rx_fifo----------------------------------//---------------------------------begin-----------------------------------------------------------always @(posedge clk180)                      //---- @posedge clk180 will work more precisely-----begin   if( (rst == `effectvalue) || (send_n == 1'b1) )        //not to read data from tx_fifo when send_n=1      tx_rd_en <= 1'b1;   else if( (locked_out0 == 1'b1) && (sck_cnt8 == 0) &&            (div10_cnt == 0) )      tx_rd_en <= 1'b0;   else      tx_rd_en <= 1'b1;   endalways @(posedge clk180)begin   if( (rst == `effectvalue) || (send_rd_spidata_cmd_n == 1'b1) )     rd_data_cmd_rd_en <= 1'b1;   else if( (locked_out0 == 1'b1) && (sck_cnt8 == 0) &&            (div10_cnt == 0) )   rd_data_cmd_rd_en <= 1'b0;   else     rd_data_cmd_rd_en <= 1'b1;endalways @(posedge clk)begin   if(rst == `effectvalue)      rd_data_cmd <= 8'b0;   else if(rd_data_cmd_rd_en == 1'b0)      rd_data_cmd <= rd_data_cmd_pad[addr];endalways @(posedge clk)begin   if(rst == `effectvalue)      addr <= 1'b0;   else if (rd_data_cmd_rd_en == 1'b0)       addr <= ~addr;endalways @(posedge clk)begin   if( (rst == `effectvalue) || (rx_full_n == 1'b0) )      rd_spidata_cmd_cnt <= 2'b0;   else if(rd_spidata_cmd_cnt == 2)      rd_spidata_cmd_cnt <= 2;   else if( (rd_spidata_cmd_cnt_en == 1'b0) && ( sck_cnt8 == 7 ) &&             (div10_cnt == 9) )      rd_spidata_cmd_cnt <= rd_spidata_cmd_cnt + 1;end///always @(posedge clk180)                                 //---- @posedge clk180 will work more precisely-----begin   if( (rst == `effectvalue) || (recv_n == 1'b1) )       //not to write to rx_fifo when recv_n=1      rx_wr_en <= 1'b1;   else if( (locked_out0 == 1'b1) && (sck_cnt8 == 7) &&            (div10_cnt == 6)  )                          //rx_wr_en be active while div10_cnt=6 and sck_cnt8=7 can     rx_wr_en <= 1'b0;                                  //leave some time space for bytecnt   else      rx_wr_en <= 1'b1;end//------------control reading from tx_fifo and writing to rx_fifo----------------------------------//---------------------------------end-----------------------------------------------------------always @(posedge clk)begin   if( (rst == `effectvalue) ||        ( (transfer_n == 1'b1) && (transmision_done == 1'b1) ) )     bytecnt <= 16'b0;      else if( (sck_cnt8 == 7) && ( div10_cnt == 7 ) )            // one more byte has been sent and received the moment     bytecnt <= bytecnt + 1;                                   //sck_cnt8=7 and div10_cnt=7(as the wave showed following)   else      bytecnt <= bytecnt;end always @(posedge clk)begin   if( rst == `effectvalue )      transmision_done <= 1'b0;   else if( (transmision_done == 1'b1) && (div10_cnt == 0) )      transmision_done <= 1'b0;   else if( (pre_state == sensor_initial) && (bytecnt == 6) )      transmision_done <= 1'b1;   else if( (pre_state == rd_sensor) && (bytecnt == 370) )      transmision_done <= 1'b1;   else if( (pre_state == rd_spistat) && (bytecnt == 3) )      transmision_done <= 1'b1;   //else if( (pre_state == rd_regs) && (bytecnt == 18) )      //transmision_done <= 1'b1;   else if( (pre_state == rd_spidata) && (bytecnt == 31352) )      transmision_done <= 1'b1;   endalways @( posedge clk )begin   if( (rst == `effectvalue) || (transmision_done == 1'b1) || (rx_full_n == 1'b0) )      dcm_rst_delaycnt <= 4'b0;   else if( dcm_rst_delaycnt == 9 )      dcm_rst_delaycnt <= 9;   else if( delaycnt_ctrl_n == 1'b0 )      dcm_rst_delaycnt <= dcm_rst_delaycnt + 1;end//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------//transfer_n-\________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________//clk        |--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|//div10_cnt   [  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ][  6 ][  7 ][  8 ][  9 ][  0 ][  1 ][  2 ][  3 ][  4 ][  5 ]    //SCK       XXXXXXX________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________/-----------------------------\_____________________________///sck_cnt8         [00000000000000000000000000000000000000000000000000000][1111111111111111111111111111111111111111111111111111111111][2222222222222222222222222222222222222222222222222222222222][3333333333333333333333333333333333333333333333333333333333][4444444444444444444444444444444444444444444444444444444444][5555555555555555555555555555555555555555555555555555555555][6666666666666666666666666666666666666666666666666666666666][7777777777777777777777777777777777777777777777777777777777][0000000000000000000000000000000000000000000000000000000000][11111111111111111111111111111111111111]//tx_rd_en      ------\_____/-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\_____/----------------------------------------------------------------------------------//tx_shifterOOOOOOOOOOOOOOOOOOO[            d7 d6 d5 d4 d3 d2 d1 d0      ][         d6 d5 d4 d3 d2 d1 d0 0                           ][                  d5 d4 d3 d2 d1 d0 0 0                   ][                  d4 d3 d2 d1 d0 0 0 0                    ][                    d3 d2 d1 d0 0 0 0 0                   ][                        d2 d1 d0 0 0 0 0 0                ][                  d1  d0  0  0  0  0  0  0                ][                      d0  0  0  0  0  0  0  0                               ][     d7 d6 d5 d4 d3 d2 d1 d0            ][           d6 d5 d4 d3 d2 d1 d0 0 ] //MOSI     OOOOOOOOOOOOOO000000000000000000[----------------------------d7----------------------------][----------------------------d6----------------------------][----------------------------d5----------------------------][----------------------------d4----------------------------][----------------------------d3----------------------------][----------------------------d2----------------------------][----------------------------d1----------------------------][----------------------------d0----------------------------][----------------------------d7----------------------------][--d6--]//MISO  XXXXX[----------------------------D7-----------------------------][----------------------------D6----------------------------][----------------------------D5----------------------------][----------------------------D4----------------------------][----------------------------D3----------------------------][----------------------------D2----------------------------][----------------------------D1----------------------------][----------------------------D0----------------------------][----------------------------D7----------------------------][----------------------------D7--------//rx_shifter0000000000000000000000000000000[                        0 0 0 0 0 0 0 D7                  ][                        0 0 0 0 0 0 D7 D6                 ][                       0 0 0 0 0 D7 D6 D5                 ][                        0 0 0 0 D7 D6 D5 D4               ][                      0 0 0 D7 D6 D5 D4 D3                ][                    0 0 D7 D6 D5 D4 D3 D2                 ][                       0 D7 D6 D5 D4 D3 D2 D1             ][                     D7 D6 D5 D4 D3 D2 D1 D0              ][                        0 0 0 0 0 0 0 D7                  ] //rx_wr_en------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\_____/-------------------------------------------------------------//----------------------------------------------------------------------------------------//-------------------------------------------------------------------------------//-------------------------------FSM---------------------------------------------always @(posedge clk)begin   if(rst == `effectvalue)      pre_state <= idle;   else      pre_state <= nx_state;end//-----------------------------------------------------------------------//FSM state transform---------------------------------------------------always @(pre_state or div10_cnt or incr or transmision_done or          rx_empty_n or rx_full_n)begin   case(pre_state)         idle          : nx_state = cmd2fifo;        cmd2fifo      : begin                    if( incr == 31)                      //all 16 commands in cmdpad were wrote to Tx_fifo when incr=15               nx_state = sensor_initial;            else               nx_state = cmd2fifo;                          end            sensor_initial: begin                    if( (transmision_done == 1'b1) && (div10_cnt == 0))               nx_state = rd_sensor;            else               nx_state = sensor_initial;                          end            rd_sensor      :begin                      if( (transmision_done == 1'b1) && (div10_cnt == 0))               nx_state = rd_spistat;            else               nx_state = rd_sensor;            end        rd_spistat     :begin                    if( (transmision_done == 1'b1) && (div10_cnt == 0))               nx_state = rd_spidata;            else               nx_state = rd_spistat;            end        rd_spidata     :begin                    if( (transmision_done == 1'b1) && (div10_cnt == 0))               nx_state = last_data2uart;            else if(rx_full_n == 1'b0)                             //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!                              nx_state = send_data2uart;            else               nx_state = rd_spidata;            end    send_data2uart:begin                   if(rx_empty_n == 1'b0)              nx_state = rd_spidata;           else              nx_state = send_data2uart;           end              last_data2uart:begin                  if(rx_empty_n == 1'b0)            nx_state = spi_stop;          else            nx_state = last_data2uart;          end                  spi_stop       :   nx_state = spi_stop;     default        :   nx_state = idle;               endcaseend//---------FSM state transform-----------------------------------------------//-----------------------------------------------------------------------------//-------------------------------------------//FSM control signals outputalways @(pre_state  or rx_full_n or div10_cnt or          incr  or bytecnt or dcm_rst_delaycnt or      rd_spidata_cmd_cnt or rx_empty_n or rx_first_n )begin   case(pre_state)         idle            :begin                     tx_wr_en    = 1'b1;             transfer_n  = 1'b1;             send_n      = 1'b1;             recv_n      = 1'b1;             delaycnt_ctrl_n = 1'b1;             send_rd_spidata_cmd_n = 1'b1;             rd_spidata_cmd_cnt_en = 1'b1;             end        cmd2fifo        :begin                     if( (incr == 0) && (incr == 31) )                begin                 tx_wr_en    = 1'b1;               transfer_n  = 1'b1;               send_n      = 1'b1;               recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             else                begin                      tx_wr_en    = 1'b0;               transfer_n  = 1'b1;               send_n      = 1'b1;               recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;                          end                           end    sensor_initial  :begin                     if( (bytecnt == 6) && ( div10_cnt == 9) )                begin                 tx_wr_en    = 1'b1;               transfer_n  = 1'b1;            // this will reset bytecnt when div10_cnt=9                send_n      = 1'b1;               recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;                                              end             else if( dcm_rst_delaycnt <= 8)                begin                           tx_wr_en    = 1'b1;               transfer_n  = 1'b1;                                  send_n      = 1'b1;               recv_n      = 1'b1;                             delaycnt_ctrl_n = 1'b0;                             send_rd_spidata_cmd_n = 1'b1;                             rd_spidata_cmd_cnt_en = 1'b1;                               end             else if(dcm_rst_delaycnt == 9)                begin                 tx_wr_en    = 1'b1;               transfer_n  = 1'b0;                                  send_n      = 1'b0;               recv_n      = 1'b1;                             delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             else                 begin                 tx_wr_en    = 1'b1;               transfer_n  = 1'b1;            // this will reset bytecnt when div10_cnt=9                send_n      = 1'b1;               recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;                               end                          end    rd_sensor       :begin                     if( dcm_rst_delaycnt <= 8)                begin                 tx_wr_en    = 1'b1;               transfer_n  = 1'b1;                                  send_n      = 1'b1;               recv_n      = 1'b1;                             delaycnt_ctrl_n = 1'b0;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             else if( (bytecnt < 2 ) && (dcm_rst_delaycnt == 9) )                begin                    tx_wr_en    = 1'b1;                 transfer_n  = 1'b0;                                    send_n      = 1'b0;                 recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;                end             else if( (bytecnt >=2) && (bytecnt <=370) && (dcm_rst_delaycnt == 9))                begin                 tx_wr_en    = 1'b1;                 transfer_n  = 1'b0;                                    send_n      = 1'b1;                 recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             else                begin                 tx_wr_en    = 1'b1;                 transfer_n  = 1'b1;                                    send_n      = 1'b1;                 recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             end      rd_spistat      :begin                     if( dcm_rst_delaycnt <= 8)                begin                 tx_wr_en    = 1'b1;               transfer_n  = 1'b1;                                  send_n      = 1'b1;               recv_n      = 1'b1;                             delaycnt_ctrl_n = 1'b0;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end                     else if( (bytecnt < 2) && (dcm_rst_delaycnt == 9) )                begin                    tx_wr_en    = 1'b1;                 transfer_n  = 1'b0;                                    send_n      = 1'b0;                 recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             else if( (bytecnt >= 2) && (dcm_rst_delaycnt == 9) )                begin                                    tx_wr_en    = 1'b1;                 transfer_n  = 1'b0;                                    send_n      = 1'b1;                 recv_n      = 1'b0;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             else                begin                                    tx_wr_en    = 1'b1;                 transfer_n  = 1'b1;                                    send_n      = 1'b1;                 recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             end      rd_spidata      :begin                     if( dcm_rst_delaycnt <= 8)                begin                 tx_wr_en    = 1'b1;               transfer_n  = 1'b1;                                  send_n      = 1'b1;               recv_n      = 1'b1;                             delaycnt_ctrl_n = 1'b0;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end                                  else if( (bytecnt > 10) && (rx_first_n == 1'b1) &&                      (rx_empty_n == 1'b0) && ( rd_spidata_cmd_cnt < 2 ) )              begin                  tx_wr_en    = 1'b1;                 transfer_n  = 1'b0;                                    send_n      = 1'b1;                 recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b0;               rd_spidata_cmd_cnt_en = 1'b0;                end             else if( (bytecnt > 10) && (rd_spidata_cmd_cnt == 2) )                begin                 tx_wr_en    = 1'b1;                 transfer_n  = 1'b0;                                    send_n      = 1'b1;                 recv_n      = 1'b0;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;                            end             else if( (bytecnt < 2) && (dcm_rst_delaycnt == 9)  )                begin                    tx_wr_en    = 1'b1;                 transfer_n  = 1'b0;                                    send_n      = 1'b0;                 recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             else if( (bytecnt >= 2) && (rx_full_n == 1'b1) )                begin                                    tx_wr_en    = 1'b1;                 transfer_n  = 1'b0;                                    send_n      = 1'b1;                 recv_n      = 1'b0;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             else                begin                                    tx_wr_en    = 1'b1;                 transfer_n  = 1'b1;                                    send_n      = 1'b1;                 recv_n      = 1'b1;               delaycnt_ctrl_n = 1'b1;               send_rd_spidata_cmd_n = 1'b1;               rd_spidata_cmd_cnt_en = 1'b1;              end             end                 send_data2uart,    last_data2uart,       spi_stop        :begin                        tx_wr_en    = 1'b1;              transfer_n  = 1'b1;                                 send_n      = 1'b1;              recv_n      = 1'b1;              delaycnt_ctrl_n = 1'b1;              send_rd_spidata_cmd_n = 1'b1;              rd_spidata_cmd_cnt_en = 1'b1;             end     default         : begin                        tx_wr_en    = 1'b1;              transfer_n  = 1'b1;                                 send_n      = 1'b1;              recv_n      = 1'b1;              delaycnt_ctrl_n = 1'b1;              send_rd_spidata_cmd_n = 1'b1;              rd_spidata_cmd_cnt_en = 1'b1;             end     endcaseend//FSM control signals output//--------------------------------------------endmodule1.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.550.551.552.553.554.555.556.557.558.559.560.561.562.563.564.565.566.567.568.569.570.571.572.573.574.575.576.577.578.579.580.581.582.583.584.585.586.587.588.589.590.591.592.593.594.595.596.597.598.599.600.601.602.603.604.605.606.607.608.609.610.611.612.613.614.615.616.617.618.619.620.621.622.623.624.625.626.627.628.629.630.631.632.633.634.635.636.637.638.639.640.641.642.643.644.645.646.647.648.649.650.651.652.653.654.655.656.657.658.659.660.661.662.663.664.665.666.667.668.669.670.671.672.673.674.675.676.677.678.679.680.681.682.683.684.685.686.687.688.689.690.691.692.693.694.695.696.697.698.699.700.701.702.703.704.705.706.707.708.709.710.711.712.713.714.715.716.717.718.719.720.721.722.723.724.





登录后复制

%ProcessOfFingerPrint.mclc;clear;clear all;%--------------加载指纹文本文件-----------------------fid=fopen('1x1.txt','r');dd=fscanf(fid,'%x');fclose(fid);array=dd';for i=0:199    OriginFingerPrint(i+1,1:152)=array(i*152+1:i*152+152);endfigure('name','OriginFingerPrint');imshow(uint8(OriginFingerPrint));%---------------灰度图像取反--------------------------ReverseFingerPrint=255-OriginFingerPrint;figure('name','ReverseFingerPrint');imshow(uint8(ReverseFingerPrint));%---------------进行二维适应性去噪过滤处理------------FrontFilt=wiener2(ReverseFingerPrint,[3 3]);figure('name','FrontFilt');imshow(uint8(FrontFilt));%---------------扩大图像的像素至400x304---------------EnhanceFingerPrint=enhance_finger(FrontFilt);%---------------取图像的中心点------------------------[XofCenter,YofCenter] = centralizing(EnhanceFingerPrint);figure('name','EnhanceFingerPrint');imshow(uint8(EnhanceFingerPrint));hold on;plot(XofCenter,YofCenter,'or');hold off;%---------------二值化图像-----------------------------[BinarizationFingerPrint,theta]=orientation(EnhanceFingerPrint);figure('name','BinarizationFingerPrint');imshow(uint8(BinarizationFingerPrint));%----------------进行中值滤波处理----------------------AfterFilt=median_filter(BinarizationFingerPrint);figure('name','AfterFilt');imshow(uint8(AfterFilt));%----------------二值化图像细化处理--------------------ThinFingerPrint=thinning(AfterFilt);figure('name','ThinFingerPrint');imshow(uint8(ThinFingerPrint));%----------------找寻细化图像的特征点------------------[Dpx,Dpy,Dpcount,Fpx,Fpy,Fpcount]=characterpoint(ThinFingerPrint);hold on;plot(Dpy,Dpx,'o');%特征端点用'o'标注plot(Fpy,Fpx,'+');%特征分叉点用'+'标注plot(XofCenter,YofCenter,'*r');%中心点用红色'*'标注hold off;%-----------------生成各特征点相对中心点的距离向量---------------Dpcount=size(Dpx,2);Fpcount=size(Fpx,2);for i=1:Dpcount    Dpdistant(i)=sqrt((Dpx(i)-YofCenter)^2+(Dpy(i)-XofCenter)^2);endfor j=1:Fpcount    Fpdistant(j)=sqrt((Fpx(j)-YofCenter)^2+(Fpy(j)-XofCenter)^2);end   %------------------特征模板建立----------------------------------------------for i=1:Dpcount    PointOfModel(i,1)=1;%特征端点分类为1    PointOfModel(i,2)=Dpdistant(i);%特征端点相对中心点的距离向量    PointOfModel(i,3)=theta(Dpx(i),Dpy(i))-theta(YofCenter,XofCenter);%特征端点相对中心点的方向向量endfor i=Dpcount+1:Dpcount+Fpcount    PointOfModel(i,1)=2;%特征分叉点分类为2    PointOfModel(i,2)=Fpdistant(i-Dpcount);%特征分叉点相对中心点的距离向量    PointOfModel(i,3)=theta(Fpx(i-Dpcount),Fpy(i-Dpcount))-theta(YofCenter,XofCenter);%特征分叉点相对中心点的方向向量end    %--------------------------------------------------------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.

4.操作步骤与仿真结论

【指纹识别】基于MATLAB/FPGA的指纹识别算法仿真实现_特征点_07

【指纹识别】基于MATLAB/FPGA的指纹识别算法仿真实现_特征点_08


【指纹识别】基于MATLAB/FPGA的指纹识别算法仿真实现_指纹识别_09

  1. FSM模块:其主要的功能是在系统复位后初始化Tx FIFO(发送FIFO),即把随后要发送给SPI传感器的命令写入Tx FIFO内,然后在满足SPI传感器时序的前提下,FSM模块通过控制Tx_rd_en信号读出Tx FIFO里的命令并传送到SPI模块;在Rx FIFO接收指纹数据时,当数满标志位Rx_full_n有效后说明接收FIFO里的数据已满,这时FSM就会通过相关信号来控制SPI停止接收数据,当检测到Rx_empty_n有效后(接收FIFO已空),FSM就会发出相应的信号启动SPI继续接收数据,直到指纹数据全部接收完毕。
  2. Tx FIFO模块:主要功能是在初始化的时候装载待发命令,然后在Tx_rd_en信号的控制下把命令发送出去,因为总的命令数不超过FIFO的深度,所以无须空满标志位。
  3. SPI模块:其主要功能是在与外部传感器通信的时候向传感器提供时钟信号SCK,以及片选信号SS,其中SCK和SS信号最初由FSM产生并由FSM进行控制;当需要向传感器发送命令时,FSM会启动SCK和SS信号,同时SPI接受从Tx FIFO读出的命令并暂存到一个8bit移位寄存器tx_shifter[7:0]中,每过一个SCK周期发送一位到至MOSI,发送完1Byte后tx_shifter会重新装载新命令继续发送直到命令发送完毕;当SPI从传感器接收数据时,FSM会启动SCK和SS信号,SPI中移位寄存器rx_shifter[7:0]会在SCK的上升沿采集输入端口MISO的数据并移一位,每8个SCK时钟周期rx_shifter中的数据就会在FSM的控制下写入Rx FIFO,直到数据接收完毕。
  4. Rx FIFO模块:此模块的主要功能是对已接收到的指纹数据进行缓存,避免指纹的数据丢失,因为此系统中SPI串口的工作频率为5MHz,而UART串口的工作频率为38400Hz,UART从Rx FIFO取数据的速度远小于SPI往Rx FIFO中写数据的速度。Rx FIFO可以向UART和FSM提供数空和数满标志位rx_empty_n,和rx_full_n,因此SPI和UART可以协调工作。
  5. UART模块:些模块主要功能是和计算机进行通信,把接收到的指纹数据通过计算机的终端显示出来。当UART检测到rx_full_n有效后,就会发出读信号Rx_rd_en读出FIFO中的数据发送给计算机,当检测到rx_empty_n有效后停止。


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空