【指纹识别】指纹识别【含GUI Matlab源码 029期】

news2024/12/25 9:08:10

⛄一、指纹识别简介

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

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

指纹图像分割

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

指纹图像二值化

二值化的目的是把灰度指纹图像变成0、1取值的二值图像二值化后处理及细化
由于灰度滤波的不完全性,而且在二值化过程中有时会引入新的噪声,需要对图像进行滤波处理。采用加权中值滤波的方法,根据前景点的不同方向选用不同的权值模板进行滤波,以便于消除纹线上的孔洞和缺口。二值化后的纹线仍然有一定宽度,需要细化为单个像素宽度的骨架。细化算法很多,这里采用骨架提取技术。

⛄二、部分源代码

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_bandsh_bands2)+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

⛄三、运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

⛄四、matlab版本及参考文献

1 matlab版本
2014a

2 参考文献
[1]刘艳华.基于MATLAB/GUI的指纹识别系统设计[J].信息与电脑(理论版). 2021,33(18)

3 备注
简介此部分摘自互联网,仅供参考,若侵权,联系删除

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/77710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IBRNet:基于IBR的NeRF

IBRNet: Learning Multi-View Image-Based Rendering 针对问题&#xff1a;使NeRF具有泛化能力 如何做&#xff1a;主要还是针对颜色和密度的预测进行改进&#xff08;三维重建部分&#xff09;&#xff0c;和NeRF一样&#xff0c;使用的是volume rendering&#xff08;渲染部…

Vulkan下多线程渲染设计

1 Vulkan 视角下的多线程渲染 首先我们需要从vulkan api的顶层框架上来看一下&#xff0c;它在哪些地方可以让我们并行。 Vulkan API的基本框架 Vulkan不同于Gles只有一个&#xff08;不被API暴露出来的&#xff09;单一链条的cmdbuffer处理&#xff0c;它最大的特点是允许多…

阿里巴巴内部:2022年全技术栈PPT分享(架构篇+算法篇+大数据)

我只截图不说话&#xff0c;PPT大全&#xff0c;氛围研发篇、算法篇、大数据、Java后端架构&#xff01;除了大家熟悉的交易、支付场景外&#xff0c;支撑起阿里双十一交易1682亿元的“超级工程”其实包括以下但不限于客服、搜索、推荐、广告、库存、物流、云计算等。 Java核心…

Linux中裸机串口通信的基本方法

大家好&#xff0c; 今天主要和大家聊一聊&#xff0c;如何使用串口进行通信的方法。 目录 第一&#xff1a;串口的基本简介 第二&#xff1a;UART的特点 ​第三&#xff1a;UART的配置步骤 第一&#xff1a;串口的基本简介 串口又叫做串行接口&#xff0c;通常叫做COM接…

农业灌区量测水流量在线监测系统解决方案-灌区信息化管理系统-灌区水网智慧化

平升电子农业灌区量测水流量在线监测系统解决方案/灌区信息化管理系统/灌区水网智慧化&#xff0c;对灌区的渠道水位、流量、水雨情、土壤墒情、气象等信息进行监测&#xff0c;同时对泵站、闸门进行远程控制&#xff0c;对重点区域进行视频监控&#xff0c;实现了信息的采集、…

Docker系统性入门(五)

文章目录Podman安装&基操pod多架构CI/CD容器安全监控Podman Podman 是 Red Hat 在2018年推出的&#xff0c;源代码开放是一个基于 Linux 系统的 daemon-less 的容器引擎&#xff1b;可以运行在root或者非root用户模式最近总听到这个要代替docker什么的&#xff0c;可以参考…

甲骨文蟾蜍 Toad for Oracle 16.2 注册版

使您的 Oracle 数据库操作现代化以实现业务敏捷性。 Toad for Oracle 是唯一一款可帮助您简化工作流程、减少代码缺陷并提高代码质量和性能同时支持团队协作的开发人员工具。自动化管理任务并主动管理您的数据库&#xff0c;同时实现性能优化和风险缓解。快速轻松地定义、搜索…

硬核干货,带你一文掌握 MySQL 的binlog 、redo log、undo log

​hello&#xff0c;大家好。 在MySQL 中我们经常会接触到三个核心日志&#xff0c;它们分别是&#xff1a;binlog 、redo log、undo log。 好多同学对于它们可能并不陌生&#xff0c;但是具体区分起来各自的功能用途以及实现原理&#xff0c;那可能认知就会比较模糊了&#x…

