应用笔记

您所在的位置:网站首页 怎样在系统中录入指纹 应用笔记

应用笔记

2023-07-29 16:48| 来源: 网络整理| 查看: 265

应用笔记-Qt 程序中使用 Live 20R 指纹采集器

最近一个项目需要用到指纹认证。就在某东上随便搜了个销量比较大的指纹采集器,就是今天这个笔记的主角(Live 20R 指纹采集器)。花了几天时间研究明白了这个小东西是如何使用的。 这里写图片描述

Live 20R 指纹采集器本身提供了 SDK 开发包,叫做 ZKFinger SDK,我使用的版本是 5.0。这个 SDK 里提供了 ActiveX 接口和 C 语言接口。比较这两个接口的功能会发现 ActiveX 接口提供的功能更强,因此,应该优先使用这个接口。

不过我当时没仔细对比,直接就用了 SDK 中提供的 C 语言接口了。这个功能少了点,但是也够我用了。

简单的说,Live 20R 指纹采集器本身只是个指纹图像获取设备。它可以用来获取指纹图像。其他的功能都是 SDK 软件来实现的。因此我将功能划分到了两个 C++类中:

FingerprintReaderFingerprintCacheDB

FingerprintReader 用于获取指纹。FingerprintCacheDB 实现指纹比对等其他功能。另外还有两个辅助类:

FingerprintEnrollFPCacheDBLoader

FingerprintEnroll 是个辅助类,用于简化指纹登记的代码。FPCacheDBLoader 用于将指纹存入数据库或从数据库中读出。

FingerprintReader

FingerprintReader 这个类直接与硬件打交道。用于获取指纹。里面用到了一个线程,不停的询问Live 20R 指纹采集器是否有新的指纹,如果有则发出一个 Qt 信号 :void onFingerprintReceived(QImage image, QByteArray fpTemplate)。

QByteArray fpTemplate 是从指纹中提取的信息。后面的比对都是用的这个 fpTemplate。指纹图像在后面倒是没什么用的。这里之所以把指纹图像给传出来了,主要是为了在界面上显示出来,看起来比较的酷。

下面直接给代码吧,首先是头文件:

#ifndef FINGERPRINTREADER_H #define FINGERPRINTREADER_H #include #include #include #include #include namespace ZKFP { /** * @brief The FingerprintReader class 这个类完成指纹采集的工作。指纹判别工作由其他类来完成。 */ class FingerprintReader : public QThread { Q_OBJECT public: explicit FingerprintReader(QObject *parent = nullptr); ~FingerprintReader(); /** * @brief getDeviceCount 获取系统中识别出来的指纹识别器的数量 * @return */ int getDeviceCount(); QImage acquireImage(); QString vendorName() const; QString productName() const; QString serialNumber() const; uint16_t getVID() const; uint16_t getPID() const; bool isFakeFuncOn(); QSize imageSize() {return QSize(m_image_width, m_image_height);} signals: /** * @brief onFeatureInfo 取得指纹初始特征时发出该信号 * @param quality 表示该指纹特征的质量 * 0: 好的指纹特征, 1: 特征点不够, 2: 其它原因导致不能取到指纹特征, -1: 可疑 */ void onFeatureInfo(int quality); /** * @brief onFingerTouching 当手指按压纹取像设备时发送该信号。 */ void onFingerTouching(); /** * @brief onFingerLeaving 当手离开压纹取像设备时发送该信号。 */ void onFingerLeaving(); void onCapture(bool result); void onFingerprintReceived(QImage image, QByteArray fpTemplate); void fakeFinger(); public slots: bool openDevice(int index = 0); void closeDevice(); void beginCapture(); void cancelCapture(); /** * @brief setFakeFunc 设置防假开关 * @param on true 表示开启防假指纹功能。 false 表示关闭防假指纹功能。 */ void setFakeFunc(bool on); private: HANDLE m_handle; QString m_vendorName; QString m_productName; QString m_serialNumber; QImage m_fpImage; int m_image_width; int m_image_height; int m_image_size; int m_image_DPI; int m_isFakeOn; uint16_t m_vid; uint16_t m_pid; bool m_init; void run() override; bool isRealFinger(); bool m_stop; }; } #endif // FINGERPRINTREADER_H

接下来是 cpp 文件:

