通过学习,掌握以下几个问题:
1、核心算法,并且向GVF衍生;
2、核心库封装的方法
2016年11月16日06:52:51
昨日实现了梯度场和频率场的计算。最大的感觉就是建立基础代码库的重要性。
如果使用opencv或者别的代码库,可能它也能实现一些功能,特别对于建立在感官上的效果,差别不大。但是,如果是用于数学计算的,特别是对于我现在还不是很清楚过程,也不是很清楚结果的算法来说,精确的、容易比对的代码更重要。在这种时候,我更愿意采取原始的、按照定义实现的计算方法。
在昨天的频度场计算中,我突破好几天的困扰,直接按照定义修改代码,比如计算频度场
int main( int argc, char** argv )
{
    Mat src = imread2gray("E:\\template\\1.bmp");
    src.convertTo(src,CV_8U);//255的运算
    pyrDown(src,src);
    Mat dst;//结果
    dst.create(src.size(),src.type());   
 
    int IMGH =src.rows;    
    int IMGW =src.cols;  
    int gradSum;
    int grad;
    long  vx, vy, lvx, lvy;
 
    unsigned char   *lpSrc = NULL;
    unsigned char   *lpOri = NULL;
    long    angle, num;
    double  fAngle;
    int r = 6;
    int i;int j;
    for (int y = 0;y<IMGH-1;y++)
    {
        for (int x=0;x<IMGW-1;x++)
        {
            lpOri = dst.ptr<uchar>(0) + y*IMGW + x;
            lvx = 0;
            lvy = 0;
            num = 0;
            for(i = -r; i <= r; i++)    // 为提高速度,步长为
            {
                if(y+i<1 || y+i>=IMGH-1) continue;
                for(j = -r; j <= r; j++)    // 为提高速度,步长为
                {
                    if(x+j<1 || x+j>=IMGW-1) continue;
                    lpSrc = src.ptr<uchar>(0) + (y+i)*(IMGW) + x+j;
                    //求x方向偏导
                    vx = *(lpSrc + IMGW + 1) - *(lpSrc + IMGW - 1) +
                        *(lpSrc + 1)*2 - *(lpSrc - 1)*2 +
                        *(lpSrc - IMGW + 1) - *(lpSrc - IMGW - 1);
                    //求y方向偏导
                    vy = *(lpSrc + IMGW - 1) - *(lpSrc - IMGW - 1) +
                        *(lpSrc + IMGW)*2 - *(lpSrc - IMGW)*2 +
                        *(lpSrc + IMGW + 1) - *(lpSrc - IMGW + 1);
 
                    lvx += vx * vy * 2;//sin(2sita)
                    lvy += vx*vx - vy*vy;//cos(2sita)
                    num++;
                }
            }
 
            if(num == 0) num = 1;
            // 求弧度
            fAngle = atan2((float)lvy, (float)lvx);
            // 变换到(0 - 2*pi)
            if(fAngle < 0)    fAngle += 2*PI;
 
            // 求纹线角度
            fAngle = (fAngle*EPI*0.5 + 0.5);
            angle = (long)fAngle;
 
            // 因为采用sobel算子,所以角度偏转了度,所以要旋转求得的角度
            angle -= 135;
            // 角度变换到(-180)
            if(angle <= 0)    angle += 180;
 
            angle = 180-angle;
            // 最终纹线角度
            *lpOri = (unsigned char)angle;
            *(lpOri + 1) = (unsigned char)angle;
            *(lpOri + IMGW) = (unsigned char)angle;
            *(lpOri + IMGW + 1) = (unsigned char)angle;
        }
    }
     
    pyrUp(dst,dst);
    imwrite("e:/sandbox/n1dst.bmp",dst);
    return 0;

}

这样从结果的面上来看,已经是非常接近书中给出的效果了。
下一步,专门成立GOGVF项目作为GOCVHelper的一个部分,逐步地改造现有代码库,实现书中的效果。并且向GOGVF的按照定义实现做出努力。
 