Web前端开发技术课程大作业_ 关于美食的HTML网页设计——HTML+CSS+JavaScript在线美食订餐网站html模板源码30个页面_

&#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计&#x1f469;‍&#x1f393;,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等&#xff0c;用的最多的还是DW&#xff0c;当然不同软件写出的…

Git基础|配置Git账号信息,Git存储的原理详解【建议收藏】

Git作为分布式版本管理&#xff0c;就需要对用户进行认证&#xff0c;账号名和邮箱&#xff0c;方便开发者从不同的电脑进行登录。同时&#xff0c;要想真的记住Git的命令&#xff0c;也必须要清楚Git的存储、上传原理。 Git基础2一、用户签名1、打开命令界面2、进入到用户管理…

CleanMyMac2023最新版软件功能及使用心得教程

电脑明明有100G&#xff0c;但是只剩下几个G&#xff0c;明明已经清理了很多&#xff0c;但是还是没有释放出内存&#xff0c;怎么办&#xff1f;可以试试CleanMyMac X&#xff0c;怎么使用呢&#xff1f;来看看吧&#xff01;CleanMyMac X是一款颇受欢迎的专业清理软件&#x…

【2022.12.10】备战春招Day5——每日一题 + 96. 不同的二叉搜索树

【每日一题】1691. 堆叠长方体的最大高度 题目描述 给你 n 个长方体 cuboids &#xff0c;其中第 i 个长方体的长宽高表示为 cuboids[i] [widthi, lengthi, heighti]&#xff08;下标从 0 开始&#xff09;。请你从 cuboids 选出一个 子集 &#xff0c;并将它们堆叠起来。 如…

​创新不是公司的救命良药

阅读本文大概需要1.06 分钟。之前问说当整个大环境都差的时候&#xff0c;公司还有项目可做就不错了&#xff0c;不要觉得只能赚点小钱就看不上&#xff0c;现在已经从伸手抓钱&#xff0c;变成弯腰捡钱的时代了。 开始赚的钱是不多&#xff0c;但能验证方向&#xff0c;先把跑…

web前端期末大作业 基于HTML+CSS+JavaScript学生宿舍管理系统

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

SSM+Mysql实现的仿网盘系统(功能包含注册登录,文件上传、所有文件、分类资源查看、用户管理、分享资源等)

博客目录SSMMysql实现的仿网盘系统实现功能截图系统功能使用技术代码完整源码SSMMysql实现的仿网盘系统 本系统是一个模拟百度网盘的系统&#xff0c;通过实现了图片/文本文件/视频等资源上传&#xff0c;并且分类管理、资源分享&#xff0c;实现了资源的在线管理。 (文末查看…

Vue2.0开发之——Vue组件-组件属性(34)

一 概述 为Count组件添加自定义属性为自定义属性添加v-bind自定义属性props是只读的自定义属性default默认值自定义属性type值类型自定义属性required必填值 二 为Count组件添加自定义属性 2.1 组件的props props 是组件的自定义属性&#xff0c;在封装通用组件的时候&#…

【Vue核心】6.数据代理

1.回顾Object.defineProperty方法 Object.defineproperty Object.defineproperty 的作用就是直接在一个对象上定义一个新属性&#xff0c;或者修改一个已经存在的属性。Object.defineproperty方法需要传递3个参数&#xff0c;1.属性所在的对象 2.属性的名字 3.一个描述符对象…

Wireshark TS | PMTU 问题实例

前言 PMTU&#xff0c;说到网络上的 PMTU 所能实现的功能&#xff0c;网工对它的原理自然是如数家珍&#xff0c;不熟悉的可能就感觉高大上了&#xff0c;觉得路径 MTU 能自动发现了&#xff0c;自然端到端数据包传输就能避免数据包分片了。可是理想很丰满&#xff0c;现实很骨…

防火墙NAT综合实验——nat控制,豁免,远程,DMZ区域(带命令)

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.实验 实验要求 实验命令 前言 本章将会进行NAT的综合配置…

编程零基础转行Python,往这个方向走,绝对没有错

近几年Python的受欢迎程度可谓是扶摇直上&#xff0c;当然了学习的人也是愈来愈多。一些学习Python的小白在学习初期&#xff0c;总希望能够得到一份Python学习路线图&#xff0c;小编经过多方汇总为大家汇总了一份Python学习路线图。 对于一个零基础的想学习python的朋友来说…