#include "FingerprintReader.h" #include "FingerprintCacheDB.h" #include "ZKFingerReader/libs/include/libzkfp.h" #include namespace ZKFP { static const int ZKFP_IMAGE_WIDTH_RO = 1; static const int ZKFP_IMAGE_HEIGHT_RO = 2; static const int ZKFP_IMAGE_DPI_RW = 3; static const int ZKFP_IMAGE_SIZE_RO = 106; static const int ZKFP_VID_PID_RO = 1015; static const int ZKFP_FAKE_ON_RW = 2002; static const int ZKFP_REAL_FINGER_RO = 2004; static const int ZKFP_VENDOR_NAME_RO = 1101; static const int ZKFP_PRODUCT_NAME = 1102; static const int ZKFP_SERIAL_NUNBER = 1103; //static const int MAX_TEMPLATE_SIZE = 2048; static const int ZKFP_ERR_OK = 0; int autoInitCount = 0; static bool autoInit() { if(autoInitCount == 0) { if( ZKFPM_Init() == 0) { autoInitCount ++; return true; } else { return false; } } return true; } static bool autoTerminate() { autoInitCount --; if(autoInitCount == 0) { return (ZKFPM_Terminate() == 0); } return false; } FingerprintReader::FingerprintReader(QObject *parent) : QThread(parent), m_init(false), m_handle(0), m_image_height(0), m_image_width(0), m_image_size(0), m_vendorName(""), m_productName(""), m_serialNumber(""), m_stop(true) { m_init = autoInit(); qDebug() 0, 0}; length = 4; ZKFPM_GetParameters(m_handle, ZKFP_VID_PID_RO, reinterpret_cast(vid_pid), &length); m_vid = vid_pid[0]; m_pid = vid_pid[1]; qDebug() return m_regTemplate;} signals: void enrollFinished(QByteArray regTemplate); void enrollFailed(); void fingerprintRejected(); void fingerprintAccepted(); public slots: void reset(); bool addFPTemplate(QByteArray fpTemplate); bool addFingerprint(QImage fingerImage, QByteArray fpTemplate); void beginEnroll(ZKFP::FingerprintReader * reader); void cancelEnroll(); private: FingerprintReader * m_reader; FingerprintCacheDB *m_cacheDB; QByteArray m_fpTemplate[3]; QByteArray m_regTemplate; bool m_bRegister; int m_enrollIdx; }; } #endif // FINGERPRINTENROLL_H

之后是 cpp 文件:

#include "FingerprintEnroll.h" #include "FingerprintCacheDB.h" #include "FingerprintReader.h" #include namespace ZKFP { static const int ENROLLCNT = 3; FingerprintEnroll::FingerprintEnroll(FingerprintCacheDB *cacheDB, QObject *parent) : QObject(parent), m_cacheDB(0), m_reader(0), m_enrollIdx(0), m_bRegister(false) { m_cacheDB = cacheDB; } void FingerprintEnroll::setFingerprintCacheDB(FingerprintCacheDB *cacheDB) { m_cacheDB = cacheDB; } void FingerprintEnroll::reset() { if(m_cacheDB && m_reader) { disconnect(m_reader, SIGNAL(onFingerprintReceived(QImage,QByteArray)), this, SLOT(addFingerprint(QImage,QByteArray))); } m_enrollIdx = 0; m_bRegister = false; m_regTemplate.clear(); m_fpTemplate[0].clear(); m_fpTemplate[1].clear(); m_fpTemplate[2].clear(); } void FingerprintEnroll::beginEnroll(FingerprintReader * reader) { reset(); m_reader = reader; if(m_cacheDB && m_reader) { connect(m_reader, SIGNAL(onFingerprintReceived(QImage,QByteArray)), this, SLOT(addFingerprint(QImage,QByteArray))); } m_reader->beginCapture(); } void FingerprintEnroll::cancelEnroll() { reset(); m_reader->cancelCapture(); } bool FingerprintEnroll::addFingerprint(QImage fingerImage, QByteArray fpTemplate) { Q_UNUSED(fingerImage); return addFPTemplate(fpTemplate); } bool FingerprintEnroll::addFPTemplate(QByteArray fpTemplate) { qDebug() 0) { int score = m_cacheDB->verifyFinger(m_fpTemplate[m_enrollIdx - 1], fpTemplate); qDebug()


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3