2016年11月16日06:52:51 已经逐步移植代码,从梯度一直做到了增强。虽然现在的代码还有一些问题,但是基本不影响使用。并且生成了专门的GOGVF库,用于收集这方面的代码。
虽然这本书很精彩,里面的代码对于我来说都是右开创性的;但是不可否认很多地方,他的代码写的还是比较繁琐、冗余的,给阅读移植带来了不少困难。
使用的情况是这样的
int main( int argc, char** argv )
{
    Mat src = imread2gray("E:\\template\\2.bmp");
    Mat grad = getGrads(src); //梯度场
    Mat org = getOrientMap(src); //方向场
    Mat seg;
    segment(grad,seg); //对梯度场进行阈值,seg为分割结果
    segment_clearEdge(src,org,seg);//反馈到src和org中了,这种方法倒也是方便
    Mat equ = src.clone();
    //cv::equalizeHist(src,equ);
    equalize(src,equ);
    Mat gauss = src.clone();
    GaussSmooth(equ,gauss,0.4);
    Mat smo = src.clone();
    smooth(gauss,smo,1,1);
    orientEnhance(org,smo);
    orientEnhance(org,smo);
    imshow("dst",smo);
    waitKey(0);
    return 0;
}
原始图像
梯度图像,可以看到,在指纹比较密集的地方,梯度很强,而在背景区域,比较干净。
通过梯度场,可以背景前景分离。
方向场。基本上是表示了指纹线段角度的变化。特别观察中间的位置,由255跳跃至0,是因为在中间的部分,指纹几乎是水平的。
  
gaobor增强,现在在细节部分还有一点问题,但是已经基本体现出来特点了。
这是我第一次自己写代码实现gabor的效果,也是深入理解gabor的一次。回头思考,指纹识别其实是很好的算法平台,因为采集到的图片,本身背景前景分割还是比较干净的;在以前,如果处理这样的图片,我可能会选择阈值分割这种直观的方法;在实现了frangi算法之后,很多时候我会拿frangi来实验一下,看看效果。但是这次试用gabor增强,应该说是给我增加了一种新的思路,以后的眼界会更宽阔。。
gaobor增强的核心,是对前面计算出来的梯度场中的“纹线方向进行平滑滤波,纹线的竖直方向进行锐化滤波”
。那么首先就是要计算处正确的梯度场来。在本例中,图片质量比较好,能够通过几乎是定义计算的方法计算出正确稳定的梯度场(但是在其他很多地方,可能不能这样使用?用什么计算出正确的梯度场,作为一个专门的话题)。然后就是通过对梯度进行增强。这里才是实现gaobor的地方。这里贴出的是实现的代码,推导过程分帖说明。关键就是“量化“。
int DDIndex(int angle)
{
    /////////////////////////////////////////////////////////////////////////
    //    angle: [in] 角度 (0 - 180)
    /////////////////////////////////////////////////////////////////////////
    if(angle >= 173 || angle < 8)
    {
        return 0;
    }
    else
    {
        return ((angle-8)/15 + 1);
    }
}
 
