diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/MainWindowForm.ui b/MainWindowForm.ui
new file mode 100644
index 0000000..79949db
--- /dev/null
+++ b/MainWindowForm.ui
@@ -0,0 +1,123 @@
+
+
+ MainWindowForm
+
+
+
+ 0
+ 0
+ 600
+ 1024
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ background: url(":images/bg_title.png")
+
+
+
+
+ 0
+ 0
+ 600
+ 84
+
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 84
+ 600
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 246
+ 20
+ 108
+ 72
+
+
+
+
+
+
+ images/logo.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
-
+
+
+ TextLabel
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/MainWindowForm.ui b/MainWindowForm.ui
new file mode 100644
index 0000000..79949db
--- /dev/null
+++ b/MainWindowForm.ui
@@ -0,0 +1,123 @@
+
+
+ MainWindowForm
+
+
+
+ 0
+ 0
+ 600
+ 1024
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ background: url(":images/bg_title.png")
+
+
+
+
+ 0
+ 0
+ 600
+ 84
+
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 84
+ 600
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 246
+ 20
+ 108
+ 72
+
+
+
+
+
+
+ images/logo.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
-
+
+
+ TextLabel
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ProMemory.cpp b/ProMemory.cpp
new file mode 100644
index 0000000..0eacecb
--- /dev/null
+++ b/ProMemory.cpp
@@ -0,0 +1,94 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "ProMemory.h"
+
+ProMemory::ProMemory()
+{
+
+}
+
+ProMemory::~ProMemory()
+{
+
+}
+
+void ProMemory::pushCasicIris(CasicIrisInfo irisInfo)
+{
+ mutex.lock();
+ if (this->irisQueue.size() > 10)
+ {
+ QStack empty;
+ std::swap(empty, irisQueue);
+ }
+ irisQueue.push(irisInfo);
+ mutex.unlock();
+}
+CasicIrisInfo ProMemory::popCasicIris()
+{
+ CasicIrisInfo result;
+
+ mutex.lock();
+ if (this->irisQueue.size() > 0)
+ {
+ result = irisQueue.pop();
+ }
+ mutex.unlock();
+
+ return result;
+}
+
+int ProMemory::getIrisQueueSize()
+{
+ int size = 0;
+
+ mutex.lock();
+ size = this->irisQueue.size();
+ mutex.unlock();
+
+ return size;
+}
+bool ProMemory::isIrisQueueEmpty()
+{
+ bool empty = true;
+
+ mutex.lock();
+ empty = this->irisQueue.isEmpty();
+ mutex.unlock();
+
+ return empty;
+}
+void ProMemory::clearIrisQueue()
+{
+ mutex.lock();
+ QStack empty;
+ std::swap(empty, irisQueue);
+ mutex.unlock();
+}
+
+void ProMemory::initIrisFeatures()
+{
+ IrisDataDao irisDao;
+
+ QVector irisDataList = irisDao.findAllRecord();
+ for (QVariantMap iris : irisDataList) {
+ CasicIrisFeature featureLeft;
+ featureLeft.personId = iris.value("person_id").toString();
+ featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray();
+
+ CasicIrisFeature featureRight;
+ featureRight.personId = iris.value("person_id").toString();
+ featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray();
+
+ irisFeatures.append(featureLeft);
+ irisFeatures.append(featureRight);
+ }
+
+ LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString());
+}
+
+QVector ProMemory::getIrisFeatures()
+{
+ return this->irisFeatures;
+}
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/MainWindowForm.ui b/MainWindowForm.ui
new file mode 100644
index 0000000..79949db
--- /dev/null
+++ b/MainWindowForm.ui
@@ -0,0 +1,123 @@
+
+
+ MainWindowForm
+
+
+
+ 0
+ 0
+ 600
+ 1024
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ background: url(":images/bg_title.png")
+
+
+
+
+ 0
+ 0
+ 600
+ 84
+
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 84
+ 600
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 246
+ 20
+ 108
+ 72
+
+
+
+
+
+
+ images/logo.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
-
+
+
+ TextLabel
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ProMemory.cpp b/ProMemory.cpp
new file mode 100644
index 0000000..0eacecb
--- /dev/null
+++ b/ProMemory.cpp
@@ -0,0 +1,94 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "ProMemory.h"
+
+ProMemory::ProMemory()
+{
+
+}
+
+ProMemory::~ProMemory()
+{
+
+}
+
+void ProMemory::pushCasicIris(CasicIrisInfo irisInfo)
+{
+ mutex.lock();
+ if (this->irisQueue.size() > 10)
+ {
+ QStack empty;
+ std::swap(empty, irisQueue);
+ }
+ irisQueue.push(irisInfo);
+ mutex.unlock();
+}
+CasicIrisInfo ProMemory::popCasicIris()
+{
+ CasicIrisInfo result;
+
+ mutex.lock();
+ if (this->irisQueue.size() > 0)
+ {
+ result = irisQueue.pop();
+ }
+ mutex.unlock();
+
+ return result;
+}
+
+int ProMemory::getIrisQueueSize()
+{
+ int size = 0;
+
+ mutex.lock();
+ size = this->irisQueue.size();
+ mutex.unlock();
+
+ return size;
+}
+bool ProMemory::isIrisQueueEmpty()
+{
+ bool empty = true;
+
+ mutex.lock();
+ empty = this->irisQueue.isEmpty();
+ mutex.unlock();
+
+ return empty;
+}
+void ProMemory::clearIrisQueue()
+{
+ mutex.lock();
+ QStack empty;
+ std::swap(empty, irisQueue);
+ mutex.unlock();
+}
+
+void ProMemory::initIrisFeatures()
+{
+ IrisDataDao irisDao;
+
+ QVector irisDataList = irisDao.findAllRecord();
+ for (QVariantMap iris : irisDataList) {
+ CasicIrisFeature featureLeft;
+ featureLeft.personId = iris.value("person_id").toString();
+ featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray();
+
+ CasicIrisFeature featureRight;
+ featureRight.personId = iris.value("person_id").toString();
+ featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray();
+
+ irisFeatures.append(featureLeft);
+ irisFeatures.append(featureRight);
+ }
+
+ LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString());
+}
+
+QVector ProMemory::getIrisFeatures()
+{
+ return this->irisFeatures;
+}
diff --git a/ProMemory.h b/ProMemory.h
new file mode 100644
index 0000000..cf1fe42
--- /dev/null
+++ b/ProMemory.h
@@ -0,0 +1,57 @@
+#ifndef PROMEMORY_H
+#define PROMEMORY_H
+
+#include
+#include
+
+#include "AppConstants.h"
+#include "casic/iris/CasicIrisInfo.h"
+#include "dao/IrisDataDao.h"
+#include "utils/SocketClientUtil.h"
+
+#include "device/IrisCameraController.h"
+#include "device/iris/IrisRecogProcess.h"
+
+class IrisCameraController;
+class IrisRecogProcess;
+
+class ProMemory
+{
+public:
+ ~ProMemory();
+ ProMemory(const ProMemory&)=delete;
+ ProMemory& operator=(const ProMemory&)=delete;
+
+ static ProMemory& getInstance() {
+ static ProMemory instance;
+ return instance;
+ }
+
+ void pushCasicIris(CasicIrisInfo irisInfo);
+ CasicIrisInfo popCasicIris();
+ int getIrisQueueSize();
+ bool isIrisQueueEmpty();
+ void clearIrisQueue();
+
+ volatile int widgeFrame = 0; // 当前显示的界面
+ volatile int appState = 0; // 当前程序所处的状态
+
+ void initIrisFeatures(); // 初始化虹膜特征值集合
+
+ QVector getIrisFeatures();
+
+ IrisCameraController * irisCamCtrl;
+ IrisRecogProcess * irisRecogPro;
+
+ SocketClientUtil client;
+
+private:
+ ProMemory();
+
+ QMutex mutex;
+
+ QStack irisQueue; // 虹膜信息队列
+ QVector irisFeatures; // 虹膜特征值集合
+};
+
+#endif // PROMEMORY_H
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/MainWindowForm.ui b/MainWindowForm.ui
new file mode 100644
index 0000000..79949db
--- /dev/null
+++ b/MainWindowForm.ui
@@ -0,0 +1,123 @@
+
+
+ MainWindowForm
+
+
+
+ 0
+ 0
+ 600
+ 1024
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ background: url(":images/bg_title.png")
+
+
+
+
+ 0
+ 0
+ 600
+ 84
+
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 84
+ 600
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 246
+ 20
+ 108
+ 72
+
+
+
+
+
+
+ images/logo.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
-
+
+
+ TextLabel
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ProMemory.cpp b/ProMemory.cpp
new file mode 100644
index 0000000..0eacecb
--- /dev/null
+++ b/ProMemory.cpp
@@ -0,0 +1,94 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "ProMemory.h"
+
+ProMemory::ProMemory()
+{
+
+}
+
+ProMemory::~ProMemory()
+{
+
+}
+
+void ProMemory::pushCasicIris(CasicIrisInfo irisInfo)
+{
+ mutex.lock();
+ if (this->irisQueue.size() > 10)
+ {
+ QStack empty;
+ std::swap(empty, irisQueue);
+ }
+ irisQueue.push(irisInfo);
+ mutex.unlock();
+}
+CasicIrisInfo ProMemory::popCasicIris()
+{
+ CasicIrisInfo result;
+
+ mutex.lock();
+ if (this->irisQueue.size() > 0)
+ {
+ result = irisQueue.pop();
+ }
+ mutex.unlock();
+
+ return result;
+}
+
+int ProMemory::getIrisQueueSize()
+{
+ int size = 0;
+
+ mutex.lock();
+ size = this->irisQueue.size();
+ mutex.unlock();
+
+ return size;
+}
+bool ProMemory::isIrisQueueEmpty()
+{
+ bool empty = true;
+
+ mutex.lock();
+ empty = this->irisQueue.isEmpty();
+ mutex.unlock();
+
+ return empty;
+}
+void ProMemory::clearIrisQueue()
+{
+ mutex.lock();
+ QStack empty;
+ std::swap(empty, irisQueue);
+ mutex.unlock();
+}
+
+void ProMemory::initIrisFeatures()
+{
+ IrisDataDao irisDao;
+
+ QVector irisDataList = irisDao.findAllRecord();
+ for (QVariantMap iris : irisDataList) {
+ CasicIrisFeature featureLeft;
+ featureLeft.personId = iris.value("person_id").toString();
+ featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray();
+
+ CasicIrisFeature featureRight;
+ featureRight.personId = iris.value("person_id").toString();
+ featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray();
+
+ irisFeatures.append(featureLeft);
+ irisFeatures.append(featureRight);
+ }
+
+ LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString());
+}
+
+QVector ProMemory::getIrisFeatures()
+{
+ return this->irisFeatures;
+}
diff --git a/ProMemory.h b/ProMemory.h
new file mode 100644
index 0000000..cf1fe42
--- /dev/null
+++ b/ProMemory.h
@@ -0,0 +1,57 @@
+#ifndef PROMEMORY_H
+#define PROMEMORY_H
+
+#include
+#include
+
+#include "AppConstants.h"
+#include "casic/iris/CasicIrisInfo.h"
+#include "dao/IrisDataDao.h"
+#include "utils/SocketClientUtil.h"
+
+#include "device/IrisCameraController.h"
+#include "device/iris/IrisRecogProcess.h"
+
+class IrisCameraController;
+class IrisRecogProcess;
+
+class ProMemory
+{
+public:
+ ~ProMemory();
+ ProMemory(const ProMemory&)=delete;
+ ProMemory& operator=(const ProMemory&)=delete;
+
+ static ProMemory& getInstance() {
+ static ProMemory instance;
+ return instance;
+ }
+
+ void pushCasicIris(CasicIrisInfo irisInfo);
+ CasicIrisInfo popCasicIris();
+ int getIrisQueueSize();
+ bool isIrisQueueEmpty();
+ void clearIrisQueue();
+
+ volatile int widgeFrame = 0; // 当前显示的界面
+ volatile int appState = 0; // 当前程序所处的状态
+
+ void initIrisFeatures(); // 初始化虹膜特征值集合
+
+ QVector getIrisFeatures();
+
+ IrisCameraController * irisCamCtrl;
+ IrisRecogProcess * irisRecogPro;
+
+ SocketClientUtil client;
+
+private:
+ ProMemory();
+
+ QMutex mutex;
+
+ QStack irisQueue; // 虹膜信息队列
+ QVector irisFeatures; // 虹膜特征值集合
+};
+
+#endif // PROMEMORY_H
diff --git a/casic/casic.pri b/casic/casic.pri
new file mode 100644
index 0000000..88263a7
--- /dev/null
+++ b/casic/casic.pri
@@ -0,0 +1,2 @@
+include(iris/casicIris.pri)
+
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/MainWindowForm.ui b/MainWindowForm.ui
new file mode 100644
index 0000000..79949db
--- /dev/null
+++ b/MainWindowForm.ui
@@ -0,0 +1,123 @@
+
+
+ MainWindowForm
+
+
+
+ 0
+ 0
+ 600
+ 1024
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ background: url(":images/bg_title.png")
+
+
+
+
+ 0
+ 0
+ 600
+ 84
+
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 84
+ 600
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 246
+ 20
+ 108
+ 72
+
+
+
+
+
+
+ images/logo.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
-
+
+
+ TextLabel
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ProMemory.cpp b/ProMemory.cpp
new file mode 100644
index 0000000..0eacecb
--- /dev/null
+++ b/ProMemory.cpp
@@ -0,0 +1,94 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "ProMemory.h"
+
+ProMemory::ProMemory()
+{
+
+}
+
+ProMemory::~ProMemory()
+{
+
+}
+
+void ProMemory::pushCasicIris(CasicIrisInfo irisInfo)
+{
+ mutex.lock();
+ if (this->irisQueue.size() > 10)
+ {
+ QStack empty;
+ std::swap(empty, irisQueue);
+ }
+ irisQueue.push(irisInfo);
+ mutex.unlock();
+}
+CasicIrisInfo ProMemory::popCasicIris()
+{
+ CasicIrisInfo result;
+
+ mutex.lock();
+ if (this->irisQueue.size() > 0)
+ {
+ result = irisQueue.pop();
+ }
+ mutex.unlock();
+
+ return result;
+}
+
+int ProMemory::getIrisQueueSize()
+{
+ int size = 0;
+
+ mutex.lock();
+ size = this->irisQueue.size();
+ mutex.unlock();
+
+ return size;
+}
+bool ProMemory::isIrisQueueEmpty()
+{
+ bool empty = true;
+
+ mutex.lock();
+ empty = this->irisQueue.isEmpty();
+ mutex.unlock();
+
+ return empty;
+}
+void ProMemory::clearIrisQueue()
+{
+ mutex.lock();
+ QStack empty;
+ std::swap(empty, irisQueue);
+ mutex.unlock();
+}
+
+void ProMemory::initIrisFeatures()
+{
+ IrisDataDao irisDao;
+
+ QVector irisDataList = irisDao.findAllRecord();
+ for (QVariantMap iris : irisDataList) {
+ CasicIrisFeature featureLeft;
+ featureLeft.personId = iris.value("person_id").toString();
+ featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray();
+
+ CasicIrisFeature featureRight;
+ featureRight.personId = iris.value("person_id").toString();
+ featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray();
+
+ irisFeatures.append(featureLeft);
+ irisFeatures.append(featureRight);
+ }
+
+ LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString());
+}
+
+QVector ProMemory::getIrisFeatures()
+{
+ return this->irisFeatures;
+}
diff --git a/ProMemory.h b/ProMemory.h
new file mode 100644
index 0000000..cf1fe42
--- /dev/null
+++ b/ProMemory.h
@@ -0,0 +1,57 @@
+#ifndef PROMEMORY_H
+#define PROMEMORY_H
+
+#include
+#include
+
+#include "AppConstants.h"
+#include "casic/iris/CasicIrisInfo.h"
+#include "dao/IrisDataDao.h"
+#include "utils/SocketClientUtil.h"
+
+#include "device/IrisCameraController.h"
+#include "device/iris/IrisRecogProcess.h"
+
+class IrisCameraController;
+class IrisRecogProcess;
+
+class ProMemory
+{
+public:
+ ~ProMemory();
+ ProMemory(const ProMemory&)=delete;
+ ProMemory& operator=(const ProMemory&)=delete;
+
+ static ProMemory& getInstance() {
+ static ProMemory instance;
+ return instance;
+ }
+
+ void pushCasicIris(CasicIrisInfo irisInfo);
+ CasicIrisInfo popCasicIris();
+ int getIrisQueueSize();
+ bool isIrisQueueEmpty();
+ void clearIrisQueue();
+
+ volatile int widgeFrame = 0; // 当前显示的界面
+ volatile int appState = 0; // 当前程序所处的状态
+
+ void initIrisFeatures(); // 初始化虹膜特征值集合
+
+ QVector getIrisFeatures();
+
+ IrisCameraController * irisCamCtrl;
+ IrisRecogProcess * irisRecogPro;
+
+ SocketClientUtil client;
+
+private:
+ ProMemory();
+
+ QMutex mutex;
+
+ QStack irisQueue; // 虹膜信息队列
+ QVector irisFeatures; // 虹膜特征值集合
+};
+
+#endif // PROMEMORY_H
diff --git a/casic/casic.pri b/casic/casic.pri
new file mode 100644
index 0000000..88263a7
--- /dev/null
+++ b/casic/casic.pri
@@ -0,0 +1,2 @@
+include(iris/casicIris.pri)
+
diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h
new file mode 100644
index 0000000..e3c0735
--- /dev/null
+++ b/casic/iris/CasicIrisInfo.h
@@ -0,0 +1,38 @@
+#ifndef CASICIRISINFO_H
+#define CASICIRISINFO_H
+
+#include
+#include
+#include "CasicSegResult.h"
+
+struct CasicIrisInfo
+{
+ // 是否有眼睛, 默认为false
+ bool hasEye = false;
+
+ // post process
+ bool postProcSucc = false;
+
+ // 眼部图像
+ // 后续计算需要使用
+ cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图
+
+ cv::Mat maskNorm;
+ cv::Mat irisCode;
+
+ iristrt::CasicSegResult segResult;
+
+ // 字节数组形式的特征码
+ QByteArray irisFeatureCode;
+};
+
+struct CasicIrisFeature
+{
+ int irisId;
+ QString personId;
+ cv::Mat irisCode;
+ cv::Mat maskNorm;
+ QByteArray irisFeatureCode;
+};
+
+#endif // CASICIRISINFO_H
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/MainWindowForm.ui b/MainWindowForm.ui
new file mode 100644
index 0000000..79949db
--- /dev/null
+++ b/MainWindowForm.ui
@@ -0,0 +1,123 @@
+
+
+ MainWindowForm
+
+
+
+ 0
+ 0
+ 600
+ 1024
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ background: url(":images/bg_title.png")
+
+
+
+
+ 0
+ 0
+ 600
+ 84
+
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 84
+ 600
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 246
+ 20
+ 108
+ 72
+
+
+
+
+
+
+ images/logo.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
-
+
+
+ TextLabel
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ProMemory.cpp b/ProMemory.cpp
new file mode 100644
index 0000000..0eacecb
--- /dev/null
+++ b/ProMemory.cpp
@@ -0,0 +1,94 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "ProMemory.h"
+
+ProMemory::ProMemory()
+{
+
+}
+
+ProMemory::~ProMemory()
+{
+
+}
+
+void ProMemory::pushCasicIris(CasicIrisInfo irisInfo)
+{
+ mutex.lock();
+ if (this->irisQueue.size() > 10)
+ {
+ QStack empty;
+ std::swap(empty, irisQueue);
+ }
+ irisQueue.push(irisInfo);
+ mutex.unlock();
+}
+CasicIrisInfo ProMemory::popCasicIris()
+{
+ CasicIrisInfo result;
+
+ mutex.lock();
+ if (this->irisQueue.size() > 0)
+ {
+ result = irisQueue.pop();
+ }
+ mutex.unlock();
+
+ return result;
+}
+
+int ProMemory::getIrisQueueSize()
+{
+ int size = 0;
+
+ mutex.lock();
+ size = this->irisQueue.size();
+ mutex.unlock();
+
+ return size;
+}
+bool ProMemory::isIrisQueueEmpty()
+{
+ bool empty = true;
+
+ mutex.lock();
+ empty = this->irisQueue.isEmpty();
+ mutex.unlock();
+
+ return empty;
+}
+void ProMemory::clearIrisQueue()
+{
+ mutex.lock();
+ QStack empty;
+ std::swap(empty, irisQueue);
+ mutex.unlock();
+}
+
+void ProMemory::initIrisFeatures()
+{
+ IrisDataDao irisDao;
+
+ QVector irisDataList = irisDao.findAllRecord();
+ for (QVariantMap iris : irisDataList) {
+ CasicIrisFeature featureLeft;
+ featureLeft.personId = iris.value("person_id").toString();
+ featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray();
+
+ CasicIrisFeature featureRight;
+ featureRight.personId = iris.value("person_id").toString();
+ featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray();
+
+ irisFeatures.append(featureLeft);
+ irisFeatures.append(featureRight);
+ }
+
+ LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString());
+}
+
+QVector ProMemory::getIrisFeatures()
+{
+ return this->irisFeatures;
+}
diff --git a/ProMemory.h b/ProMemory.h
new file mode 100644
index 0000000..cf1fe42
--- /dev/null
+++ b/ProMemory.h
@@ -0,0 +1,57 @@
+#ifndef PROMEMORY_H
+#define PROMEMORY_H
+
+#include
+#include
+
+#include "AppConstants.h"
+#include "casic/iris/CasicIrisInfo.h"
+#include "dao/IrisDataDao.h"
+#include "utils/SocketClientUtil.h"
+
+#include "device/IrisCameraController.h"
+#include "device/iris/IrisRecogProcess.h"
+
+class IrisCameraController;
+class IrisRecogProcess;
+
+class ProMemory
+{
+public:
+ ~ProMemory();
+ ProMemory(const ProMemory&)=delete;
+ ProMemory& operator=(const ProMemory&)=delete;
+
+ static ProMemory& getInstance() {
+ static ProMemory instance;
+ return instance;
+ }
+
+ void pushCasicIris(CasicIrisInfo irisInfo);
+ CasicIrisInfo popCasicIris();
+ int getIrisQueueSize();
+ bool isIrisQueueEmpty();
+ void clearIrisQueue();
+
+ volatile int widgeFrame = 0; // 当前显示的界面
+ volatile int appState = 0; // 当前程序所处的状态
+
+ void initIrisFeatures(); // 初始化虹膜特征值集合
+
+ QVector getIrisFeatures();
+
+ IrisCameraController * irisCamCtrl;
+ IrisRecogProcess * irisRecogPro;
+
+ SocketClientUtil client;
+
+private:
+ ProMemory();
+
+ QMutex mutex;
+
+ QStack irisQueue; // 虹膜信息队列
+ QVector irisFeatures; // 虹膜特征值集合
+};
+
+#endif // PROMEMORY_H
diff --git a/casic/casic.pri b/casic/casic.pri
new file mode 100644
index 0000000..88263a7
--- /dev/null
+++ b/casic/casic.pri
@@ -0,0 +1,2 @@
+include(iris/casicIris.pri)
+
diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h
new file mode 100644
index 0000000..e3c0735
--- /dev/null
+++ b/casic/iris/CasicIrisInfo.h
@@ -0,0 +1,38 @@
+#ifndef CASICIRISINFO_H
+#define CASICIRISINFO_H
+
+#include
+#include
+#include "CasicSegResult.h"
+
+struct CasicIrisInfo
+{
+ // 是否有眼睛, 默认为false
+ bool hasEye = false;
+
+ // post process
+ bool postProcSucc = false;
+
+ // 眼部图像
+ // 后续计算需要使用
+ cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图
+
+ cv::Mat maskNorm;
+ cv::Mat irisCode;
+
+ iristrt::CasicSegResult segResult;
+
+ // 字节数组形式的特征码
+ QByteArray irisFeatureCode;
+};
+
+struct CasicIrisFeature
+{
+ int irisId;
+ QString personId;
+ cv::Mat irisCode;
+ cv::Mat maskNorm;
+ QByteArray irisFeatureCode;
+};
+
+#endif // CASICIRISINFO_H
diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp
new file mode 100644
index 0000000..5803f44
--- /dev/null
+++ b/casic/iris/CasicIrisInterface.cpp
@@ -0,0 +1,234 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "CasicIrisInterface.h"
+
+#include
+#include
+#include
+
+casic::iris::CasicIrisInterface::CasicIrisInterface()
+{
+ rec = iristrt::CasicIrisRec(gaborFilterFileName, applicationPointsFileName);
+
+ cascade = new cv::CascadeClassifier();
+ cascade->load(cascadeName);
+}
+
+casic::iris::CasicIrisInterface::~CasicIrisInterface()
+{
+
+}
+
+void casic::iris::CasicIrisInterface::setCascadeFile(QString filename)
+{
+ this->cascadeName = filename.toStdString();
+}
+void casic::iris::CasicIrisInterface::setMinEyeSize(int minEyeSize)
+{
+ this->minEyeSize = minEyeSize;
+}
+void casic::iris::CasicIrisInterface::setMaxEyeSize(int maxEyeSize)
+{
+ this->maxEyeSize = maxEyeSize;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::findEye(CasicIrisInfo irisInfo)
+{
+ // 构建OpenCV自带的眼睛分类器
+ if (this->cascade == nullptr) {
+ this->cascade = new cv::CascadeClassifier();
+ this->cascade->load(cascadeName);
+ }
+
+ QElapsedTimer timer;
+ timer.start();
+
+ std::vector rect;
+ cv::Size minEyeRectSize(minEyeSize, minEyeSize);
+ cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize);
+
+ // ★分类器对象调用
+ cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize);
+
+ if (rect.size() == 0)
+ {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+// LOG(DEBUG) << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString();
+// LOG_DEBUG(QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString());
+ qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+ .arg(timer.elapsed()).arg(rect.size())
+ .arg(rect.at(0).x).arg(rect.at(0).y)
+ .arg(rect.at(0).width).arg(rect.at(0).height);
+
+ irisInfo.hasEye = true;
+// irisInfo.eyeRect = rect.at(0);
+
+// irisInfo.data = ImageUtil::MatImageToQImage(irisInfo.matData);
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::findAndCutEye(CasicIrisInfo irisInfo)
+{
+ // 构建OpenCV自带的眼睛分类器
+ if (this->cascade == nullptr) {
+ this->cascade = new cv::CascadeClassifier();
+ this->cascade->load(cascadeName);
+ }
+
+ std::vector rect;
+ cv::Size minEyeRectSize(minEyeSize, minEyeSize);
+ cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize);
+
+ if (irisInfo.matData.empty() == true) {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+ // ★分类器对象调用
+ cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize);
+
+ if (rect.size() == 0)
+ {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+// LOG(DEBUG) << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString();
+// LOG_DEBUG(QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString());
+ qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]")
+ .arg(rect.size())
+ .arg(rect.at(0).x).arg(rect.at(0).y)
+ .arg(rect.at(0).width).arg(rect.at(0).height);
+
+ // 找到眼睛之后, 将眼部裁剪下来, 图像拉伸到640 * 480
+ cv::Point center;
+ center.x = cvFloor(rect.at(0).x + rect.at(0).width*0.5);
+ center.y = cvFloor(rect.at(0).y + rect.at(0).height*0.5);
+
+ // 限制中心点的范围
+ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5)
+ {
+ // x小于240则x=240
+ center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5;
+ } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) {
+ // x大于1040则x=1040
+ center.x = SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5;
+ }
+
+ if (center.y < SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5)
+ {
+ // y小于180则y=180
+ center.y = SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5;
+ } else if (center.y > SettingConfig::getInstance().IRIS_FRAME_HEIGHT - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5) {
+ center.y = SettingConfig::getInstance().IRIS_FRAME_HEIGHT - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5;
+ }
+
+ // 裁剪眼部图像
+ cv::Mat cutSize = irisInfo.matData.clone();
+ cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5,
+ center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5,
+ SettingConfig::getInstance().IRIS_WIDTH * cutRatio,
+ SettingConfig::getInstance().IRIS_HEIGHT * cutRatio));
+
+ // 裁剪后放大到 640 * 480
+ cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT));
+ cv::flip(cutSize, cutSize, 1); // 左右翻转
+
+ irisInfo.hasEye = true;
+ irisInfo.postProcSucc = false;
+ irisInfo.matData = cutSize;
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::irisQualityAssess(CasicIrisInfo irisInfo)
+{
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo)
+{
+// std::vector irisCircle, pupilCircle; // x,y,r
+ std::vector irisCircle(0); // x,y,r
+ std::vector pupilCircle(0); // x,y,r
+ iristrt::CasicSegPostProcess segPost;
+
+ cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+ cv::resize(irisInfo.segResult.innerMask, irisInfo.segResult.innerMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+ cv::resize(irisInfo.segResult.outerCircle, irisInfo.segResult.outerCircle,cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+
+ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle);
+ if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0)
+ {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+// std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl;
+ int iris_x = irisCircle[0];
+ int iris_y = irisCircle[1];
+ int iris_r = irisCircle[2];
+ int pupil_x = pupilCircle[0];
+ int pupil_y = pupilCircle[1];
+ int pupil_r = pupilCircle[2];
+ int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y);
+ if(!(dis + pupil_r < iris_r))
+ {
+ // pupil circle doesn't contained in iris circle
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+
+ cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]);
+ if (imageNorm.empty() == true) {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+ irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]);
+ if (irisInfo.maskNorm.empty() == true)
+ {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+// std::cout << "finish normalize" << std::endl;
+// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm);
+
+ irisInfo.irisCode = rec.encodeToImage(imageNorm);
+ irisInfo.postProcSucc = true;
+
+ return irisInfo;
+}
+
+QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo)
+{
+ QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm);
+ return irisFeatureCode;
+}
+
+float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo)
+{
+ return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm);
+}
+
+float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other)
+{
+ return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data()));
+}
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/MainWindowForm.ui b/MainWindowForm.ui
new file mode 100644
index 0000000..79949db
--- /dev/null
+++ b/MainWindowForm.ui
@@ -0,0 +1,123 @@
+
+
+ MainWindowForm
+
+
+
+ 0
+ 0
+ 600
+ 1024
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ background: url(":images/bg_title.png")
+
+
+
+
+ 0
+ 0
+ 600
+ 84
+
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 84
+ 600
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 246
+ 20
+ 108
+ 72
+
+
+
+
+
+
+ images/logo.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
-
+
+
+ TextLabel
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ProMemory.cpp b/ProMemory.cpp
new file mode 100644
index 0000000..0eacecb
--- /dev/null
+++ b/ProMemory.cpp
@@ -0,0 +1,94 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "ProMemory.h"
+
+ProMemory::ProMemory()
+{
+
+}
+
+ProMemory::~ProMemory()
+{
+
+}
+
+void ProMemory::pushCasicIris(CasicIrisInfo irisInfo)
+{
+ mutex.lock();
+ if (this->irisQueue.size() > 10)
+ {
+ QStack empty;
+ std::swap(empty, irisQueue);
+ }
+ irisQueue.push(irisInfo);
+ mutex.unlock();
+}
+CasicIrisInfo ProMemory::popCasicIris()
+{
+ CasicIrisInfo result;
+
+ mutex.lock();
+ if (this->irisQueue.size() > 0)
+ {
+ result = irisQueue.pop();
+ }
+ mutex.unlock();
+
+ return result;
+}
+
+int ProMemory::getIrisQueueSize()
+{
+ int size = 0;
+
+ mutex.lock();
+ size = this->irisQueue.size();
+ mutex.unlock();
+
+ return size;
+}
+bool ProMemory::isIrisQueueEmpty()
+{
+ bool empty = true;
+
+ mutex.lock();
+ empty = this->irisQueue.isEmpty();
+ mutex.unlock();
+
+ return empty;
+}
+void ProMemory::clearIrisQueue()
+{
+ mutex.lock();
+ QStack empty;
+ std::swap(empty, irisQueue);
+ mutex.unlock();
+}
+
+void ProMemory::initIrisFeatures()
+{
+ IrisDataDao irisDao;
+
+ QVector irisDataList = irisDao.findAllRecord();
+ for (QVariantMap iris : irisDataList) {
+ CasicIrisFeature featureLeft;
+ featureLeft.personId = iris.value("person_id").toString();
+ featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray();
+
+ CasicIrisFeature featureRight;
+ featureRight.personId = iris.value("person_id").toString();
+ featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray();
+
+ irisFeatures.append(featureLeft);
+ irisFeatures.append(featureRight);
+ }
+
+ LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString());
+}
+
+QVector ProMemory::getIrisFeatures()
+{
+ return this->irisFeatures;
+}
diff --git a/ProMemory.h b/ProMemory.h
new file mode 100644
index 0000000..cf1fe42
--- /dev/null
+++ b/ProMemory.h
@@ -0,0 +1,57 @@
+#ifndef PROMEMORY_H
+#define PROMEMORY_H
+
+#include
+#include
+
+#include "AppConstants.h"
+#include "casic/iris/CasicIrisInfo.h"
+#include "dao/IrisDataDao.h"
+#include "utils/SocketClientUtil.h"
+
+#include "device/IrisCameraController.h"
+#include "device/iris/IrisRecogProcess.h"
+
+class IrisCameraController;
+class IrisRecogProcess;
+
+class ProMemory
+{
+public:
+ ~ProMemory();
+ ProMemory(const ProMemory&)=delete;
+ ProMemory& operator=(const ProMemory&)=delete;
+
+ static ProMemory& getInstance() {
+ static ProMemory instance;
+ return instance;
+ }
+
+ void pushCasicIris(CasicIrisInfo irisInfo);
+ CasicIrisInfo popCasicIris();
+ int getIrisQueueSize();
+ bool isIrisQueueEmpty();
+ void clearIrisQueue();
+
+ volatile int widgeFrame = 0; // 当前显示的界面
+ volatile int appState = 0; // 当前程序所处的状态
+
+ void initIrisFeatures(); // 初始化虹膜特征值集合
+
+ QVector getIrisFeatures();
+
+ IrisCameraController * irisCamCtrl;
+ IrisRecogProcess * irisRecogPro;
+
+ SocketClientUtil client;
+
+private:
+ ProMemory();
+
+ QMutex mutex;
+
+ QStack irisQueue; // 虹膜信息队列
+ QVector irisFeatures; // 虹膜特征值集合
+};
+
+#endif // PROMEMORY_H
diff --git a/casic/casic.pri b/casic/casic.pri
new file mode 100644
index 0000000..88263a7
--- /dev/null
+++ b/casic/casic.pri
@@ -0,0 +1,2 @@
+include(iris/casicIris.pri)
+
diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h
new file mode 100644
index 0000000..e3c0735
--- /dev/null
+++ b/casic/iris/CasicIrisInfo.h
@@ -0,0 +1,38 @@
+#ifndef CASICIRISINFO_H
+#define CASICIRISINFO_H
+
+#include
+#include
+#include "CasicSegResult.h"
+
+struct CasicIrisInfo
+{
+ // 是否有眼睛, 默认为false
+ bool hasEye = false;
+
+ // post process
+ bool postProcSucc = false;
+
+ // 眼部图像
+ // 后续计算需要使用
+ cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图
+
+ cv::Mat maskNorm;
+ cv::Mat irisCode;
+
+ iristrt::CasicSegResult segResult;
+
+ // 字节数组形式的特征码
+ QByteArray irisFeatureCode;
+};
+
+struct CasicIrisFeature
+{
+ int irisId;
+ QString personId;
+ cv::Mat irisCode;
+ cv::Mat maskNorm;
+ QByteArray irisFeatureCode;
+};
+
+#endif // CASICIRISINFO_H
diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp
new file mode 100644
index 0000000..5803f44
--- /dev/null
+++ b/casic/iris/CasicIrisInterface.cpp
@@ -0,0 +1,234 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "CasicIrisInterface.h"
+
+#include
+#include
+#include
+
+casic::iris::CasicIrisInterface::CasicIrisInterface()
+{
+ rec = iristrt::CasicIrisRec(gaborFilterFileName, applicationPointsFileName);
+
+ cascade = new cv::CascadeClassifier();
+ cascade->load(cascadeName);
+}
+
+casic::iris::CasicIrisInterface::~CasicIrisInterface()
+{
+
+}
+
+void casic::iris::CasicIrisInterface::setCascadeFile(QString filename)
+{
+ this->cascadeName = filename.toStdString();
+}
+void casic::iris::CasicIrisInterface::setMinEyeSize(int minEyeSize)
+{
+ this->minEyeSize = minEyeSize;
+}
+void casic::iris::CasicIrisInterface::setMaxEyeSize(int maxEyeSize)
+{
+ this->maxEyeSize = maxEyeSize;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::findEye(CasicIrisInfo irisInfo)
+{
+ // 构建OpenCV自带的眼睛分类器
+ if (this->cascade == nullptr) {
+ this->cascade = new cv::CascadeClassifier();
+ this->cascade->load(cascadeName);
+ }
+
+ QElapsedTimer timer;
+ timer.start();
+
+ std::vector rect;
+ cv::Size minEyeRectSize(minEyeSize, minEyeSize);
+ cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize);
+
+ // ★分类器对象调用
+ cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize);
+
+ if (rect.size() == 0)
+ {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+// LOG(DEBUG) << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString();
+// LOG_DEBUG(QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString());
+ qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+ .arg(timer.elapsed()).arg(rect.size())
+ .arg(rect.at(0).x).arg(rect.at(0).y)
+ .arg(rect.at(0).width).arg(rect.at(0).height);
+
+ irisInfo.hasEye = true;
+// irisInfo.eyeRect = rect.at(0);
+
+// irisInfo.data = ImageUtil::MatImageToQImage(irisInfo.matData);
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::findAndCutEye(CasicIrisInfo irisInfo)
+{
+ // 构建OpenCV自带的眼睛分类器
+ if (this->cascade == nullptr) {
+ this->cascade = new cv::CascadeClassifier();
+ this->cascade->load(cascadeName);
+ }
+
+ std::vector rect;
+ cv::Size minEyeRectSize(minEyeSize, minEyeSize);
+ cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize);
+
+ if (irisInfo.matData.empty() == true) {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+ // ★分类器对象调用
+ cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize);
+
+ if (rect.size() == 0)
+ {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+// LOG(DEBUG) << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString();
+// LOG_DEBUG(QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString());
+ qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]")
+ .arg(rect.size())
+ .arg(rect.at(0).x).arg(rect.at(0).y)
+ .arg(rect.at(0).width).arg(rect.at(0).height);
+
+ // 找到眼睛之后, 将眼部裁剪下来, 图像拉伸到640 * 480
+ cv::Point center;
+ center.x = cvFloor(rect.at(0).x + rect.at(0).width*0.5);
+ center.y = cvFloor(rect.at(0).y + rect.at(0).height*0.5);
+
+ // 限制中心点的范围
+ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5)
+ {
+ // x小于240则x=240
+ center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5;
+ } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) {
+ // x大于1040则x=1040
+ center.x = SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5;
+ }
+
+ if (center.y < SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5)
+ {
+ // y小于180则y=180
+ center.y = SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5;
+ } else if (center.y > SettingConfig::getInstance().IRIS_FRAME_HEIGHT - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5) {
+ center.y = SettingConfig::getInstance().IRIS_FRAME_HEIGHT - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5;
+ }
+
+ // 裁剪眼部图像
+ cv::Mat cutSize = irisInfo.matData.clone();
+ cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5,
+ center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5,
+ SettingConfig::getInstance().IRIS_WIDTH * cutRatio,
+ SettingConfig::getInstance().IRIS_HEIGHT * cutRatio));
+
+ // 裁剪后放大到 640 * 480
+ cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT));
+ cv::flip(cutSize, cutSize, 1); // 左右翻转
+
+ irisInfo.hasEye = true;
+ irisInfo.postProcSucc = false;
+ irisInfo.matData = cutSize;
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::irisQualityAssess(CasicIrisInfo irisInfo)
+{
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo)
+{
+// std::vector irisCircle, pupilCircle; // x,y,r
+ std::vector irisCircle(0); // x,y,r
+ std::vector pupilCircle(0); // x,y,r
+ iristrt::CasicSegPostProcess segPost;
+
+ cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+ cv::resize(irisInfo.segResult.innerMask, irisInfo.segResult.innerMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+ cv::resize(irisInfo.segResult.outerCircle, irisInfo.segResult.outerCircle,cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+
+ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle);
+ if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0)
+ {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+// std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl;
+ int iris_x = irisCircle[0];
+ int iris_y = irisCircle[1];
+ int iris_r = irisCircle[2];
+ int pupil_x = pupilCircle[0];
+ int pupil_y = pupilCircle[1];
+ int pupil_r = pupilCircle[2];
+ int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y);
+ if(!(dis + pupil_r < iris_r))
+ {
+ // pupil circle doesn't contained in iris circle
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+
+ cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]);
+ if (imageNorm.empty() == true) {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+ irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]);
+ if (irisInfo.maskNorm.empty() == true)
+ {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+// std::cout << "finish normalize" << std::endl;
+// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm);
+
+ irisInfo.irisCode = rec.encodeToImage(imageNorm);
+ irisInfo.postProcSucc = true;
+
+ return irisInfo;
+}
+
+QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo)
+{
+ QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm);
+ return irisFeatureCode;
+}
+
+float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo)
+{
+ return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm);
+}
+
+float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other)
+{
+ return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data()));
+}
diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h
new file mode 100644
index 0000000..7f91d68
--- /dev/null
+++ b/casic/iris/CasicIrisInterface.h
@@ -0,0 +1,54 @@
+#ifndef CASICIRISINTERFACE_H
+#define CASICIRISINTERFACE_H
+
+#include "CasicIrisInfo.h"
+#include "CasicSegPostProcess.h"
+#include "CasicIrisUtil.h"
+#include "CasicIrisRec.h"
+#include "utils/UtilInclude.h"
+
+namespace casic {
+ namespace iris {
+ class CasicIrisInterface
+ {
+ public:
+ ~CasicIrisInterface();
+ CasicIrisInterface(const CasicIrisInterface&)=delete;
+ CasicIrisInterface& operator=(const CasicIrisInterface&)=delete;
+
+ static CasicIrisInterface& getInstance() {
+ static CasicIrisInterface instance;
+ return instance;
+ }
+
+ CasicIrisInfo findEye(CasicIrisInfo irisInfo);
+ CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo);
+ CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo);
+
+ CasicIrisInfo irisEncode(CasicIrisInfo irisInfo);
+ QByteArray extractFeature(CasicIrisInfo irisInfo);
+ float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo);
+ float calculatePairPoints(QByteArray feature, QByteArray other);
+
+ void setCascadeFile(QString filename);
+ void setMinEyeSize(int minEyeSize);
+ void setMaxEyeSize(int maxEyeSize);
+
+ private:
+ CasicIrisInterface();
+
+ std::string cascadeName = "./model/haarcascade_eye.xml";
+ const char * gaborFilterFileName = "./model/filters.txt";
+ const char * applicationPointsFileName = "./model/points.txt";
+ int minEyeSize = 320;
+ int maxEyeSize = 480;
+ float cutRatio = 0.72f; // 裁剪比率 用于裁剪更大比例的眼部图像
+
+ cv::CascadeClassifier * cascade;
+ iristrt::CasicIrisRec rec;
+ };
+ }
+}
+
+
+#endif // CASICIRISINTERFACE_H
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/MainWindowForm.ui b/MainWindowForm.ui
new file mode 100644
index 0000000..79949db
--- /dev/null
+++ b/MainWindowForm.ui
@@ -0,0 +1,123 @@
+
+
+ MainWindowForm
+
+
+
+ 0
+ 0
+ 600
+ 1024
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ background: url(":images/bg_title.png")
+
+
+
+
+ 0
+ 0
+ 600
+ 84
+
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 84
+ 600
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 246
+ 20
+ 108
+ 72
+
+
+
+
+
+
+ images/logo.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
-
+
+
+ TextLabel
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ProMemory.cpp b/ProMemory.cpp
new file mode 100644
index 0000000..0eacecb
--- /dev/null
+++ b/ProMemory.cpp
@@ -0,0 +1,94 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "ProMemory.h"
+
+ProMemory::ProMemory()
+{
+
+}
+
+ProMemory::~ProMemory()
+{
+
+}
+
+void ProMemory::pushCasicIris(CasicIrisInfo irisInfo)
+{
+ mutex.lock();
+ if (this->irisQueue.size() > 10)
+ {
+ QStack empty;
+ std::swap(empty, irisQueue);
+ }
+ irisQueue.push(irisInfo);
+ mutex.unlock();
+}
+CasicIrisInfo ProMemory::popCasicIris()
+{
+ CasicIrisInfo result;
+
+ mutex.lock();
+ if (this->irisQueue.size() > 0)
+ {
+ result = irisQueue.pop();
+ }
+ mutex.unlock();
+
+ return result;
+}
+
+int ProMemory::getIrisQueueSize()
+{
+ int size = 0;
+
+ mutex.lock();
+ size = this->irisQueue.size();
+ mutex.unlock();
+
+ return size;
+}
+bool ProMemory::isIrisQueueEmpty()
+{
+ bool empty = true;
+
+ mutex.lock();
+ empty = this->irisQueue.isEmpty();
+ mutex.unlock();
+
+ return empty;
+}
+void ProMemory::clearIrisQueue()
+{
+ mutex.lock();
+ QStack empty;
+ std::swap(empty, irisQueue);
+ mutex.unlock();
+}
+
+void ProMemory::initIrisFeatures()
+{
+ IrisDataDao irisDao;
+
+ QVector irisDataList = irisDao.findAllRecord();
+ for (QVariantMap iris : irisDataList) {
+ CasicIrisFeature featureLeft;
+ featureLeft.personId = iris.value("person_id").toString();
+ featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray();
+
+ CasicIrisFeature featureRight;
+ featureRight.personId = iris.value("person_id").toString();
+ featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray();
+
+ irisFeatures.append(featureLeft);
+ irisFeatures.append(featureRight);
+ }
+
+ LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString());
+}
+
+QVector ProMemory::getIrisFeatures()
+{
+ return this->irisFeatures;
+}
diff --git a/ProMemory.h b/ProMemory.h
new file mode 100644
index 0000000..cf1fe42
--- /dev/null
+++ b/ProMemory.h
@@ -0,0 +1,57 @@
+#ifndef PROMEMORY_H
+#define PROMEMORY_H
+
+#include
+#include
+
+#include "AppConstants.h"
+#include "casic/iris/CasicIrisInfo.h"
+#include "dao/IrisDataDao.h"
+#include "utils/SocketClientUtil.h"
+
+#include "device/IrisCameraController.h"
+#include "device/iris/IrisRecogProcess.h"
+
+class IrisCameraController;
+class IrisRecogProcess;
+
+class ProMemory
+{
+public:
+ ~ProMemory();
+ ProMemory(const ProMemory&)=delete;
+ ProMemory& operator=(const ProMemory&)=delete;
+
+ static ProMemory& getInstance() {
+ static ProMemory instance;
+ return instance;
+ }
+
+ void pushCasicIris(CasicIrisInfo irisInfo);
+ CasicIrisInfo popCasicIris();
+ int getIrisQueueSize();
+ bool isIrisQueueEmpty();
+ void clearIrisQueue();
+
+ volatile int widgeFrame = 0; // 当前显示的界面
+ volatile int appState = 0; // 当前程序所处的状态
+
+ void initIrisFeatures(); // 初始化虹膜特征值集合
+
+ QVector getIrisFeatures();
+
+ IrisCameraController * irisCamCtrl;
+ IrisRecogProcess * irisRecogPro;
+
+ SocketClientUtil client;
+
+private:
+ ProMemory();
+
+ QMutex mutex;
+
+ QStack irisQueue; // 虹膜信息队列
+ QVector irisFeatures; // 虹膜特征值集合
+};
+
+#endif // PROMEMORY_H
diff --git a/casic/casic.pri b/casic/casic.pri
new file mode 100644
index 0000000..88263a7
--- /dev/null
+++ b/casic/casic.pri
@@ -0,0 +1,2 @@
+include(iris/casicIris.pri)
+
diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h
new file mode 100644
index 0000000..e3c0735
--- /dev/null
+++ b/casic/iris/CasicIrisInfo.h
@@ -0,0 +1,38 @@
+#ifndef CASICIRISINFO_H
+#define CASICIRISINFO_H
+
+#include
+#include
+#include "CasicSegResult.h"
+
+struct CasicIrisInfo
+{
+ // 是否有眼睛, 默认为false
+ bool hasEye = false;
+
+ // post process
+ bool postProcSucc = false;
+
+ // 眼部图像
+ // 后续计算需要使用
+ cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图
+
+ cv::Mat maskNorm;
+ cv::Mat irisCode;
+
+ iristrt::CasicSegResult segResult;
+
+ // 字节数组形式的特征码
+ QByteArray irisFeatureCode;
+};
+
+struct CasicIrisFeature
+{
+ int irisId;
+ QString personId;
+ cv::Mat irisCode;
+ cv::Mat maskNorm;
+ QByteArray irisFeatureCode;
+};
+
+#endif // CASICIRISINFO_H
diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp
new file mode 100644
index 0000000..5803f44
--- /dev/null
+++ b/casic/iris/CasicIrisInterface.cpp
@@ -0,0 +1,234 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "CasicIrisInterface.h"
+
+#include
+#include
+#include
+
+casic::iris::CasicIrisInterface::CasicIrisInterface()
+{
+ rec = iristrt::CasicIrisRec(gaborFilterFileName, applicationPointsFileName);
+
+ cascade = new cv::CascadeClassifier();
+ cascade->load(cascadeName);
+}
+
+casic::iris::CasicIrisInterface::~CasicIrisInterface()
+{
+
+}
+
+void casic::iris::CasicIrisInterface::setCascadeFile(QString filename)
+{
+ this->cascadeName = filename.toStdString();
+}
+void casic::iris::CasicIrisInterface::setMinEyeSize(int minEyeSize)
+{
+ this->minEyeSize = minEyeSize;
+}
+void casic::iris::CasicIrisInterface::setMaxEyeSize(int maxEyeSize)
+{
+ this->maxEyeSize = maxEyeSize;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::findEye(CasicIrisInfo irisInfo)
+{
+ // 构建OpenCV自带的眼睛分类器
+ if (this->cascade == nullptr) {
+ this->cascade = new cv::CascadeClassifier();
+ this->cascade->load(cascadeName);
+ }
+
+ QElapsedTimer timer;
+ timer.start();
+
+ std::vector rect;
+ cv::Size minEyeRectSize(minEyeSize, minEyeSize);
+ cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize);
+
+ // ★分类器对象调用
+ cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize);
+
+ if (rect.size() == 0)
+ {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+// LOG(DEBUG) << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString();
+// LOG_DEBUG(QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString());
+ qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+ .arg(timer.elapsed()).arg(rect.size())
+ .arg(rect.at(0).x).arg(rect.at(0).y)
+ .arg(rect.at(0).width).arg(rect.at(0).height);
+
+ irisInfo.hasEye = true;
+// irisInfo.eyeRect = rect.at(0);
+
+// irisInfo.data = ImageUtil::MatImageToQImage(irisInfo.matData);
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::findAndCutEye(CasicIrisInfo irisInfo)
+{
+ // 构建OpenCV自带的眼睛分类器
+ if (this->cascade == nullptr) {
+ this->cascade = new cv::CascadeClassifier();
+ this->cascade->load(cascadeName);
+ }
+
+ std::vector rect;
+ cv::Size minEyeRectSize(minEyeSize, minEyeSize);
+ cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize);
+
+ if (irisInfo.matData.empty() == true) {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+ // ★分类器对象调用
+ cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize);
+
+ if (rect.size() == 0)
+ {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+// LOG(DEBUG) << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString();
+// LOG_DEBUG(QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString());
+ qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]")
+ .arg(rect.size())
+ .arg(rect.at(0).x).arg(rect.at(0).y)
+ .arg(rect.at(0).width).arg(rect.at(0).height);
+
+ // 找到眼睛之后, 将眼部裁剪下来, 图像拉伸到640 * 480
+ cv::Point center;
+ center.x = cvFloor(rect.at(0).x + rect.at(0).width*0.5);
+ center.y = cvFloor(rect.at(0).y + rect.at(0).height*0.5);
+
+ // 限制中心点的范围
+ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5)
+ {
+ // x小于240则x=240
+ center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5;
+ } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) {
+ // x大于1040则x=1040
+ center.x = SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5;
+ }
+
+ if (center.y < SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5)
+ {
+ // y小于180则y=180
+ center.y = SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5;
+ } else if (center.y > SettingConfig::getInstance().IRIS_FRAME_HEIGHT - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5) {
+ center.y = SettingConfig::getInstance().IRIS_FRAME_HEIGHT - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5;
+ }
+
+ // 裁剪眼部图像
+ cv::Mat cutSize = irisInfo.matData.clone();
+ cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5,
+ center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5,
+ SettingConfig::getInstance().IRIS_WIDTH * cutRatio,
+ SettingConfig::getInstance().IRIS_HEIGHT * cutRatio));
+
+ // 裁剪后放大到 640 * 480
+ cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT));
+ cv::flip(cutSize, cutSize, 1); // 左右翻转
+
+ irisInfo.hasEye = true;
+ irisInfo.postProcSucc = false;
+ irisInfo.matData = cutSize;
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::irisQualityAssess(CasicIrisInfo irisInfo)
+{
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo)
+{
+// std::vector irisCircle, pupilCircle; // x,y,r
+ std::vector irisCircle(0); // x,y,r
+ std::vector pupilCircle(0); // x,y,r
+ iristrt::CasicSegPostProcess segPost;
+
+ cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+ cv::resize(irisInfo.segResult.innerMask, irisInfo.segResult.innerMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+ cv::resize(irisInfo.segResult.outerCircle, irisInfo.segResult.outerCircle,cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+
+ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle);
+ if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0)
+ {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+// std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl;
+ int iris_x = irisCircle[0];
+ int iris_y = irisCircle[1];
+ int iris_r = irisCircle[2];
+ int pupil_x = pupilCircle[0];
+ int pupil_y = pupilCircle[1];
+ int pupil_r = pupilCircle[2];
+ int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y);
+ if(!(dis + pupil_r < iris_r))
+ {
+ // pupil circle doesn't contained in iris circle
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+
+ cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]);
+ if (imageNorm.empty() == true) {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+ irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]);
+ if (irisInfo.maskNorm.empty() == true)
+ {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+// std::cout << "finish normalize" << std::endl;
+// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm);
+
+ irisInfo.irisCode = rec.encodeToImage(imageNorm);
+ irisInfo.postProcSucc = true;
+
+ return irisInfo;
+}
+
+QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo)
+{
+ QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm);
+ return irisFeatureCode;
+}
+
+float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo)
+{
+ return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm);
+}
+
+float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other)
+{
+ return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data()));
+}
diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h
new file mode 100644
index 0000000..7f91d68
--- /dev/null
+++ b/casic/iris/CasicIrisInterface.h
@@ -0,0 +1,54 @@
+#ifndef CASICIRISINTERFACE_H
+#define CASICIRISINTERFACE_H
+
+#include "CasicIrisInfo.h"
+#include "CasicSegPostProcess.h"
+#include "CasicIrisUtil.h"
+#include "CasicIrisRec.h"
+#include "utils/UtilInclude.h"
+
+namespace casic {
+ namespace iris {
+ class CasicIrisInterface
+ {
+ public:
+ ~CasicIrisInterface();
+ CasicIrisInterface(const CasicIrisInterface&)=delete;
+ CasicIrisInterface& operator=(const CasicIrisInterface&)=delete;
+
+ static CasicIrisInterface& getInstance() {
+ static CasicIrisInterface instance;
+ return instance;
+ }
+
+ CasicIrisInfo findEye(CasicIrisInfo irisInfo);
+ CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo);
+ CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo);
+
+ CasicIrisInfo irisEncode(CasicIrisInfo irisInfo);
+ QByteArray extractFeature(CasicIrisInfo irisInfo);
+ float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo);
+ float calculatePairPoints(QByteArray feature, QByteArray other);
+
+ void setCascadeFile(QString filename);
+ void setMinEyeSize(int minEyeSize);
+ void setMaxEyeSize(int maxEyeSize);
+
+ private:
+ CasicIrisInterface();
+
+ std::string cascadeName = "./model/haarcascade_eye.xml";
+ const char * gaborFilterFileName = "./model/filters.txt";
+ const char * applicationPointsFileName = "./model/points.txt";
+ int minEyeSize = 320;
+ int maxEyeSize = 480;
+ float cutRatio = 0.72f; // 裁剪比率 用于裁剪更大比例的眼部图像
+
+ cv::CascadeClassifier * cascade;
+ iristrt::CasicIrisRec rec;
+ };
+ }
+}
+
+
+#endif // CASICIRISINTERFACE_H
diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp
new file mode 100644
index 0000000..c8d3bbb
--- /dev/null
+++ b/casic/iris/CasicIrisRec.cpp
@@ -0,0 +1,499 @@
+#include "CasicIrisRec.h"
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+using Eigen::MatrixXd;
+using Eigen::MatrixXi;
+
+namespace iristrt
+{
+CasicIrisRec::CasicIrisRec()
+{
+
+}
+
+CasicIrisRec::CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName)
+{
+ loadApplicationPoints(applicationPointsFileName);
+ loadGaborFilters(gaborFilterFileName);
+}
+
+CasicIrisRec::~CasicIrisRec()
+{
+
+}
+
+cv::Mat CasicIrisRec::normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r)
+{
+ int width = NORM_WIDTH;
+ int height = NORM_HEIGHT;
+ int realHeight = height + 2;
+ int angledivisions = width - 1;
+// int rows = image.rows;
+// int cols = image.cols;
+
+ double ox = pupil_x - iris_x;
+ double oy = pupil_y - iris_y;
+
+ int sgn = ox <= 0 ? -1 : 1;
+ if (ox == 0 && oy > 0) {
+ sgn = 1;
+ }
+
+ double phi = ox == 0 ? M_PI / 2 : atan(oy / ox);
+
+ MatrixXd a = MatrixXd::Ones(1, width) * (ox * ox + oy * oy);
+
+ MatrixXd thetas(1, width);
+ for (int i = 0; i < width; i++) {
+ thetas(0, i) = (2 * M_PI / angledivisions) * i;
+ }
+
+ MatrixXd b = M_PI - phi - thetas.array();
+ b = b.array().cos();
+ b = sgn * b;
+
+ MatrixXd item1 = a.array().sqrt() * b.array();
+ MatrixXd item2 = a.array() * b.array().pow(2);
+ MatrixXd item3 = a.array() - (iris_r * iris_r);
+ MatrixXd r = item1 + (item2 - item3).array().sqrt().matrix();
+ r = r.array() - pupil_r;
+
+ MatrixXd rMatrix = MatrixXd::Ones(1, realHeight).transpose() * r;
+ MatrixXd tmp(1, realHeight);
+ for (int i = 0; i < realHeight; i++) {
+ tmp(0, i) = (double)(1.0 / realHeight) * i;
+ }
+ rMatrix = rMatrix.array() * (MatrixXd::Ones(angledivisions + 1, 1) * tmp).array().transpose();
+ rMatrix = rMatrix.array() + pupil_r;
+
+ MatrixXd new_rMatrix = rMatrix.middleRows(1,realHeight-2);
+
+ MatrixXd xcosMat = MatrixXd::Ones(height, 1) * thetas.array().cos().matrix();
+ MatrixXd xsinMat = MatrixXd::Ones(height, 1) * thetas.array().sin().matrix();
+
+ MatrixXd xo = pupil_x + new_rMatrix.array() * xcosMat.array();
+ MatrixXd yo = pupil_y - new_rMatrix.array() * xsinMat.array();
+
+ MatrixXi xo_i = xo.cast();
+ MatrixXi yo_i = yo.cast();
+
+ if(image.channels() == 3){
+ cv::cvtColor(image,image,cv::COLOR_RGB2GRAY);
+ }
+
+ MatrixXi eigenImage;
+
+ cv::cv2eigen(image, eigenImage);
+
+ MatrixXi normMat = MatrixXi::Zero(xo_i.rows(), xo_i.cols());
+ for (int i = 0; i < xo_i.rows(); i++) {
+ for (int j = 0; j < xo_i.cols(); j++) {
+ if (yo_i(i, j) < 0 || xo_i(i, j) < 0) {
+ cv::Mat empty;
+ return empty;
+ }
+ normMat(i, j) = eigenImage(yo_i(i, j), xo_i(i, j));
+ }
+ }
+
+ cv::Mat normImage(image.size(),image.type());
+ cv::eigen2cv(normMat, normImage);
+ normImage.convertTo(normImage, CV_8UC1);
+
+ return normImage;
+}
+
+std::vector CasicIrisRec::loadGaborFilters(const char * gaborFilterFileName)
+{
+ std::ifstream file(gaborFilterFileName, std::ios::in);
+ if (!file)
+ {
+ std::cout << "Cannot load Gabor filters in file " << gaborFilterFileName << std::endl;
+ }
+
+ // Get the number of filters
+ int n_filters;
+ file >> n_filters;
+ gaborFilters.resize(n_filters);
+
+ //cout << "n_filters " << n_filters << endl;
+
+ // Size of filter
+ int rows, cols;
+
+ // Loop on each filter
+ for (int f = 0; f < n_filters; f++)
+ {
+ // Get the size of the filter
+ file >> rows;
+ file >> cols;
+ //cout << rows << " " << cols << endl;
+ // Temporary filter. Will be destroyed at the end of loop
+ gaborFilters[f] = cv::Mat(rows, cols, CV_32FC1);
+
+ // Set the value at coordinates r,c
+ for (int r = 0; r < rows; r++)
+ {
+ for (int c = 0; c < cols; c++)
+ {
+ file >> gaborFilters[f].at(r,c);
+ }
+ }
+
+ } // Loop on each filter
+
+ // Close the file
+ file.close();
+
+ return gaborFilters;
+}
+
+cv::Mat CasicIrisRec::loadApplicationPoints(const char * applicationPointsFileName)
+{
+ // Open text file containing the filters
+ std::ifstream file(applicationPointsFileName, std::ios::in);
+ if (!file)
+ {
+ std::cout << "Cannot load the application points in " << applicationPointsFileName << std::endl;
+ }
+
+ // Get the number of points
+ int n_points = 0;
+ file >> n_points;
+
+ // Allocate memory for the matrix containing the points
+ applicationPoints = cv::Mat(NORM_HEIGHT, NORM_WIDTH, CV_8UC1);
+ // Initialize all pixels to "off"
+ applicationPoints.setTo(cv::Scalar(0));
+
+ // Local variables
+ int i, j;
+
+ // Loop on each point
+ for (int p = 0; p < n_points; p++)
+ {
+ // Get the coordinates
+ file >> i; file >> j;
+
+ mvApplicationPoints.push_back(QPair(i, j));
+
+ // Set pixel to "on"
+ if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1)
+ {
+ std::cout << "Point (" << i << "," << j << ") ";
+ std::cout << "exceeds size of normalized image : ";
+ std::cout << applicationPoints.rows << "x" << applicationPoints.cols;
+ std::cout << " while loading application points" << std::endl;
+ }
+ else
+ {
+ applicationPoints.at(i,j) = 255;
+ }
+ }
+
+ //cv::imshow("mpApplicationPoints", mpApplicationPoints);
+ //cv::waitKey(0);
+
+ // Close the file
+ file.close();
+
+ return applicationPoints;
+}
+
+cv::Mat CasicIrisRec::encodeToImage(cv::Mat normalizedImage)
+{
+ cv::Size size(normalizedImage.size());
+ cv::Mat encodeImage(cv::Size(size.width, size.height * gaborFilters.size()), CV_32FC1);
+
+ int max_width = 0;
+ for (int f = 0; f < gaborFilters.size(); f++)
+ if (gaborFilters[f].cols > max_width)
+ max_width = gaborFilters[f].cols;
+ max_width = (max_width - 1) / 2;
+
+ cv::Mat resized = addBorders(normalizedImage, max_width);
+
+// std::cout << resized.size() << std::endl;
+// cv::imshow("resized", resized);
+// cv::waitKey(0);
+
+ cv::Mat img1(resized.size(), CV_32F, 1);
+ cv::Mat img2(resized.size(), encodeImage.depth(), 1);
+
+ for (int f = 0; f < gaborFilters.size(); f++)
+ {
+ // Convolution
+ cv::filter2D(resized, img1, img1.depth(), gaborFilters[f]);
+
+ // Threshold : above or below 0
+ cv::threshold(img1, img2, 0, 255, cv::THRESH_BINARY);
+
+// cv::imshow("img2", img2);
+// cv::waitKey(0);
+
+ // Form the iris code
+ cv::Mat roi = img2(cv::Rect(max_width, 0, normalizedImage.cols, normalizedImage.rows));
+ cv::Mat dst = encodeImage(cv::Rect(0, f*normalizedImage.rows, normalizedImage.cols, normalizedImage.rows));
+ roi.copyTo(dst);
+ //cv::copyTo(img2, dst, NULL);
+ }
+ cv::Mat image8UC1;
+ encodeImage.convertTo(image8UC1, CV_8UC1);
+ return image8UC1;
+}
+
+QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm)
+{
+ // count points width and height
+ cv::Mat pointTemp(applicationPoints);
+ cv::Mat rowTemp;
+
+ std::vector pointRows;
+ for (int i = 0; i < applicationPoints.rows; i++) {
+ rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1));
+ if (cv::sum(rowTemp)[0] > 0) {
+ pointRows.push_back(i);
+ }
+ }
+
+ int width = irisCode.cols;
+ int height = pointRows.size();
+ rowTemp.release();
+ pointTemp.release();
+
+ int n_codes = irisCode.rows / applicationPoints.rows;
+
+ int irisDataLength = (n_codes + 1) * width * height;
+ uchar * irisData = new uchar[irisDataLength];
+ int irisDataIndex = 0;
+
+ uchar* codePixel = new uchar;
+
+ // save iris code 512 * 8 * 6
+ for (int n = 0; n < n_codes; n++) { // 6
+ for (auto i : pointRows) { // 8
+ i = n * maskNorm.rows + i;
+ for (int j = 0; j < irisCode.cols; j++) { // 512
+ codePixel = (uchar*)(irisCode.data + i * irisCode.step + j);
+ if (*codePixel == 255) {
+ irisData[irisDataIndex++] = 1;
+ }
+ else {
+ irisData[irisDataIndex++] = *codePixel;
+ }
+ }
+ }
+ }
+
+ // save iris mask 512 * 8 * 1
+ uchar * maskPixel;
+ for (auto i : pointRows) { // 8
+ for (int j = 0; j < irisCode.cols; j++) { // 512
+ maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j);
+ if (*maskPixel == 255) {
+ irisData[irisDataIndex++] = 1;
+ }
+ else {
+ irisData[irisDataIndex++] = *maskPixel;
+ }
+ }
+ }
+
+
+ uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5];
+ memset(irisFeaturePtr, 0, irisDataLength / 8 + 5);
+
+ // first byte is width;
+ irisFeaturePtr[0] = (uchar)width;
+ irisFeaturePtr[1] = (uchar)(width >> 8);
+
+ // second byte is height;
+ irisFeaturePtr[2] = (uchar)height;
+
+ // third byte is n_codes
+ irisFeaturePtr[3] = (uchar)n_codes;
+
+ // fourth byte is n_mask(1)
+ irisFeaturePtr[4] = (uchar)1;
+ for (int i = 0; i < irisDataLength; i++) {
+ irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8));
+ }
+
+ QByteArray feature;
+ for (int i = 0; i < irisDataLength / 8 + 5; i++) {
+ feature.append((char) irisFeaturePtr[i]);
+ }
+
+ delete[] irisData;
+ delete[] irisFeaturePtr;
+ return feature;
+}
+
+float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2)
+{
+ code1.convertTo(code1, CV_8UC1);
+ code2.convertTo(code2, CV_8UC1);
+
+ cv::Mat temp(applicationPoints.size(), CV_8UC1);
+ temp.setTo(cv::Scalar(0));
+
+ cv::bitwise_and(normalizedMask1, normalizedMask2, temp, applicationPoints);
+
+ // Copy the mask f times, where f correspond to the number of codes (= number of filters)
+ int n_codes = code1.rows / applicationPoints.rows;
+
+ cv::Mat totalMask(code1.size(), CV_8UC1);
+ for (int n = 0; n < n_codes; n++) {
+ cv::Mat maskRoi = totalMask(cv::Rect(0, n*applicationPoints.rows, applicationPoints.cols, applicationPoints.rows));
+ temp.copyTo(maskRoi);
+ }
+
+// cv::imshow("totalMask", totalMask);
+// cv::waitKey(0);
+
+ cv::Mat result(code1.size(), CV_8UC1);
+ result.setTo(cv::Scalar(0));
+
+ int shift = 10;
+ cv::Mat shifted = addBorders(code1, shift);
+
+ float score = 1;
+ for (int s = -shift; s <= shift; s++) {
+ cv::Mat roi = shifted(cv::Rect(shift + s, 0, code1.cols, code1.rows));
+ cv::bitwise_xor(roi, code2, result, totalMask);
+
+ float mean = (cv::sum(result).val[0]) / (cv::sum(totalMask).val[0]);
+ // std::cout << "mean: " << mean << std::endl;
+ score = std::min(score, mean);
+ }
+
+ // std::cout << "score: " << score << std::endl;
+ return score;
+
+}
+
+float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2)
+{
+ int width = feature1[0] | feature1[1] << 8; // 32
+ int height = feature1[2]; // 8
+ int nCode = feature1[3]; // 6
+// int nMask = feature1[4];
+
+ uchar ** irisData1 = reduceIrisCode(feature1);
+ uchar ** irisMask1 = reduceIrisMask(feature1);
+ uchar ** irisData2 = reduceIrisCode(feature2);
+ uchar ** irisMask2 = reduceIrisMask(feature2);
+
+// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl;
+
+ int shift = 10;
+ float score = 1.0;
+
+ int minstep = 0 - shift;
+ int maxstep = shift;
+
+ for (int s = minstep; s <= maxstep; s++) {
+ int count = 0;
+ float mean = 0.0;
+ for (int n = 0; n < nCode; n++) {
+ for (auto pos : mvApplicationPoints) {
+ int row = pos.first / mvApplicationPoints[0].first - 1;
+ int col = (pos.second + s + width) % width;
+
+// std::cout << "array: " << row << ", " << pos.second << std::endl;
+ if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) {
+
+ uchar tmp1 = irisData1[row + height * n][col];
+ uchar tmp2 = irisData2[row + height * n][pos.second];
+ mean += tmp1 ^ tmp2;
+ count += 1;
+ }
+ }
+ }
+
+// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl;
+ mean = mean / count;
+ score = mean < score ? mean : score;
+
+ }
+
+// std::cout << "feature score: " << score << std::endl;
+
+
+// for (int i = 0; i < height * nCode; i++) {
+// delete irisData1[i];
+// delete irisData2[i];
+// }
+// delete irisData1;
+// delete irisData2;
+
+// for (int i = 0; i < height; i++) {
+// delete irisMask1[i];
+// delete irisMask2[i];
+// }
+// delete irisMask1;
+// delete irisMask2;
+ return score;
+}
+
+cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width)
+{
+ cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels());
+
+ cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0);
+
+ for (int i = 0; i < pSrc.rows; i++) {
+ for (int j = 0; j < width; j++) {
+ result.at(i, j) = pSrc.at(i, pSrc.cols - width + j);
+ result.at(i, result.cols - width + j) = pSrc.at(i, j);
+ }
+ }
+ return result;
+}
+
+uchar ** CasicIrisRec::reduceIrisCode(uchar *feature)
+{
+ int width = feature[0] | feature[1] << 8;
+ int height = feature[2] * feature[3];
+
+ uchar ** reduceCode = new uchar*[width*height];
+ for (int i = 0; i < height; i++) {
+ reduceCode[i] = new uchar[width];
+ for (int j = 0; j < width; j++) {
+ int tmp = i * width + j;
+ reduceCode[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1;
+ }
+ }
+
+// std::cout << "reduce iris code, length: " << width * height << std::endl;
+
+ return reduceCode;
+}
+
+uchar ** CasicIrisRec::reduceIrisMask(uchar *feature)
+{
+ int width = feature[0] | feature[1] << 8;
+ int height = feature[2]; // 8
+ int nCode = feature[3]; // 6
+
+ uchar ** irisMask = new uchar*[width*height];
+ for (int i = 0; i < height; i++) {
+ irisMask[i] = new uchar[width];
+ for (int j = 0; j < width; j++) {
+ int tmp = width * height * nCode + i * width + j;
+ irisMask[i][j] = (uchar)feature[5 + tmp / 8] >> (7 - tmp % 8) & 1;
+ }
+ }
+
+// std::cout << "reduce iris mask, length: " << width * height << std::endl;
+
+ return irisMask;
+}
+
+}
diff --git a/.gitignore b/.gitignore
index fab7372..1358d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,73 +1,73 @@
-# This file is used to ignore files which are generated
-# ----------------------------------------------------------------------------
-
-*~
-*.autosave
-*.a
-*.core
-*.moc
-*.o
-*.obj
-*.orig
-*.rej
-*.so
-*.so.*
-*_pch.h.cpp
-*_resource.rc
-*.qm
-.#*
-*.*#
-core
-!core/
-tags
-.DS_Store
-.directory
-*.debug
-Makefile*
-*.prl
-*.app
-moc_*.cpp
-ui_*.h
-qrc_*.cpp
-Thumbs.db
-*.res
-*.rc
-/.qmake.cache
-/.qmake.stash
-
-# qtcreator generated files
-*.pro.user*
-
-# xemacs temporary files
-*.flc
-
-# Vim temporary files
-.*.swp
-
-# Visual Studio generated files
-*.ib_pdb_index
-*.idb
-*.ilk
-*.pdb
-*.sln
-*.suo
-*.vcproj
-*vcproj.*.*.user
-*.ncb
-*.sdf
-*.opensdf
-*.vcxproj
-*vcxproj.*
-
-# MinGW generated files
-*.Debug
-*.Release
-
-# Python byte code
-*.pyc
-
-# Binaries
-# --------
-*.dll
-*.exe
-
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/AppConstants.h b/AppConstants.h
new file mode 100644
index 0000000..716094a
--- /dev/null
+++ b/AppConstants.h
@@ -0,0 +1,35 @@
+#ifndef APPCONSTANTS_H
+#define APPCONSTANTS_H
+
+class AppConstants
+{
+public:
+ enum WidgeFrameName
+ {
+// MAIN_PAGE = 0, // 主页面
+// PERSON_LIST_FORM = 1, // 人员列表页面
+// ADD_PERSON_FORM = 2, // 添加人员页面
+// ADD_PERSON_CAPTURE_FACE = 21, // 添加/编辑人员时进行人脸拍图
+// ADD_PERSON_CAPTURE_IRIS = 22, // 添加/编辑人员时进行虹膜拍图
+// SETTING_FORM = 3, // 设置页面
+// RECOGNIZE_RESULT_FORM = 4, // 识别结果界面
+ IDENTIFY_FORM = 5, // 识别界面 含识别中 和 识别结果
+ LOCKSCREEN_FORM = 6 // 锁屏待机界面
+ };
+
+ enum ApplicationState
+ {
+ STATE_WAIT = 0, // 待机
+ STATE_WORKING = 1, // 工作状态
+ STATE_IDENTIFYING = 2, // 识别中
+ };
+
+ enum IdentifyType
+ {
+ IRIS = 1, // 虹膜识别
+ FACE = 2, // 人脸识别
+ FINGER = 3, // 指纹识别
+ };
+};
+
+#endif // APPCONSTANTS_H
diff --git a/CasicIrisIdentify.pro b/CasicIrisIdentify.pro
index 5d7fea6..e5f8c61 100644
--- a/CasicIrisIdentify.pro
+++ b/CasicIrisIdentify.pro
@@ -1,34 +1,59 @@
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
- main.cpp \
- IdentifyForm.cpp
-
-HEADERS += \
- IdentifyForm.h
-
-FORMS += \
- IdentifyForm.ui
-
-TRANSLATIONS += \
- CasicIrisIdentify_zh_CN.ts
-
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
+QT += core gui sql network texttospeech multimedia
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+include("casic/casic.pri")
+include("dao/dao.pri")
+include("device/device.pri")
+include("utils/utils.pri")
+
+SOURCES += main.cpp
+SOURCES += ProMemory.cpp
+SOURCES += MainWindowForm.cpp
+SOURCES += IdentifyForm.cpp
+SOURCES += LockScreenForm.cpp
+
+HEADERS += AppConstants.h
+HEADERS += ProMemory.h
+HEADERS += MainWindowForm.h
+HEADERS += IdentifyForm.h
+HEADERS += LockScreenForm.h
+
+FORMS += MainWindowForm.ui
+FORMS += IdentifyForm.ui
+FORMS += LockScreenForm.ui
+
+RESOURCES += resource.qrc
+
+DISTFILES += conf/config.ini
+
+#INCLUDEPATH += include/spdlog
+#DEPENDPATH += include/spdlog
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+INCLUDEPATH += $$PWD/Eigen
+
+unix:!macx: LIBS += -L$$PWD/lib/daheng/ -lgxiapi
+
+INCLUDEPATH += $$PWD/include/daheng
+DEPENDPATH += $$PWD/include/daheng
+
+LIBS += $(shell pkg-config opencv4 --libs)
+INCLUDEPATH += /usr/include/opencv4
diff --git a/CasicIrisIdentify_zh_CN.ts b/CasicIrisIdentify_zh_CN.ts
deleted file mode 100644
index 5526fe4..0000000
--- a/CasicIrisIdentify_zh_CN.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/IdentifyForm.cpp b/IdentifyForm.cpp
index 348a897..7abffa4 100644
--- a/IdentifyForm.cpp
+++ b/IdentifyForm.cpp
@@ -1,15 +1,161 @@
-#include "IdentifyForm.h"
-#include "ui_IdentifyForm.h"
-
-IdentifyForm::IdentifyForm(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::IdentifyForm)
-{
- ui->setupUi(this);
-}
-
-IdentifyForm::~IdentifyForm()
-{
- delete ui;
-}
-
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "IdentifyForm.h"
+#include "ui_IdentifyForm.h"
+
+IdentifyForm::IdentifyForm(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::IdentifyForm)
+{
+ ui->setupUi(this);
+
+ ui->wgtIdentifying->setCurrentIndex(0);
+
+ ui->labelIdenTips->setText("");
+ ui->labelFailTips->setText("识 别 失 败\n请 重 试");
+}
+
+IdentifyForm::~IdentifyForm()
+{
+ delete ui;
+}
+
+void IdentifyForm::updateIdentifyTips(QString tips)
+{
+ ui->labelIdenTips->setText(tips);
+}
+
+void IdentifyForm::drawIrisImageOnFrame()
+{
+ // If acquisition did not started
+ if (!ProMemory::getInstance().irisCamCtrl->m_bAcquisitionStart)
+ {
+ return;
+ }
+
+ // Get Image from image show queue, if image show queue is empty, return directly
+ QImage* qobjImgShow = ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PopFrontFromShowImageDeque();
+ if(qobjImgShow == NULL)
+ {
+ return;
+ }
+
+ QImage objImgGray = qobjImgShow->convertToFormat(QImage::Format_Grayscale8);
+
+ // 图像逆时针旋转90度
+ objImgGray = objImgGray.transformed(QTransform().rotate(SettingConfig::getInstance().DEBUG_CAMERA_ROTATE.toInt()));
+
+ // 创建虹膜信息对象
+ CasicIrisInfo irisInfo;
+ irisInfo.hasEye = false;
+ irisInfo.postProcSucc = false;
+
+ // 存入图像栈
+ cv::Mat irisMat = ImageUtil::QImageToMat(objImgGray);
+ irisInfo.matData = irisMat;
+
+ ProMemory::getInstance().pushCasicIris(irisInfo);
+
+ // Display is finished, push back image buffer to buffer queue
+ ProMemory::getInstance().irisCamCtrl->m_pobjAcqThread->PushBackToEmptyBufferDeque(qobjImgShow);
+
+ // 只在识别界面才显示画面
+ if (ui->wgtIdentifying->currentIndex() == 0) {
+ // Display the image
+ QImage imgDisp = objImgGray.scaled(SettingConfig::getInstance().IRIS_DISPLAY_WIDTH, SettingConfig::getInstance().IRIS_DISPLAY_HEIGHT);
+ ui->labelVideo->setPixmap(QPixmap::fromImage(imgDisp));
+ }
+
+ return;
+}
+
+void IdentifyForm::showRecogFailure()
+{
+ SpeakerUtil::getInstance().sayIdentifyFailureZhCn();
+ LOG_INFO("识别失败,请重试");
+
+ ui->wgtIdentifying->setCurrentIndex(2);
+
+ ProMemory::getInstance().clearIrisQueue();
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisCamCtrl->stopCapture();
+
+ QTimer::singleShot(SettingConfig::getInstance().FAILURE_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
+
+void IdentifyForm::showRecognizeResult(QString personId)
+{
+ QVariantMap matched = personDao.findRecordById(personId);
+
+ QString deptName = matched.value("deptname").toString();
+ QString personName = matched.value("name").toString();
+ SpeakerUtil::getInstance().sayIdentifySuccessZhCn();
+ LOG_INFO(QString("识别成功,%1%2").arg(deptName).arg(personName).toStdString());
+
+ ui->wgtIdentifying->setCurrentIndex(1);
+
+ // 查询并显示人员信息
+ ui->labelName->setText("");
+ ui->labelName->setText(personName);
+ ui->labelGender->setText("");
+ ui->labelGender->setText(CacheManager::getInstance().getGenderName().value(matched.value("gender").toString()).toString());
+ ui->labelDept->setText("");
+ ui->labelDept->setText(deptName);
+ ui->labelTs->setText("");
+ ui->labelTs->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"));
+
+ // 查询并显示头像
+ QPixmap photo;
+ QString photoPath = QString("images/%1").arg(matched.value("avatar").toString());
+ bool succ = photo.load(photoPath);
+ if (succ == false) {
+ photo.load(":/images/photo.png");
+ }
+
+ // 缩放到合适的尺寸
+ float rp = photo.width() * 1.0 / photo.height() * 1.0; // 图片的比例
+ float rl = ui->labelPhoto->width() * 1.0 / ui->labelPhoto->height() * 1.0; // 显示框的比例
+
+ if (rp <= rl) {
+ // 如果图片的比例小则缩放到显示框的高度
+ photo = photo.scaledToHeight(ui->labelPhoto->height());
+ } else {
+ // 如果图片的比例大则缩放到显示框的宽度
+ photo = photo.scaledToWidth(ui->labelPhoto->width());
+ }
+ // 显示
+ ui->labelPhoto->setPixmap(photo);
+
+ // 执行数据库操作
+ QVariantMap record;
+ record.insert("person_id", personId);
+ record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
+ record.insert("rec_type", AppConstants::IdentifyType::IRIS); // 虹膜识别;
+ record.insert("dev_code", SettingConfig::getInstance().DEVICE_CODE);
+ record.insert("debug_info", CasicIrisRecState::getInstance().toString());
+ recordDao.save(record);
+ LOG_INFO("识别成功记录保存成功");
+
+ // 返回工作状态和界面
+ QTimer::singleShot(SettingConfig::getInstance().SUCCESS_TIPS_LAST, [=](){
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING;
+ ui->labelIdenTips->setText("");
+
+ // 清除上一次识别的状态信息
+ CasicIrisRecState::getInstance().restRecognize();
+ ui->wgtIdentifying->setCurrentIndex(0);
+ });
+}
diff --git a/IdentifyForm.h b/IdentifyForm.h
index fc857a1..8196c19 100644
--- a/IdentifyForm.h
+++ b/IdentifyForm.h
@@ -1,21 +1,39 @@
-#ifndef IDENTIFYFORM_H
-#define IDENTIFYFORM_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui { class IdentifyForm; }
-QT_END_NAMESPACE
-
-class IdentifyForm : public QWidget
-{
- Q_OBJECT
-
-public:
- IdentifyForm(QWidget *parent = nullptr);
- ~IdentifyForm();
-
-private:
- Ui::IdentifyForm *ui;
-};
-#endif // IDENTIFYFORM_H
+#ifndef IDENTIFYFORM_H
+#define IDENTIFYFORM_H
+
+#include
+#include
+
+#include "dao/SysPersonDao.h"
+#include "dao/RecognitionRecordsDao.h"
+#include "dao/util/CacheManager.h"
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class IdentifyForm; }
+QT_END_NAMESPACE
+
+class IdentifyForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IdentifyForm(QWidget *parent = nullptr);
+ ~IdentifyForm();
+
+ void updateIdentifyTips(QString tips);
+
+public slots:
+ void drawIrisImageOnFrame();
+
+ void showRecogFailure();
+ void showRecognizeResult(QString personId);
+
+private:
+ Ui::IdentifyForm *ui;
+ SysPersonDao personDao;
+ RecognitionRecordsDao recordDao;
+
+};
+#endif // IDENTIFYFORM_H
diff --git a/IdentifyForm.ui b/IdentifyForm.ui
index c72a36f..def6ccf 100644
--- a/IdentifyForm.ui
+++ b/IdentifyForm.ui
@@ -1,19 +1,199 @@
-
-
- IdentifyForm
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- IdentifyForm
-
-
-
-
-
+
+
+ IdentifyForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ IdentifyForm
+
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ 2
+
+
+
+
+
+ 105
+ 35
+ 393
+ 512
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 650
+ 600
+ 80
+
+
+
+ background: transparent;
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ background: url(":/images/bg_success.png");
+
+
+
+
+ 100
+ 50
+ 400
+ 305
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 200
+ 400
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 498
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 595
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+ 200
+ 691
+ 300
+ 60
+
+
+
+ background: transparent;
+
+
+
+
+
+
+
+
+
+
+ 100
+ 50
+ 400
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ :/images/iconWarn.png
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 150
+ 420
+ 300
+ 300
+
+
+
+ background: transparent;
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
diff --git a/LockScreenForm.cpp b/LockScreenForm.cpp
new file mode 100644
index 0000000..c33cbe8
--- /dev/null
+++ b/LockScreenForm.cpp
@@ -0,0 +1,31 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "LockScreenForm.h"
+#include "ui_LockScreenForm.h"
+
+LockScreenForm::LockScreenForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::LockScreenForm)
+{
+ ui->setupUi(this);
+}
+
+LockScreenForm::~LockScreenForm()
+{
+ delete ui;
+}
+
+void LockScreenForm::showLockScreenTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ ui->labelLockHour->setText(now.time().toString("HH"));
+ ui->labelLockMinute->setText(now.time().toString("mm"));
+ ui->labelLockDate->setText(now.date().toString("MM月dd日 dddd"));
+ if (now.time().second() % 2 == 0) {
+ ui->labelLockSep->hide();
+ } else {
+ ui->labelLockSep->show();
+ }
+}
diff --git a/LockScreenForm.h b/LockScreenForm.h
new file mode 100644
index 0000000..f53f308
--- /dev/null
+++ b/LockScreenForm.h
@@ -0,0 +1,28 @@
+#ifndef LOCKSCREENFORM_H
+#define LOCKSCREENFORM_H
+
+#include
+#include
+
+#include "utils/UtilInclude.h"
+
+namespace Ui {
+class LockScreenForm;
+}
+
+class LockScreenForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit LockScreenForm(QWidget *parent = nullptr);
+ ~LockScreenForm();
+
+public slots:
+ void showLockScreenTime();
+
+private:
+ Ui::LockScreenForm *ui;
+};
+
+#endif // LOCKSCREENFORM_H
diff --git a/LockScreenForm.ui b/LockScreenForm.ui
new file mode 100644
index 0000000..81e12d1
--- /dev/null
+++ b/LockScreenForm.ui
@@ -0,0 +1,113 @@
+
+
+ LockScreenForm
+
+
+
+ 0
+ 0
+ 600
+ 800
+
+
+
+ Form
+
+
+
+
+ 0
+ 270
+ 600
+ 100
+
+
+
+
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+ 285
+ 130
+ 30
+ 128
+
+
+
+
+ Microsoft YaHei UI Light
+ 96
+
+
+
+ :
+
+
+ Qt::AutoText
+
+
+ false
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+
+
+
+ 320
+ 120
+ 280
+ 150
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+
+
+ 275
+ 700
+ 50
+ 50
+
+
+
+
+
+
+ :/images/lock.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
diff --git a/MainWindowForm.cpp b/MainWindowForm.cpp
new file mode 100644
index 0000000..1a6e8fb
--- /dev/null
+++ b/MainWindowForm.cpp
@@ -0,0 +1,185 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "MainWindowForm.h"
+#include "ui_MainWindowForm.h"
+
+MainWindowForm::MainWindowForm(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::MainWindowForm)
+{
+ ui->setupUi(this);
+
+ // 设置窗口透明和大小、位置
+ this->setWindowFlags(Qt::FramelessWindowHint);
+// this->move(1400, 15);
+ this->move(0, 0);
+ this->resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);
+
+ // 通过调色板的颜色来设置窗口的统一背景色
+ qApp->setPalette(QPalette(QColor(SettingConfig::getInstance().WINDOW_BACKGROUND_COLOR)));
+
+ // 加载css文件设置控件样式
+ QFile file(QApplication::applicationDirPath() + "/qss/main.css");
+ if (file.open(QFile::ReadOnly))
+ {
+ QString qssStr = QLatin1String(file.readAll());
+ this->setStyleSheet(qssStr);
+ file.close();
+ }
+
+ // 初始化虹膜库
+ ProMemory::getInstance().initIrisFeatures();
+
+ // 初始化各个界面的form
+ initFormsPtr();
+
+ // 设置标题文字
+ ui->labelCopyright->setText(SettingConfig::getInstance().WINDOW_RIGHTS);
+ ui->labelVersion->setText(SettingConfig::getInstance().WINDOW_VERSION);
+
+ ui->labelMainTime->setText(QTime::currentTime().toString("HH:mm:ss"));
+ ui->labelMainDate->setText(QDate::currentDate().toString("yyyy-MM-dd dddd"));
+ ui->labelLogo->hide();
+
+ // 初始化更新界面的定时器
+ // 每秒执行一次
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ TimeCounterUtil::getInstance().clockCounter->start(1000);
+
+ // 初始化虹膜相机控制
+ ProMemory::getInstance().irisCamCtrl = new IrisCameraController();
+ ProMemory::getInstance().irisCamCtrl->openIrisCamera();
+
+ connect(TimeCounterUtil::getInstance().videoCounter, &QTimer::timeout, identifyForm, &IdentifyForm::drawIrisImageOnFrame);
+ TimeCounterUtil::getInstance().videoCounter->start(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ LOG_INFO(QString("应用程序启动成功[Application Startup Success]").toStdString());
+ qDebug() << QString("应用程序启动成功[Application Startup Success]");
+
+ // 启动后显示视频画面 工作状态 未开始识别
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM; // 启动后显示视频画面
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WORKING; // 启动后处于工作状态
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+
+ // 开始虹膜相机拍图
+ ProMemory::getInstance().irisCamCtrl->startCapture();
+
+ // 识别线程开始工作
+ initIrisRecogThread(); // 虹膜识别线程
+ ProMemory::getInstance().irisRecogPro->setWorking(true);
+}
+
+MainWindowForm::~MainWindowForm()
+{
+ ProMemory::getInstance().irisRecogPro->setWorking(false);
+ ProMemory::getInstance().irisRecogPro->exitThread();
+ ProMemory::getInstance().irisRecogPro->deleteLater();
+ ProMemory::getInstance().irisRecogPro->wait();
+
+ delete ui;
+ delete ProMemory::getInstance().irisRecogPro;
+}
+
+void MainWindowForm::lockScreenHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(lockScreenForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::LOCKSCREEN_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_WAIT; // App状态 = 待机
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(2.5f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().LOCK_FRAME_INTERVAL);
+
+ ui->labelMainTime->hide();
+ ui->labelMainDate->hide();
+ ui->labelLogo->show();
+ ui->labelLogo->setPixmap(QPixmap("images/logo.png"));
+
+ LOG_INFO("长时间未找到眼睛,开始待机");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+}
+
+void MainWindowForm::startIdentifyHandler()
+{
+ ui->wdgtStatced->setCurrentWidget(identifyForm);
+ ProMemory::getInstance().widgeFrame = AppConstants::WidgeFrameName::IDENTIFY_FORM;
+ ProMemory::getInstance().appState = AppConstants::ApplicationState::STATE_IDENTIFYING; // App状态 = 识别中
+ identifyForm->updateIdentifyTips("识 别 中");
+
+ ProMemory::getInstance().irisCamCtrl->SetCameraFrameRate(10.0f);
+ TimeCounterUtil::getInstance().irisCapCounter->setInterval(SettingConfig::getInstance().IRIS_FRAME_INTERVAL);
+
+ ui->labelMainTime->show();
+ ui->labelMainDate->show();
+ ui->labelLogo->hide();
+
+ LOG_INFO("找到眼睛,结束待机,开始工作");
+
+ // 重新绑定每秒的定时信号和槽函数
+ disconnect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, lockScreenForm, &LockScreenForm::showLockScreenTime);
+ connect(TimeCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &MainWindowForm::updateBannerTime);
+}
+
+void MainWindowForm::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ QTimer::singleShot(100, qApp, [=](){
+ QApplication::quit();
+ });
+
+ default:
+ QWidget::keyPressEvent(event);
+ }
+}
+
+void MainWindowForm::initFormsPtr()
+{
+ // 初始化各个form
+ lockScreenForm = new LockScreenForm(this);
+ identifyForm = new IdentifyForm(this);
+
+ // 将form添加到statcked widget中
+ ui->wdgtStatced->addWidget(identifyForm);
+ ui->wdgtStatced->addWidget(lockScreenForm);
+
+ // 绑定按钮函数
+}
+
+void MainWindowForm::initIrisRecogThread()
+{
+ // 虹膜识别处理过程
+ ProMemory::getInstance().irisRecogPro = new IrisRecogProcess(this);
+
+ // 绑定信号与槽函数
+ // 识别成功
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::findMatchedIris, identifyForm, &IdentifyForm::showRecognizeResult);
+
+ // 识别失败
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::failedMatchedIris, identifyForm, &IdentifyForm::showRecogFailure);
+
+ // 找到眼睛 开始识别
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::startIdentifyIris, this, &MainWindowForm::startIdentifyHandler);
+
+ // 持续没找到目标 待机
+ connect(ProMemory::getInstance().irisRecogPro, &IrisRecogProcess::backToLockScreen, this, &MainWindowForm::lockScreenHandler);
+
+ ProMemory::getInstance().irisRecogPro->start();
+}
+
+void MainWindowForm::updateBannerTime()
+{
+ QDateTime now = QDateTime::currentDateTime();
+ if (ProMemory::getInstance().widgeFrame == AppConstants::WidgeFrameName::IDENTIFY_FORM)
+ {
+ ui->labelMainTime->setText(now.toString("HH:mm:ss"));
+
+ if (now.toString("HH:mm:ss") == "00:00:00") {
+ ui->labelMainDate->setText(now.toString("yyyy-MM-dd dddd"));
+ }
+ }
+}
diff --git a/MainWindowForm.h b/MainWindowForm.h
new file mode 100644
index 0000000..9858b2a
--- /dev/null
+++ b/MainWindowForm.h
@@ -0,0 +1,43 @@
+#ifndef MAINWINDOWFORM_H
+#define MAINWINDOWFORM_H
+
+#include
+#include
+#include
+
+#include "utils/UtilInclude.h"
+#include "ProMemory.h"
+#include "LockScreenForm.h"
+#include "IdentifyForm.h"
+
+namespace Ui {
+class MainWindowForm;
+}
+
+class MainWindowForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindowForm(QWidget *parent = nullptr);
+ ~MainWindowForm();
+
+public slots:
+ void lockScreenHandler();
+ void startIdentifyHandler();
+
+private:
+ Ui::MainWindowForm *ui;
+ LockScreenForm * lockScreenForm;
+ IdentifyForm * identifyForm;
+
+ void keyPressEvent(QKeyEvent *event);
+
+ void initFormsPtr();
+ void initIrisRecogThread();
+
+private slots:
+ void updateBannerTime();
+};
+
+#endif // MAINWINDOWFORM_H
diff --git a/MainWindowForm.ui b/MainWindowForm.ui
new file mode 100644
index 0000000..79949db
--- /dev/null
+++ b/MainWindowForm.ui
@@ -0,0 +1,123 @@
+
+
+ MainWindowForm
+
+
+
+ 0
+ 0
+ 600
+ 1024
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ background: url(":images/bg_title.png")
+
+
+
+
+ 0
+ 0
+ 600
+ 84
+
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+ 0
+ 84
+ 600
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 246
+ 20
+ 108
+ 72
+
+
+
+
+
+
+ images/logo.png
+
+
+ true
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
-
+
+
+ TextLabel
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ProMemory.cpp b/ProMemory.cpp
new file mode 100644
index 0000000..0eacecb
--- /dev/null
+++ b/ProMemory.cpp
@@ -0,0 +1,94 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "ProMemory.h"
+
+ProMemory::ProMemory()
+{
+
+}
+
+ProMemory::~ProMemory()
+{
+
+}
+
+void ProMemory::pushCasicIris(CasicIrisInfo irisInfo)
+{
+ mutex.lock();
+ if (this->irisQueue.size() > 10)
+ {
+ QStack empty;
+ std::swap(empty, irisQueue);
+ }
+ irisQueue.push(irisInfo);
+ mutex.unlock();
+}
+CasicIrisInfo ProMemory::popCasicIris()
+{
+ CasicIrisInfo result;
+
+ mutex.lock();
+ if (this->irisQueue.size() > 0)
+ {
+ result = irisQueue.pop();
+ }
+ mutex.unlock();
+
+ return result;
+}
+
+int ProMemory::getIrisQueueSize()
+{
+ int size = 0;
+
+ mutex.lock();
+ size = this->irisQueue.size();
+ mutex.unlock();
+
+ return size;
+}
+bool ProMemory::isIrisQueueEmpty()
+{
+ bool empty = true;
+
+ mutex.lock();
+ empty = this->irisQueue.isEmpty();
+ mutex.unlock();
+
+ return empty;
+}
+void ProMemory::clearIrisQueue()
+{
+ mutex.lock();
+ QStack empty;
+ std::swap(empty, irisQueue);
+ mutex.unlock();
+}
+
+void ProMemory::initIrisFeatures()
+{
+ IrisDataDao irisDao;
+
+ QVector irisDataList = irisDao.findAllRecord();
+ for (QVariantMap iris : irisDataList) {
+ CasicIrisFeature featureLeft;
+ featureLeft.personId = iris.value("person_id").toString();
+ featureLeft.irisFeatureCode = iris.value("left_iris_code1").toByteArray();
+
+ CasicIrisFeature featureRight;
+ featureRight.personId = iris.value("person_id").toString();
+ featureRight.irisFeatureCode = iris.value("right_iris_code1").toByteArray();
+
+ irisFeatures.append(featureLeft);
+ irisFeatures.append(featureRight);
+ }
+
+ LOG_INFO(QString("加载虹膜特征值数据成功 %1个[IRIS Features loaded Success]").arg(irisFeatures.size()).toStdString());
+}
+
+QVector ProMemory::getIrisFeatures()
+{
+ return this->irisFeatures;
+}
diff --git a/ProMemory.h b/ProMemory.h
new file mode 100644
index 0000000..cf1fe42
--- /dev/null
+++ b/ProMemory.h
@@ -0,0 +1,57 @@
+#ifndef PROMEMORY_H
+#define PROMEMORY_H
+
+#include
+#include
+
+#include "AppConstants.h"
+#include "casic/iris/CasicIrisInfo.h"
+#include "dao/IrisDataDao.h"
+#include "utils/SocketClientUtil.h"
+
+#include "device/IrisCameraController.h"
+#include "device/iris/IrisRecogProcess.h"
+
+class IrisCameraController;
+class IrisRecogProcess;
+
+class ProMemory
+{
+public:
+ ~ProMemory();
+ ProMemory(const ProMemory&)=delete;
+ ProMemory& operator=(const ProMemory&)=delete;
+
+ static ProMemory& getInstance() {
+ static ProMemory instance;
+ return instance;
+ }
+
+ void pushCasicIris(CasicIrisInfo irisInfo);
+ CasicIrisInfo popCasicIris();
+ int getIrisQueueSize();
+ bool isIrisQueueEmpty();
+ void clearIrisQueue();
+
+ volatile int widgeFrame = 0; // 当前显示的界面
+ volatile int appState = 0; // 当前程序所处的状态
+
+ void initIrisFeatures(); // 初始化虹膜特征值集合
+
+ QVector getIrisFeatures();
+
+ IrisCameraController * irisCamCtrl;
+ IrisRecogProcess * irisRecogPro;
+
+ SocketClientUtil client;
+
+private:
+ ProMemory();
+
+ QMutex mutex;
+
+ QStack irisQueue; // 虹膜信息队列
+ QVector irisFeatures; // 虹膜特征值集合
+};
+
+#endif // PROMEMORY_H
diff --git a/casic/casic.pri b/casic/casic.pri
new file mode 100644
index 0000000..88263a7
--- /dev/null
+++ b/casic/casic.pri
@@ -0,0 +1,2 @@
+include(iris/casicIris.pri)
+
diff --git a/casic/iris/CasicIrisInfo.h b/casic/iris/CasicIrisInfo.h
new file mode 100644
index 0000000..e3c0735
--- /dev/null
+++ b/casic/iris/CasicIrisInfo.h
@@ -0,0 +1,38 @@
+#ifndef CASICIRISINFO_H
+#define CASICIRISINFO_H
+
+#include
+#include
+#include "CasicSegResult.h"
+
+struct CasicIrisInfo
+{
+ // 是否有眼睛, 默认为false
+ bool hasEye = false;
+
+ // post process
+ bool postProcSucc = false;
+
+ // 眼部图像
+ // 后续计算需要使用
+ cv::Mat matData; // 原始图像 找到眼睛之后裁剪成640 * 480的灰度图
+
+ cv::Mat maskNorm;
+ cv::Mat irisCode;
+
+ iristrt::CasicSegResult segResult;
+
+ // 字节数组形式的特征码
+ QByteArray irisFeatureCode;
+};
+
+struct CasicIrisFeature
+{
+ int irisId;
+ QString personId;
+ cv::Mat irisCode;
+ cv::Mat maskNorm;
+ QByteArray irisFeatureCode;
+};
+
+#endif // CASICIRISINFO_H
diff --git a/casic/iris/CasicIrisInterface.cpp b/casic/iris/CasicIrisInterface.cpp
new file mode 100644
index 0000000..5803f44
--- /dev/null
+++ b/casic/iris/CasicIrisInterface.cpp
@@ -0,0 +1,234 @@
+#ifdef _MSC_VER
+#pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8)
+#endif
+
+#include "CasicIrisInterface.h"
+
+#include
+#include
+#include
+
+casic::iris::CasicIrisInterface::CasicIrisInterface()
+{
+ rec = iristrt::CasicIrisRec(gaborFilterFileName, applicationPointsFileName);
+
+ cascade = new cv::CascadeClassifier();
+ cascade->load(cascadeName);
+}
+
+casic::iris::CasicIrisInterface::~CasicIrisInterface()
+{
+
+}
+
+void casic::iris::CasicIrisInterface::setCascadeFile(QString filename)
+{
+ this->cascadeName = filename.toStdString();
+}
+void casic::iris::CasicIrisInterface::setMinEyeSize(int minEyeSize)
+{
+ this->minEyeSize = minEyeSize;
+}
+void casic::iris::CasicIrisInterface::setMaxEyeSize(int maxEyeSize)
+{
+ this->maxEyeSize = maxEyeSize;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::findEye(CasicIrisInfo irisInfo)
+{
+ // 构建OpenCV自带的眼睛分类器
+ if (this->cascade == nullptr) {
+ this->cascade = new cv::CascadeClassifier();
+ this->cascade->load(cascadeName);
+ }
+
+ QElapsedTimer timer;
+ timer.start();
+
+ std::vector rect;
+ cv::Size minEyeRectSize(minEyeSize, minEyeSize);
+ cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize);
+
+ // ★分类器对象调用
+ cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize);
+
+ if (rect.size() == 0)
+ {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+// LOG(DEBUG) << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString();
+// LOG_DEBUG(QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString());
+ qDebug() << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+ .arg(timer.elapsed()).arg(rect.size())
+ .arg(rect.at(0).x).arg(rect.at(0).y)
+ .arg(rect.at(0).width).arg(rect.at(0).height);
+
+ irisInfo.hasEye = true;
+// irisInfo.eyeRect = rect.at(0);
+
+// irisInfo.data = ImageUtil::MatImageToQImage(irisInfo.matData);
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::findAndCutEye(CasicIrisInfo irisInfo)
+{
+ // 构建OpenCV自带的眼睛分类器
+ if (this->cascade == nullptr) {
+ this->cascade = new cv::CascadeClassifier();
+ this->cascade->load(cascadeName);
+ }
+
+ std::vector rect;
+ cv::Size minEyeRectSize(minEyeSize, minEyeSize);
+ cv::Size maxEyeRectSize(maxEyeSize, maxEyeSize);
+
+ if (irisInfo.matData.empty() == true) {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+ // ★分类器对象调用
+ cascade->detectMultiScale(irisInfo.matData, rect, 1.1, 3, cv::CASCADE_FIND_BIGGEST_OBJECT, minEyeRectSize, maxEyeRectSize);
+
+ if (rect.size() == 0)
+ {
+ irisInfo.hasEye = false;
+ return irisInfo;
+ }
+
+// LOG(DEBUG) << QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString();
+// LOG_DEBUG(QString("眼睛检测算法[tm: %1 ms][count: %2][rect: (%3, %4) %5 * %6]")
+// .arg(timer.elapsed()).arg(rect.size())
+// .arg(rect.at(0).x).arg(rect.at(0).y)
+// .arg(rect.at(0).width).arg(rect.at(0).height).toStdString());
+ qDebug() << QString("眼睛检测算法[count: %1][rect: (%2, %3) %4 * %5]")
+ .arg(rect.size())
+ .arg(rect.at(0).x).arg(rect.at(0).y)
+ .arg(rect.at(0).width).arg(rect.at(0).height);
+
+ // 找到眼睛之后, 将眼部裁剪下来, 图像拉伸到640 * 480
+ cv::Point center;
+ center.x = cvFloor(rect.at(0).x + rect.at(0).width*0.5);
+ center.y = cvFloor(rect.at(0).y + rect.at(0).height*0.5);
+
+ // 限制中心点的范围
+ if (center.x < SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5)
+ {
+ // x小于240则x=240
+ center.x = SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5;
+ } else if (center.x > SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5) {
+ // x大于1040则x=1040
+ center.x = SettingConfig::getInstance().IRIS_FRAME_WIDTH - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5;
+ }
+
+ if (center.y < SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5)
+ {
+ // y小于180则y=180
+ center.y = SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5;
+ } else if (center.y > SettingConfig::getInstance().IRIS_FRAME_HEIGHT - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5) {
+ center.y = SettingConfig::getInstance().IRIS_FRAME_HEIGHT - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5;
+ }
+
+ // 裁剪眼部图像
+ cv::Mat cutSize = irisInfo.matData.clone();
+ cutSize = irisInfo.matData(cv::Rect(center.x - SettingConfig::getInstance().IRIS_WIDTH * cutRatio * 0.5,
+ center.y - SettingConfig::getInstance().IRIS_HEIGHT * cutRatio * 0.5,
+ SettingConfig::getInstance().IRIS_WIDTH * cutRatio,
+ SettingConfig::getInstance().IRIS_HEIGHT * cutRatio));
+
+ // 裁剪后放大到 640 * 480
+ cv::resize(cutSize, cutSize, cv::Size(SettingConfig::getInstance().IRIS_WIDTH, SettingConfig::getInstance().IRIS_HEIGHT));
+ cv::flip(cutSize, cutSize, 1); // 左右翻转
+
+ irisInfo.hasEye = true;
+ irisInfo.postProcSucc = false;
+ irisInfo.matData = cutSize;
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::irisQualityAssess(CasicIrisInfo irisInfo)
+{
+
+ return irisInfo;
+}
+
+CasicIrisInfo casic::iris::CasicIrisInterface::irisEncode(CasicIrisInfo irisInfo)
+{
+// std::vector irisCircle, pupilCircle; // x,y,r
+ std::vector irisCircle(0); // x,y,r
+ std::vector pupilCircle(0); // x,y,r
+ iristrt::CasicSegPostProcess segPost;
+
+ cv::resize(irisInfo.segResult.irisMask, irisInfo.segResult.irisMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+ cv::resize(irisInfo.segResult.innerMask, irisInfo.segResult.innerMask, cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+ cv::resize(irisInfo.segResult.outerCircle, irisInfo.segResult.outerCircle,cv::Size(irisInfo.matData.cols, irisInfo.matData.rows));
+
+ bool flag = segPost.postProcess(irisInfo.segResult.irisMask, irisInfo.segResult.outerCircle, irisInfo.segResult.innerMask, irisCircle, pupilCircle);
+ if(!flag || irisCircle.size() <= 0 || pupilCircle.size() <= 0)
+ {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+// std::cout << "finish postProcess " << irisCircle[0] << " " << irisCircle[1] << " " << irisCircle[2] << " " << pupilCircle[0] << " " << pupilCircle[1] << " " << pupilCircle[2] << std::endl;
+ int iris_x = irisCircle[0];
+ int iris_y = irisCircle[1];
+ int iris_r = irisCircle[2];
+ int pupil_x = pupilCircle[0];
+ int pupil_y = pupilCircle[1];
+ int pupil_r = pupilCircle[2];
+ int dis = iristrt::point_distance(iris_x, iris_y, pupil_x, pupil_y);
+ if(!(dis + pupil_r < iris_r))
+ {
+ // pupil circle doesn't contained in iris circle
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+
+ cv::Mat imageNorm = rec.normalize(irisInfo.matData, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]);
+ if (imageNorm.empty() == true) {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+ irisInfo.maskNorm = rec.normalize(irisInfo.segResult.irisMask, irisCircle[0], irisCircle[1], irisCircle[2], pupilCircle[0], pupilCircle[1], pupilCircle[2]);
+ if (irisInfo.maskNorm.empty() == true)
+ {
+ irisInfo.postProcSucc = false;
+ return irisInfo;
+ }
+// std::cout << "finish normalize" << std::endl;
+// cv::imwrite("/home/nvidia/irisLogs/image-norm.bmp", imageNorm);
+
+ irisInfo.irisCode = rec.encodeToImage(imageNorm);
+ irisInfo.postProcSucc = true;
+
+ return irisInfo;
+}
+
+QByteArray casic::iris::CasicIrisInterface::extractFeature(CasicIrisInfo irisInfo)
+{
+ QByteArray irisFeatureCode = rec.extractFeature(irisInfo.irisCode, irisInfo.maskNorm);
+ return irisFeatureCode;
+}
+
+float casic::iris::CasicIrisInterface::calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo)
+{
+ return rec.matchImage(feature.irisCode, irisInfo.irisCode, feature.maskNorm, irisInfo.maskNorm);
+}
+
+float casic::iris::CasicIrisInterface::calculatePairPoints(QByteArray feature, QByteArray other)
+{
+ return rec.matchFeatureCode(reinterpret_cast(feature.data()), reinterpret_cast(other.data()));
+}
diff --git a/casic/iris/CasicIrisInterface.h b/casic/iris/CasicIrisInterface.h
new file mode 100644
index 0000000..7f91d68
--- /dev/null
+++ b/casic/iris/CasicIrisInterface.h
@@ -0,0 +1,54 @@
+#ifndef CASICIRISINTERFACE_H
+#define CASICIRISINTERFACE_H
+
+#include "CasicIrisInfo.h"
+#include "CasicSegPostProcess.h"
+#include "CasicIrisUtil.h"
+#include "CasicIrisRec.h"
+#include "utils/UtilInclude.h"
+
+namespace casic {
+ namespace iris {
+ class CasicIrisInterface
+ {
+ public:
+ ~CasicIrisInterface();
+ CasicIrisInterface(const CasicIrisInterface&)=delete;
+ CasicIrisInterface& operator=(const CasicIrisInterface&)=delete;
+
+ static CasicIrisInterface& getInstance() {
+ static CasicIrisInterface instance;
+ return instance;
+ }
+
+ CasicIrisInfo findEye(CasicIrisInfo irisInfo);
+ CasicIrisInfo findAndCutEye(CasicIrisInfo irisInfo);
+ CasicIrisInfo irisQualityAssess(CasicIrisInfo irisInfo);
+
+ CasicIrisInfo irisEncode(CasicIrisInfo irisInfo);
+ QByteArray extractFeature(CasicIrisInfo irisInfo);
+ float calculateMatchScore(CasicIrisFeature feature, CasicIrisInfo irisInfo);
+ float calculatePairPoints(QByteArray feature, QByteArray other);
+
+ void setCascadeFile(QString filename);
+ void setMinEyeSize(int minEyeSize);
+ void setMaxEyeSize(int maxEyeSize);
+
+ private:
+ CasicIrisInterface();
+
+ std::string cascadeName = "./model/haarcascade_eye.xml";
+ const char * gaborFilterFileName = "./model/filters.txt";
+ const char * applicationPointsFileName = "./model/points.txt";
+ int minEyeSize = 320;
+ int maxEyeSize = 480;
+ float cutRatio = 0.72f; // 裁剪比率 用于裁剪更大比例的眼部图像
+
+ cv::CascadeClassifier * cascade;
+ iristrt::CasicIrisRec rec;
+ };
+ }
+}
+
+
+#endif // CASICIRISINTERFACE_H
diff --git a/casic/iris/CasicIrisRec.cpp b/casic/iris/CasicIrisRec.cpp
new file mode 100644
index 0000000..c8d3bbb
--- /dev/null
+++ b/casic/iris/CasicIrisRec.cpp
@@ -0,0 +1,499 @@
+#include "CasicIrisRec.h"
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+using Eigen::MatrixXd;
+using Eigen::MatrixXi;
+
+namespace iristrt
+{
+CasicIrisRec::CasicIrisRec()
+{
+
+}
+
+CasicIrisRec::CasicIrisRec(const char * gaborFilterFileName,const char * applicationPointsFileName)
+{
+ loadApplicationPoints(applicationPointsFileName);
+ loadGaborFilters(gaborFilterFileName);
+}
+
+CasicIrisRec::~CasicIrisRec()
+{
+
+}
+
+cv::Mat CasicIrisRec::normalize(cv::Mat image, int iris_x, int iris_y, int iris_r,int pupil_x, int pupil_y, int pupil_r)
+{
+ int width = NORM_WIDTH;
+ int height = NORM_HEIGHT;
+ int realHeight = height + 2;
+ int angledivisions = width - 1;
+// int rows = image.rows;
+// int cols = image.cols;
+
+ double ox = pupil_x - iris_x;
+ double oy = pupil_y - iris_y;
+
+ int sgn = ox <= 0 ? -1 : 1;
+ if (ox == 0 && oy > 0) {
+ sgn = 1;
+ }
+
+ double phi = ox == 0 ? M_PI / 2 : atan(oy / ox);
+
+ MatrixXd a = MatrixXd::Ones(1, width) * (ox * ox + oy * oy);
+
+ MatrixXd thetas(1, width);
+ for (int i = 0; i < width; i++) {
+ thetas(0, i) = (2 * M_PI / angledivisions) * i;
+ }
+
+ MatrixXd b = M_PI - phi - thetas.array();
+ b = b.array().cos();
+ b = sgn * b;
+
+ MatrixXd item1 = a.array().sqrt() * b.array();
+ MatrixXd item2 = a.array() * b.array().pow(2);
+ MatrixXd item3 = a.array() - (iris_r * iris_r);
+ MatrixXd r = item1 + (item2 - item3).array().sqrt().matrix();
+ r = r.array() - pupil_r;
+
+ MatrixXd rMatrix = MatrixXd::Ones(1, realHeight).transpose() * r;
+ MatrixXd tmp(1, realHeight);
+ for (int i = 0; i < realHeight; i++) {
+ tmp(0, i) = (double)(1.0 / realHeight) * i;
+ }
+ rMatrix = rMatrix.array() * (MatrixXd::Ones(angledivisions + 1, 1) * tmp).array().transpose();
+ rMatrix = rMatrix.array() + pupil_r;
+
+ MatrixXd new_rMatrix = rMatrix.middleRows(1,realHeight-2);
+
+ MatrixXd xcosMat = MatrixXd::Ones(height, 1) * thetas.array().cos().matrix();
+ MatrixXd xsinMat = MatrixXd::Ones(height, 1) * thetas.array().sin().matrix();
+
+ MatrixXd xo = pupil_x + new_rMatrix.array() * xcosMat.array();
+ MatrixXd yo = pupil_y - new_rMatrix.array() * xsinMat.array();
+
+ MatrixXi xo_i = xo.cast();
+ MatrixXi yo_i = yo.cast();
+
+ if(image.channels() == 3){
+ cv::cvtColor(image,image,cv::COLOR_RGB2GRAY);
+ }
+
+ MatrixXi eigenImage;
+
+ cv::cv2eigen(image, eigenImage);
+
+ MatrixXi normMat = MatrixXi::Zero(xo_i.rows(), xo_i.cols());
+ for (int i = 0; i < xo_i.rows(); i++) {
+ for (int j = 0; j < xo_i.cols(); j++) {
+ if (yo_i(i, j) < 0 || xo_i(i, j) < 0) {
+ cv::Mat empty;
+ return empty;
+ }
+ normMat(i, j) = eigenImage(yo_i(i, j), xo_i(i, j));
+ }
+ }
+
+ cv::Mat normImage(image.size(),image.type());
+ cv::eigen2cv(normMat, normImage);
+ normImage.convertTo(normImage, CV_8UC1);
+
+ return normImage;
+}
+
+std::vector CasicIrisRec::loadGaborFilters(const char * gaborFilterFileName)
+{
+ std::ifstream file(gaborFilterFileName, std::ios::in);
+ if (!file)
+ {
+ std::cout << "Cannot load Gabor filters in file " << gaborFilterFileName << std::endl;
+ }
+
+ // Get the number of filters
+ int n_filters;
+ file >> n_filters;
+ gaborFilters.resize(n_filters);
+
+ //cout << "n_filters " << n_filters << endl;
+
+ // Size of filter
+ int rows, cols;
+
+ // Loop on each filter
+ for (int f = 0; f < n_filters; f++)
+ {
+ // Get the size of the filter
+ file >> rows;
+ file >> cols;
+ //cout << rows << " " << cols << endl;
+ // Temporary filter. Will be destroyed at the end of loop
+ gaborFilters[f] = cv::Mat(rows, cols, CV_32FC1);
+
+ // Set the value at coordinates r,c
+ for (int r = 0; r < rows; r++)
+ {
+ for (int c = 0; c < cols; c++)
+ {
+ file >> gaborFilters[f].at(r,c);
+ }
+ }
+
+ } // Loop on each filter
+
+ // Close the file
+ file.close();
+
+ return gaborFilters;
+}
+
+cv::Mat CasicIrisRec::loadApplicationPoints(const char * applicationPointsFileName)
+{
+ // Open text file containing the filters
+ std::ifstream file(applicationPointsFileName, std::ios::in);
+ if (!file)
+ {
+ std::cout << "Cannot load the application points in " << applicationPointsFileName << std::endl;
+ }
+
+ // Get the number of points
+ int n_points = 0;
+ file >> n_points;
+
+ // Allocate memory for the matrix containing the points
+ applicationPoints = cv::Mat(NORM_HEIGHT, NORM_WIDTH, CV_8UC1);
+ // Initialize all pixels to "off"
+ applicationPoints.setTo(cv::Scalar(0));
+
+ // Local variables
+ int i, j;
+
+ // Loop on each point
+ for (int p = 0; p < n_points; p++)
+ {
+ // Get the coordinates
+ file >> i; file >> j;
+
+ mvApplicationPoints.push_back(QPair(i, j));
+
+ // Set pixel to "on"
+ if (i < 0 || i > applicationPoints.rows - 1 || j < 0 || j > applicationPoints.cols- 1)
+ {
+ std::cout << "Point (" << i << "," << j << ") ";
+ std::cout << "exceeds size of normalized image : ";
+ std::cout << applicationPoints.rows << "x" << applicationPoints.cols;
+ std::cout << " while loading application points" << std::endl;
+ }
+ else
+ {
+ applicationPoints.at(i,j) = 255;
+ }
+ }
+
+ //cv::imshow("mpApplicationPoints", mpApplicationPoints);
+ //cv::waitKey(0);
+
+ // Close the file
+ file.close();
+
+ return applicationPoints;
+}
+
+cv::Mat CasicIrisRec::encodeToImage(cv::Mat normalizedImage)
+{
+ cv::Size size(normalizedImage.size());
+ cv::Mat encodeImage(cv::Size(size.width, size.height * gaborFilters.size()), CV_32FC1);
+
+ int max_width = 0;
+ for (int f = 0; f < gaborFilters.size(); f++)
+ if (gaborFilters[f].cols > max_width)
+ max_width = gaborFilters[f].cols;
+ max_width = (max_width - 1) / 2;
+
+ cv::Mat resized = addBorders(normalizedImage, max_width);
+
+// std::cout << resized.size() << std::endl;
+// cv::imshow("resized", resized);
+// cv::waitKey(0);
+
+ cv::Mat img1(resized.size(), CV_32F, 1);
+ cv::Mat img2(resized.size(), encodeImage.depth(), 1);
+
+ for (int f = 0; f < gaborFilters.size(); f++)
+ {
+ // Convolution
+ cv::filter2D(resized, img1, img1.depth(), gaborFilters[f]);
+
+ // Threshold : above or below 0
+ cv::threshold(img1, img2, 0, 255, cv::THRESH_BINARY);
+
+// cv::imshow("img2", img2);
+// cv::waitKey(0);
+
+ // Form the iris code
+ cv::Mat roi = img2(cv::Rect(max_width, 0, normalizedImage.cols, normalizedImage.rows));
+ cv::Mat dst = encodeImage(cv::Rect(0, f*normalizedImage.rows, normalizedImage.cols, normalizedImage.rows));
+ roi.copyTo(dst);
+ //cv::copyTo(img2, dst, NULL);
+ }
+ cv::Mat image8UC1;
+ encodeImage.convertTo(image8UC1, CV_8UC1);
+ return image8UC1;
+}
+
+QByteArray CasicIrisRec::extractFeature(cv::Mat irisCode, cv::Mat maskNorm)
+{
+ // count points width and height
+ cv::Mat pointTemp(applicationPoints);
+ cv::Mat rowTemp;
+
+ std::vector pointRows;
+ for (int i = 0; i < applicationPoints.rows; i++) {
+ rowTemp = pointTemp(cv::Rect(0, i, applicationPoints.cols, 1));
+ if (cv::sum(rowTemp)[0] > 0) {
+ pointRows.push_back(i);
+ }
+ }
+
+ int width = irisCode.cols;
+ int height = pointRows.size();
+ rowTemp.release();
+ pointTemp.release();
+
+ int n_codes = irisCode.rows / applicationPoints.rows;
+
+ int irisDataLength = (n_codes + 1) * width * height;
+ uchar * irisData = new uchar[irisDataLength];
+ int irisDataIndex = 0;
+
+ uchar* codePixel = new uchar;
+
+ // save iris code 512 * 8 * 6
+ for (int n = 0; n < n_codes; n++) { // 6
+ for (auto i : pointRows) { // 8
+ i = n * maskNorm.rows + i;
+ for (int j = 0; j < irisCode.cols; j++) { // 512
+ codePixel = (uchar*)(irisCode.data + i * irisCode.step + j);
+ if (*codePixel == 255) {
+ irisData[irisDataIndex++] = 1;
+ }
+ else {
+ irisData[irisDataIndex++] = *codePixel;
+ }
+ }
+ }
+ }
+
+ // save iris mask 512 * 8 * 1
+ uchar * maskPixel;
+ for (auto i : pointRows) { // 8
+ for (int j = 0; j < irisCode.cols; j++) { // 512
+ maskPixel = (uchar*)(maskNorm.data + i * maskNorm.step + j);
+ if (*maskPixel == 255) {
+ irisData[irisDataIndex++] = 1;
+ }
+ else {
+ irisData[irisDataIndex++] = *maskPixel;
+ }
+ }
+ }
+
+
+ uchar * irisFeaturePtr = new uchar[irisDataLength / 8 + 5];
+ memset(irisFeaturePtr, 0, irisDataLength / 8 + 5);
+
+ // first byte is width;
+ irisFeaturePtr[0] = (uchar)width;
+ irisFeaturePtr[1] = (uchar)(width >> 8);
+
+ // second byte is height;
+ irisFeaturePtr[2] = (uchar)height;
+
+ // third byte is n_codes
+ irisFeaturePtr[3] = (uchar)n_codes;
+
+ // fourth byte is n_mask(1)
+ irisFeaturePtr[4] = (uchar)1;
+ for (int i = 0; i < irisDataLength; i++) {
+ irisFeaturePtr[5 + i / 8] += irisData[i] << (7 - (i % 8));
+ }
+
+ QByteArray feature;
+ for (int i = 0; i < irisDataLength / 8 + 5; i++) {
+ feature.append((char) irisFeaturePtr[i]);
+ }
+
+ delete[] irisData;
+ delete[] irisFeaturePtr;
+ return feature;
+}
+
+float CasicIrisRec::matchImage(cv::Mat code1, cv::Mat code2, cv::Mat normalizedMask1, cv::Mat normalizedMask2)
+{
+ code1.convertTo(code1, CV_8UC1);
+ code2.convertTo(code2, CV_8UC1);
+
+ cv::Mat temp(applicationPoints.size(), CV_8UC1);
+ temp.setTo(cv::Scalar(0));
+
+ cv::bitwise_and(normalizedMask1, normalizedMask2, temp, applicationPoints);
+
+ // Copy the mask f times, where f correspond to the number of codes (= number of filters)
+ int n_codes = code1.rows / applicationPoints.rows;
+
+ cv::Mat totalMask(code1.size(), CV_8UC1);
+ for (int n = 0; n < n_codes; n++) {
+ cv::Mat maskRoi = totalMask(cv::Rect(0, n*applicationPoints.rows, applicationPoints.cols, applicationPoints.rows));
+ temp.copyTo(maskRoi);
+ }
+
+// cv::imshow("totalMask", totalMask);
+// cv::waitKey(0);
+
+ cv::Mat result(code1.size(), CV_8UC1);
+ result.setTo(cv::Scalar(0));
+
+ int shift = 10;
+ cv::Mat shifted = addBorders(code1, shift);
+
+ float score = 1;
+ for (int s = -shift; s <= shift; s++) {
+ cv::Mat roi = shifted(cv::Rect(shift + s, 0, code1.cols, code1.rows));
+ cv::bitwise_xor(roi, code2, result, totalMask);
+
+ float mean = (cv::sum(result).val[0]) / (cv::sum(totalMask).val[0]);
+ // std::cout << "mean: " << mean << std::endl;
+ score = std::min(score, mean);
+ }
+
+ // std::cout << "score: " << score << std::endl;
+ return score;
+
+}
+
+float CasicIrisRec::matchFeatureCode(uchar *feature1, uchar *feature2)
+{
+ int width = feature1[0] | feature1[1] << 8; // 32
+ int height = feature1[2]; // 8
+ int nCode = feature1[3]; // 6
+// int nMask = feature1[4];
+
+ uchar ** irisData1 = reduceIrisCode(feature1);
+ uchar ** irisMask1 = reduceIrisMask(feature1);
+ uchar ** irisData2 = reduceIrisCode(feature2);
+ uchar ** irisMask2 = reduceIrisMask(feature2);
+
+// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl;
+
+ int shift = 10;
+ float score = 1.0;
+
+ int minstep = 0 - shift;
+ int maxstep = shift;
+
+ for (int s = minstep; s <= maxstep; s++) {
+ int count = 0;
+ float mean = 0.0;
+ for (int n = 0; n < nCode; n++) {
+ for (auto pos : mvApplicationPoints) {
+ int row = pos.first / mvApplicationPoints[0].first - 1;
+ int col = (pos.second + s + width) % width;
+
+// std::cout << "array: " << row << ", " << pos.second << std::endl;
+ if (irisMask1[row][pos.second] == 1 && irisMask2[row][pos.second] == 1) {
+
+ uchar tmp1 = irisData1[row + height * n][col];
+ uchar tmp2 = irisData2[row + height * n][pos.second];
+ mean += tmp1 ^ tmp2;
+ count += 1;
+ }
+ }
+ }
+
+// std::cout << "shift " << s << " " << mean << "/" << count << " : " << mean / count << std::endl;
+ mean = mean / count;
+ score = mean < score ? mean : score;
+
+ }
+
+// std::cout << "feature score: " << score << std::endl;
+
+
+// for (int i = 0; i < height * nCode; i++) {
+// delete irisData1[i];
+// delete irisData2[i];
+// }
+// delete irisData1;
+// delete irisData2;
+
+// for (int i = 0; i < height; i++) {
+// delete irisMask1[i];
+// delete irisMask2[i];
+// }
+// delete irisMask1;
+// delete irisMask2;
+ return score;
+}
+
+cv::Mat CasicIrisRec::addBorders(cv::Mat pSrc, int width)
+{
+ cv::Mat result(cv::Size(pSrc.cols + 2 * width, pSrc.rows), pSrc.depth(), pSrc.channels());
+
+ cv::copyMakeBorder(pSrc, result, 0, 0, width, width, cv::BORDER_REPLICATE, 0);
+
+ for (int i = 0; i < pSrc.rows; i++) {
+ for (int j = 0; j < width; j++) {
+ result.at(i, j) = pSrc.at(i, pSrc.cols - width + j);
+ result.at(i, result.cols - width + j) = pSrc.at