void orientEnhance(Mat org,Mat& dst)
{
    int x, y;
    int i;
    int d = 0;
    int sum = 0;
    // 纹线方向上进行平滑滤波的平滑滤波器
    int Hw[7] = {1, 1, 1, 1, 1, 1, 1};
    // 纹线方向的垂直方向上进行锐化滤波的锐化滤波器
    int Vw[7] = {-3, -1, 3, 9, 3, -1, -3};
    int hsum = 0;
    int vsum = 0;
    int temp = 0;
    int IMGW = org.cols;
    int IMGH = org.rows;
 
    BYTE  *lpSrc = NULL;
    BYTE  *lpDir = NULL;
 
    BYTE *g_lpOrient = org.ptr<uchar>(0);
    BYTE *g_lpOrgFinger = dst.ptr<uchar>(0);
    BYTE *g_lpTemp = dst.ptr<uchar>(0);
    //BYTE *g_lpTemp = new BYTE[IMGW * IMGH];
 
    // 纹线方向上进行平滑滤波
    temp = 0;
    for(y = 0; y < IMGH; y++)
    {
        for(x = 0; x < IMGW; x++)
        {
            lpDir = g_lpOrient + temp + x;
            lpSrc = g_lpOrgFinger + temp + x;
            // 纹线方向的索引
            d = DDIndex(*lpDir);
            sum = 0;
            hsum = 0;
            for(i = 0; i < 7; i++)
            {
                if(y+g_DDSite[d][i][1] < 0 || y+g_DDSite[d][i][1] >= IMGH ||
                    x+g_DDSite[d][i][0] < 0 || x+g_DDSite[d][i][0] >= IMGW)
                {
                    continue;
                }
                sum += Hw[i]*(*(lpSrc + g_DDSite[d][i][1]*IMGW + g_DDSite[d][i][0]));
                hsum += Hw[i];
            }
            if(hsum != 0)
            {
                *(g_lpTemp + temp + x) = (BYTE)(sum/hsum);
            }
            else
            {
                *(g_lpTemp + temp + x) = 255;
            }
        }
        temp += IMGW;
    }
 
    // 纹线方向的垂直方向上进行锐化滤波
    temp = 0;
    for(y = 0; y < IMGH; y++)
    {
        for(x = 0; x < IMGW; x++)
        {
            lpDir = g_lpOrient + temp + x;
            lpSrc = g_lpTemp + temp + x;
 
            // 纹线方向的垂直方向的索引
            d = (DDIndex(*lpDir)+6) % 12;
 
            sum = 0;
            vsum = 0;
            for(i = 0; i < 7; i++)
            {
                if(y+g_DDSite[d][i][1] < 0 || y+g_DDSite[d][i][1] >= IMGH ||
                    x+g_DDSite[d][i][0] < 0 || x+g_DDSite[d][i][0] >= IMGW)
                {
                    continue;
                }
                sum += Vw[i]*(*(lpSrc + g_DDSite[d][i][1]*IMGW + g_DDSite[d][i][0]));
                vsum += Vw[i];
            }
            if(vsum > 0)
            {
                sum /= vsum;
                if(sum > 255)
                {
                    *(g_lpOrgFinger + temp + x) = 255;
                }
                else if(sum < 0)
                {
                    *(g_lpOrgFinger + temp + x) = 0;
                }
                else
                {
                    *(g_lpOrgFinger + temp + x) = (BYTE)sum;
                }
            }
            else
            {
                *(g_lpOrgFinger + temp + x) = 255;
            }
        }
        temp += IMGW;
    }
 

}

了现在的代码,下一步就可以思考如何对自然环境下的许多图像进行增强了。
 
 
 
 

精通visual c++指纹模式识别系统算法及实现的更多相关文章

  1. 基于MFC开发的指纹识别系统.

    MFC-FingerPrint 基于MFC开发的指纹识别系统. 效果图如下: 在第12步特征入库中,会对当前指纹的mdl数据与databases中所有的mdl进行对比,然后返回识别结果. 一.载入图像 ...

  2. 企业办公3D指纹考勤系统解决方案(一)

    员工准时.正常出勤是企业考勤制度的基本要求,然而目前签名式.卡钟式.IC卡考勤系统均存在代打卡.人情卡.不易统计等漏洞,而市面上的光学指纹考勤机存在识别能力差.识别速度慢.使用寿命短.不能完全杜绝指纹 ...

  3. 连锁机构3D指纹考勤系统解决方案

    信息技术的高速发展加速了商业零售业连锁经营的信息化和全球化的进程,同时也推动了商业管理的变革.尽管人们对它的认识是被动与滞后的,但这种变革依然伴随着商业业态的转变和信息技术的发展或快或慢地在悄然进行着 ...

  4. 景区3D指纹验证系统解决方案

    旅游业已成为全球经济中发展势头最强劲和规模最大的产业之一.旅游业在城市经济发展中的产业地位.经济作用逐步增强,旅游业对城市经济的拉动性.社会就业的带动力.以及对文化与环境的促进作用日益显现.指纹门票为 ...

  5. 公共交通3D指纹验证系统解决方案

    为了响应国家关于老年人的优待政策,华本研发了退休老人乘公交车指纹认证系统.指纹认证系统不仅方便老人乘坐公交,还能为公共部门减压,杜绝伪造优待证乘坐公交的不法行为. 目前,优待证都是人工检查,缺乏有效的 ...

  6. 工厂食堂3D指纹考勤系统解决方案

    指纹考勤就餐管理系统利用3D活体指纹技术完成对正式员工就餐管理.就餐者只需办理完入职手续,并登记考勤指纹,就可通过考勤指纹在工厂食堂领餐. 大多数工厂食堂就餐是福利性的,只准员工就餐,不准员工带亲戚朋 ...

  7. 企业办公3D指纹考勤系统解决方案

    员工准时.正常出勤是企业考勤制度的基本要求,然而目前签名式.卡钟式.IC卡考勤系统均存在代打卡.人情卡.不易统计等漏洞,而市面上的光学指纹考勤机存在识别能力差.识别速度慢.使用寿命短.不能完全杜绝指纹 ...

  8. Microsoft Visual Studio 2010导致系统C盘不断增大问题处理。

    一直用Microsoft Visual Studio 2010做开发,发现最近C盘空间是越来越小,一开始以为是IE或者一些系统补丁造成的临时文件,但是使用360,windows优化大师之类的软件都清过 ...

  9. Visual Studio 2013 错误系统找不到指定文件,0x80070002

    错误:Visual Studio 2013 按照成功后,可以创建空web项目,但不能建webform 和 mvc 项目. 提示系统找不到指定文件,0x80070002. 解决方式: Step1: Wi ...

随机推荐

  1. php操作mysql

  2. ubuntu14.04+nvidia driver+cuda8+cudnn5+tensorflow0.12

    文章在简书里面编辑的,复制过来貌似不太好看,还是到简书的页面看吧: http://www.jianshu.com/p/c89b97d052b7 1.安装环境简介: 硬件: cpu:i7 6700k g ...

  3. 1.2.1 OC概述

    本文并非最终版本,如想关注更新或更正的内容,详见文末的联系方式,如有疏忽和遗漏,欢迎指正. 本文相关目录:(链接为简书链接) ====================== 所属文集:1.2 Objec ...

  4. mysql数据库表的自增主键号不规律,重新排列

    mysql数据库表的自增主键ID乱了,需要重新排序. 原理:删除原有的自增ID,重新建立新的自增ID. 1.删除原有主键: ALTER TABLE `table_name` DROP `id`; 2. ...

  5. 有关iOS系统中调用相机设备实现二维码扫描功能的注意点(3/3)

    今天我们接着聊聊iOS系统实现二维码扫描的其他注意点. 大家还记得前面我们用到的输出数据的类对象吗?AVCaptureMetadataOutput,就是它!如果我们需要实现目前主流APP扫描二维码的功 ...

  6. linux下的tcp连接超时

    最近需要写一个linux下的通信程序, 通信模块用的是Qt的QTcpSocket. 最后程序需要增加一个断网检测, 在windows下调试没问题, 拔网线, 断网口都能马上检测到, 但到了部署到lin ...

  7. bootstrap之强调文本的类(带颜色)

    bootstrap之强调文本的类(带颜色) <small>本行内容是在标签内</small><br> <strong>本行内容是在标签内</str ...

  8. Qgis连接Oracle

    CMake编译中选择编译Oracle一项以后,编译的qgis才会有连接Oracle数据库的功能. 编译qgis以后,可以通过添加矢量图层中选择Oracle数据库,或是添加Oracle空间图层,或是添加 ...

  9. android webView开发之js调用java代码示例

    1.webView设置 webView.getSettings().setJavaScriptEnabled(true);//设置支持js webView.addJavascriptInterface ...

  10. Tomcat7安装配置 for Ubuntu

    一.环境说明: 操作系统:Ubuntu 12.04.2 LTS Tomcat:apache-tomcat-7.0.52 二.下载 下载地址:http://tomcat.apache.org/ 这里下载 ...