diff --git a/CMakeLists.txt b/CMakeLists.txt index ccf938f..cadbc8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,11 +72,15 @@ option(RSID_DOXYGEN "Build doxygen docs" OFF) option(RSID_SECURE "Enable secure communication with device" OFF) option(RSID_TOOLS "Build additional tools" ON) option(RSID_PY "Build python wrapper" OFF) - +option(RSID_NETWORK "Enable networking. Required for license and update checker." ON) # install option option(RSID_INSTALL "Generate the install target and rsidConfig.cmake" OFF) +if(RSID_NETWORK) + add_compile_definitions(RSID_NETWORK) +endif() + if(RSID_TIDY) set(CMAKE_CXX_CLANG_TIDY "clang-tidy") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -96,13 +100,16 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${LIBS_OUTPUT_PATH}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${LIBS_OUTPUT_PATH}") SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -include(cmake/libcurl.cmake) -include(cmake/restClient.cmake) -include(cmake/nlohmann-json.cmake) -include(cmake/base64_hpp.cmake) +if(RSID_NETWORK) + include(cmake/libcurl.cmake) + include(cmake/restClient.cmake) + include(cmake/nlohmann-json.cmake) + include(cmake/base64_hpp.cmake) +endif() + include(cmake/OS.cmake) include(cmake/SpdLog.cmake) -if(MSVC) +if(MSVC AND RSID_NETWORK) include(cmake/winreg.cmake) endif() diff --git a/Readme.md b/Readme.md index e5e8ec8..47c1a89 100644 --- a/Readme.md +++ b/Readme.md @@ -45,23 +45,25 @@ $ make -j The following possible options are available for the `cmake` command -| Option | Default | Feature | -|----------------------|:-------:|:-------------------------------------------------| -| `RSID_DEBUG_CONSOLE` | `ON` | Log everything to console | -| `RSID_DEBUG_FILE` | `OFF` | Log everything to _rsid_debug.log_ file | -| `RSID_DEBUG_SERIAL` | `OFF` | Log all serial communication | -| `RSID_DEBUG_PACKETS` | `OFF` | Log packet sent/received over the serial line | -| `RSID_DEBUG_VALUES` | `OFF` | Replace default common values with debug ones | -| `RSID_PREVIEW` | `OFF` | Enables preview feature. | -| `RSID_SAMPLES` | `OFF` | Build samples | -| `RSID_TIDY` | `OFF` | Enable clang-tidy | -| `RSID_PEDANTIC` | `OFF` | Enable extra compiler warnings | -| `RSID_PROTECT_STACK` | `OFF` | Enable stack protection compiler flags | -| `RSID_DOXYGEN` | `OFF` | Build doxygen docs | -| `RSID_SECURE` | `OFF` | Enable secure communication with device | -| `RSID_TOOLS` | `ON` | Build additional tools | -| `RSID_PY` | `OFF` | Build python wrapper | -| `RSID_INSTALL` | `OFF` | Generate the install target and rsidConfig.cmake | +| Option | Default | Feature | +|----------------------|:-------:|:-----------------------------------------------------------| +| `RSID_DEBUG_CONSOLE` | `ON` | Log everything to console | +| `RSID_DEBUG_FILE` | `OFF` | Log everything to _rsid_debug.log_ file | +| `RSID_DEBUG_SERIAL` | `OFF` | Log all serial communication | +| `RSID_DEBUG_PACKETS` | `OFF` | Log packet sent/received over the serial line | +| `RSID_DEBUG_VALUES` | `OFF` | Replace default common values with debug ones | +| `RSID_PREVIEW` | `OFF` | Enables preview feature. | +| `RSID_SAMPLES` | `OFF` | Build samples | +| `RSID_TIDY` | `OFF` | Enable clang-tidy | +| `RSID_PEDANTIC` | `OFF` | Enable extra compiler warnings | +| `RSID_PROTECT_STACK` | `OFF` | Enable stack protection compiler flags | +| `RSID_DOXYGEN` | `OFF` | Build doxygen docs | +| `RSID_SECURE` | `OFF` | Enable secure communication with device | +| `RSID_TOOLS` | `ON` | Build additional tools | +| `RSID_PY` | `OFF` | Build python wrapper | +| `RSID_INSTALL` | `OFF` | Generate the install target and rsidConfig.cmake | +| `RSID_NETWORK` | `ON` | Enable networking. Required for license and update checker.| + ### Linux Post Install @@ -375,17 +377,7 @@ struct RSID_API DeviceConfig SpoofOnly = 2, // spoof only RecognitionOnly = 3 // recognition only }; - - /** - * @enum FaceSelectionPolicy - * @brief To run authentication on all (up to 5) detected faces vs single (closest) face - */ - enum class FaceSelectionPolicy - { - Single = 0, // default, run authentication on closest face - All = 1 // run authentication on all (up to 5) detected faces - }; - + enum class DumpMode { None = 0, @@ -395,8 +387,7 @@ struct RSID_API DeviceConfig CameraRotation camera_rotation = CameraRotation::Rotation_0_Deg; SecurityLevel security_level = SecurityLevel::Medium; - AlgoFlow algo_flow = AlgoFlow::All; - FaceSelectionPolicy face_selection_policy = FaceSelectionPolicy::Single; + AlgoFlow algo_flow = AlgoFlow::All; DumpMode dump_mode = DumpMode::None; }; ``` diff --git a/include/RealSenseID/AuthenticateStatus.h b/include/RealSenseID/AuthenticateStatus.h index 80355f5..7cb1cfe 100644 --- a/include/RealSenseID/AuthenticateStatus.h +++ b/include/RealSenseID/AuthenticateStatus.h @@ -34,6 +34,8 @@ enum class RSID_API AuthenticateStatus TooManySpoofs, InvalidFeatures, AmbiguiousFace, + /// Accessories + Sunglasses = 50, /// serial statuses Ok = 100, Error, @@ -43,13 +45,15 @@ enum class RSID_API AuthenticateStatus CrcError, LicenseError, LicenseCheck, - /// + /// Spoofs Spoof_2D = 120, Spoof_3D, Spoof_LR, Spoof_Disparity, Spoof_Surface, - Spoof_Plane_Disparity + Spoof_Plane_Disparity, + Spoof_2D_Right, + /* Note: Should not exceed 127 - to be a legal ascii*/ }; /** diff --git a/include/RealSenseID/DeviceConfig.h b/include/RealSenseID/DeviceConfig.h index 2538ca2..be5ec38 100644 --- a/include/RealSenseID/DeviceConfig.h +++ b/include/RealSenseID/DeviceConfig.h @@ -44,16 +44,7 @@ struct RSID_API DeviceConfig RecognitionOnly = 3 // recognition only }; - /** - * @enum FaceSelectionPolicy - * @brief Controls whether to run authentication on all (up to 5) detected faces vs single (closest) face - */ - enum class FaceSelectionPolicy - { - Single = 0, // default, run authentication on closest face - All = 1 // run authentication on all (up to 5) detected faces - }; - + enum class DumpMode { None = 0, // default @@ -79,7 +70,6 @@ struct RSID_API DeviceConfig CameraRotation camera_rotation = CameraRotation::Rotation_0_Deg; SecurityLevel security_level = SecurityLevel::Low; AlgoFlow algo_flow = AlgoFlow::FaceDetectionOnly; - FaceSelectionPolicy face_selection_policy = FaceSelectionPolicy::Single; DumpMode dump_mode = DumpMode::None; MatcherConfidenceLevel matcher_confidence_level = MatcherConfidenceLevel::Low; @@ -98,7 +88,6 @@ struct RSID_API DeviceConfig RSID_API const char* Description(DeviceConfig::CameraRotation rotation); RSID_API const char* Description(DeviceConfig::SecurityLevel level); RSID_API const char* Description(DeviceConfig::AlgoFlow algoMode); -RSID_API const char* Description(DeviceConfig::FaceSelectionPolicy policy); RSID_API const char* Description(DeviceConfig::DumpMode dump_mode); RSID_API const char* Description(DeviceConfig::MatcherConfidenceLevel matcher_confidence_level); @@ -123,12 +112,6 @@ inline OStream& operator<<(OStream& os, const DeviceConfig::SecurityLevel& level return os; } -template -inline OStream& operator<<(OStream& os, const DeviceConfig::FaceSelectionPolicy& policy) -{ - os << Description(policy); - return os; -} template inline OStream& operator<<(OStream& os, const DeviceConfig::DumpMode& dump_mode) diff --git a/include/RealSenseID/EnrollStatus.h b/include/RealSenseID/EnrollStatus.h index e0a421a..dad41f3 100644 --- a/include/RealSenseID/EnrollStatus.h +++ b/include/RealSenseID/EnrollStatus.h @@ -34,6 +34,8 @@ enum class RSID_API EnrollStatus Spoof, InvalidFeatures, AmbiguiousFace, + /// Accessories + Sunglasses = 50, /// serial statuses Ok = 100, Error, @@ -43,13 +45,14 @@ enum class RSID_API EnrollStatus CrcError, LicenseError, LicenseCheck, - /// + /// Spoofs Spoof_2D = 120, Spoof_3D, Spoof_LR, Spoof_Disparity, Spoof_Surface, - Spoof_Plane_Disparity + Spoof_Plane_Disparity, + Spoof_2D_Right }; /** diff --git a/include/RealSenseID/UpdateChecker.h b/include/RealSenseID/UpdateChecker.h index f716f99..4c0b14c 100644 --- a/include/RealSenseID/UpdateChecker.h +++ b/include/RealSenseID/UpdateChecker.h @@ -22,7 +22,13 @@ struct RSID_API ReleaseInfo { const char* fw_version_str = nullptr; const char* release_url = nullptr; const char* release_notes_url = nullptr; - ~ReleaseInfo(); + + ~ReleaseInfo() { + delete[] sw_version_str; + delete[] fw_version_str; + delete[] release_url; + delete[] release_notes_url; + } }; class RSID_API UpdateChecker diff --git a/include/RealSenseID/Version.h b/include/RealSenseID/Version.h index dc62846..277d6a0 100644 --- a/include/RealSenseID/Version.h +++ b/include/RealSenseID/Version.h @@ -9,7 +9,7 @@ #define RSID_VER_MAJOR 0 #define RSID_VER_MINOR 40 -#define RSID_VER_PATCH 0 +#define RSID_VER_PATCH 10 #define RSID_VERSION (RSID_VER_MAJOR * 10000 + RSID_VER_MINOR * 100 + RSID_VER_PATCH) @@ -36,4 +36,4 @@ RSID_API const char* CompatibleFirmwareVersion(); */ RSID_API bool IsFwCompatibleWithHost(const std::string& fw_version); -} // namespace RealSenseID \ No newline at end of file +} // namespace RealSenseID diff --git a/release_info.json b/release_info.json index b8816ca..1258d75 100644 --- a/release_info.json +++ b/release_info.json @@ -1,8 +1,8 @@ { - "sw_version": 4000, - "sw_version_str": "0.40.0", - "fw_version": 700000304, - "fw_version_str": "7.0.0.304", - "release_url": "https://github.com/IntelRealSense/RealSenseID/releases/tag/v0.40.0", - "release_notes_url": "https://github.com/IntelRealSense/RealSenseID/blob/v0.40.0/release_notes.txt" + "sw_version": 4010, + "sw_version_str": "0.40.10", + "fw_version": 705000303, + "fw_version_str": "7.5.0.303", + "release_url": "https://github.com/IntelRealSense/RealSenseID/releases/tag/v0.40.10", + "release_notes_url": "https://github.com/IntelRealSense/RealSenseID/blob/v0.40.10/release_notes.txt" } \ No newline at end of file diff --git a/release_notes.txt b/release_notes.txt index 82ccb3b..89dd23c 100644 --- a/release_notes.txt +++ b/release_notes.txt @@ -1,3 +1,18 @@ +Realsense ID version 0.40.10 +----------------------------------- +**Important:** To retain the device database, export it before upgrading. You can import it back after the upgrade using rsid-viewer +* New firmware release - version 7.5.0.303 + * Improved TPR for Anti-Spoofing + * Increased database limit to 1,000 users. + * Added anti spoofing limitations to enrollment + * Added standby mode for lower power consumption +* New host SW: + * Improved support for device databases with 1,000 users + * Added CMake option to compile without network support (`-DRSID_NETWORK=OFF`) + * Added Set/Get color gains to python API + * Removed support for multi-face authentication + + Realsense ID version 0.40.0 ----------------------------------- * New firmware release - version 7.0.0.304 diff --git a/samples/cpp/CMakeLists.txt b/samples/cpp/CMakeLists.txt index 9f98ad0..301ae71 100644 --- a/samples/cpp/CMakeLists.txt +++ b/samples/cpp/CMakeLists.txt @@ -32,10 +32,5 @@ if (RSID_PREVIEW) # snapshot preview add_executable(preview-snapshot-cpp-sample preview_snapshot.cc) target_link_libraries(preview-snapshot-cpp-sample PRIVATE rsid) - set_target_properties(preview-snapshot-cpp-sample PROPERTIES FOLDER "samples/cpp") - - # face-rects - add_executable(multi-faces-cpp-sample multi-faces.cc) - target_link_libraries(multi-faces-cpp-sample PRIVATE rsid) - set_target_properties(multi-faces-cpp-sample PROPERTIES FOLDER "samples/cpp") + set_target_properties(preview-snapshot-cpp-sample PROPERTIES FOLDER "samples/cpp") endif() \ No newline at end of file diff --git a/samples/cpp/multi-faces.cc b/samples/cpp/multi-faces.cc deleted file mode 100644 index 2a08b86..0000000 --- a/samples/cpp/multi-faces.cc +++ /dev/null @@ -1,148 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2020-2021 Intel Corporation. All Rights Reserved. - -// Sample of how to correlate detected face rectangle with authenticated user - -#include "RealSenseID/FaceAuthenticator.h" -#include "RealSenseID/Preview.h" -#include -#include - -RealSenseID::DeviceConfig device_config; - -class PreviewRender : public RealSenseID::PreviewImageReadyCallback -{ - std::vector _images_ts; - -public: - void OnPreviewImageReady(const RealSenseID::Image image) - { - std::cout << image.metadata.timestamp << std::endl; - _images_ts.push_back(image.metadata.timestamp); // save timestamps for matching to onFaceDetected - // image can be saved to file with timestamp in name - } - - const std::vector& GetImagesTimeStamps() - { - return _images_ts; - } -}; - -class MyAuthClbk : public RealSenseID::AuthenticationCallback -{ - std::vector _faces; - size_t _result_idx = 0; - unsigned int _ts =0; - -public: - void OnResult(const RealSenseID::AuthenticateStatus status, const char* user_id) override - { - std::cout << "\n******* OnResult #" << _result_idx << "*******" << std::endl; - std::cout << "Status: " << status << std::endl; - if (status == RealSenseID::AuthenticateStatus::Success) - { - if (device_config.algo_flow == RealSenseID::DeviceConfig::AlgoFlow::SpoofOnly) - { - std::cout << " Real face" << std::endl; - } - else - { - std::cout << "UserId: " << user_id << std::endl; - } - } - else if (status == RealSenseID::AuthenticateStatus::Forbidden) - { - std::cout << " User is not authenticated" << std::endl; - } - else if (status == RealSenseID::AuthenticateStatus::Spoof) - { - std::cout << " Spoof" << std::endl; - } - - - - - // print the corresponding face coords (that was received in OnFaceDetected) - if (_faces.size() > _result_idx) - { - auto& face = _faces[_result_idx]; - std::cout << "Face: " << face.x << "," << face.y << " " << face.w << "x" << face.h << std::endl; - } - _result_idx++; - std::cout << std::endl; - } - - void OnHint(const RealSenseID::AuthenticateStatus hint) override - { - std::cout << "OnHint " << hint << std::endl; - } - - void OnFaceDetected(const std::vector& faces, const unsigned int ts) override - { - _faces = faces; - _ts = ts; - } - - unsigned int GetLastTimeStamp() - { - return _ts; - } -}; - -int main() -{ - RealSenseID::FaceAuthenticator authenticator; - RealSenseID::PreviewConfig preview_config; - RealSenseID::Preview preview(preview_config); - -#ifdef _WIN32 - auto status = authenticator.Connect({"COM25"}); -#elif LINUX - auto status = authenticator.Connect({"/dev/ttyACM0"}); -#endif - if (status != RealSenseID::Status::Ok) - { - std::cout << "Failed connecting with status " << status << std::endl; - return 1; - } - - - // uncomment below line to configure FW to run Spoof detection only, by default all algo(s) are running - // device_config.algo_flow = RealSenseID::DeviceConfig::AlgoFlow::SpoofOnly; - - // configure FW to authenticate or detect spooofs all detected faces - device_config.face_selection_policy = RealSenseID::DeviceConfig::FaceSelectionPolicy::All; - - // apply configuration - status = authenticator.SetDeviceConfig(device_config); - - PreviewRender image_clbk; - MyAuthClbk auth_clbk; - - preview.StartPreview(image_clbk); - authenticator.Authenticate(auth_clbk); - preview.StopPreview(); - - // get timestamps saved in callbacks - auto face_detection_ts = auth_clbk.GetLastTimeStamp(); - auto images_ts = image_clbk.GetImagesTimeStamps(); - - if (face_detection_ts != 0) - { - // looking for the preview image that is closest to face detection by timestamp - for (auto it = images_ts.begin(); it != images_ts.end(); ++it) - { - if (*it >= face_detection_ts) - { - auto most_close = - (*it - face_detection_ts < face_detection_ts - *(it -1)) ? it : (it-1); // chose closest - - std::cout << "The image matched to OnFaceDetected is the #" << most_close - images_ts.begin() - << " image accquired." << std::endl; - std::cout << "Face detection timestamp: " << face_detection_ts << " milliseconds." << std::endl; - std::cout << "Image timestamp: " << *most_close << " milliseconds." << std::endl; - break; - } - } - } -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d5b7443..655cbcd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,12 +8,17 @@ target_link_libraries(${LIBRSID_CPP_TARGET} PRIVATE spdlog::spdlog Threads::Threads - $<$:mbedtls> + $<$:mbedtls> +) + +if(RSID_NETWORK) +target_link_libraries(${LIBRSID_CPP_TARGET} + PRIVATE rsid-license-checker nlohmann_json::nlohmann_json restclient-cpp ) - +endif() set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(HEADERS @@ -31,9 +36,13 @@ set(SOURCES "${SRC_DIR}/Version.cc" "${SRC_DIR}/Logging.cc" "${SRC_DIR}/FwUpdater.cc" - "${SRC_DIR}/DiscoverDevices.cc" - "${SRC_DIR}/UpdateChecker.cc" + "${SRC_DIR}/DiscoverDevices.cc" ) +if(RSID_NETWORK) + list(APPEND SOURCES "${SRC_DIR}/UpdateChecker.cc") +else() + list(APPEND SOURCES "${SRC_DIR}/UpdateCheckerNotImpl.cc") +endif() if(RSID_PREVIEW) @@ -46,8 +55,7 @@ if(RSID_PREVIEW) target_include_directories(${LIBRSID_CPP_TARGET} PRIVATE "${LIBJPEG_TURBO_INSTALL_DIR}/include") target_link_directories(${LIBRSID_CPP_TARGET} PRIVATE "${LIBJPEG_TURBO_INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}") target_link_libraries(${LIBRSID_CPP_TARGET} PRIVATE LibUVC::UVC jpeg) - endif() - + endif() add_subdirectory("${SRC_DIR}/Capture") endif() @@ -57,7 +65,7 @@ target_sources(${LIBRSID_CPP_TARGET} PRIVATE ${HEADERS} ${SOURCES}) target_include_directories(${LIBRSID_CPP_TARGET} PRIVATE "${SRC_DIR}" - $ + $<$:$> "${CMAKE_CURRENT_SOURCE_DIR}/Logger" PUBLIC "$" @@ -81,7 +89,10 @@ add_subdirectory("${SRC_DIR}/Logger") add_subdirectory("${SRC_DIR}/PacketManager") add_subdirectory("${SRC_DIR}/Matcher") add_subdirectory("${SRC_DIR}/FwUpdate") -add_subdirectory("${SRC_DIR}/LicenseChecker") + +if(RSID_NETWORK) + add_subdirectory("${SRC_DIR}/LicenseChecker") +endif() # set ide source group get_target_property(PROJECT_SOURCES ${LIBRSID_CPP_TARGET} SOURCES) diff --git a/src/FaceAuthenticator.cc b/src/FaceAuthenticator.cc index b2375df..5bf6004 100644 --- a/src/FaceAuthenticator.cc +++ b/src/FaceAuthenticator.cc @@ -78,17 +78,26 @@ bool FaceAuthenticator::HandleLicenseCheck(T status) } } +#ifdef RSID_NETWORK // 1. perform the given function and check // 2. if status is LicenseCheck perform license provision and retry #define CALL_IMPL(_func, ...) \ { \ - auto status = (_impl)->_func(__VA_ARGS__); \ + auto status = (_impl) -> _func(__VA_ARGS__); \ if (HandleLicenseCheck(status)) \ return (_impl)->_func(__VA_ARGS__); \ else \ return status; \ } +#else // if license handler is disabled, just call the function +#define CALL_IMPL(_func, ...) \ + { \ + return (_impl)->_func(__VA_ARGS__); \ + } +#endif // RSID_NETWORK + + Status FaceAuthenticator::Enroll(EnrollmentCallback& callback, const char* user_id) { CALL_IMPL(Enroll, callback, user_id); diff --git a/src/FaceAuthenticatorImpl.cc b/src/FaceAuthenticatorImpl.cc index d25a72d..6efd049 100644 --- a/src/FaceAuthenticatorImpl.cc +++ b/src/FaceAuthenticatorImpl.cc @@ -11,7 +11,11 @@ #include "RealSenseID/Faceprints.h" #include "Matcher/Matcher.h" #include "CommonValues.h" + +#ifdef RSID_NETWORK #include "LicenseChecker/LicenseChecker.h" +#endif // RSID_NETWORK + #include "string.h" #include #include @@ -19,6 +23,7 @@ #include #include #include +#include #ifdef _WIN32 #include "PacketManager/WindowsSerial.h" @@ -840,7 +845,7 @@ Status FaceAuthenticatorImpl::SetDeviceConfig(const DeviceConfig& device_config) settings[0] = static_cast(device_config.camera_rotation); settings[1] = static_cast(device_config.security_level); settings[2] = static_cast(device_config.algo_flow); - settings[3] = static_cast(device_config.face_selection_policy); + settings[3] = 0; // reserved (was face selection policy) settings[4] = static_cast(device_config.dump_mode); settings[5] = static_cast(device_config.matcher_confidence_level); settings[6] = static_cast(device_config.max_spoofs); @@ -926,10 +931,7 @@ Status FaceAuthenticatorImpl::QueryDeviceConfig(DeviceConfig& device_config) static_cast(data_packet_reply.payload.message.data_msg.data[1]); device_config.algo_flow = static_cast(data_packet_reply.payload.message.data_msg.data[2]); - - device_config.face_selection_policy = - static_cast(data_packet_reply.payload.message.data_msg.data[3]); - + device_config.dump_mode = static_cast(data_packet_reply.payload.message.data_msg.data[4]); device_config.matcher_confidence_level = @@ -944,7 +946,7 @@ Status FaceAuthenticatorImpl::QueryDeviceConfig(DeviceConfig& device_config) Status FaceAuthenticatorImpl::QueryUserIds(char** user_ids, unsigned int& number_of_users) { unsigned int retrieved_user_count = 0; - constexpr unsigned int chunk_size = 5; + constexpr unsigned int chunk_size = 50; if (user_ids == nullptr || number_of_users == 0) { @@ -1097,8 +1099,22 @@ Status FaceAuthenticatorImpl::QueryNumberOfUsers(unsigned int& number_of_users) Status FaceAuthenticatorImpl::Standby() { - LOG_ERROR(LOG_TAG, "Standby is not supported"); - return Status::Error; + auto status = _session.Start(_serial.get()); + if (status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Session start failed with status %d", static_cast(status)); + return ToStatus(status); + } + PacketManager::FaPacket fa_packet {PacketManager::MsgId::StandBy}; + status = _session.SendPacket(fa_packet); + if (status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Failed sending fa packet (status %d)", (int)status); + } + + // we're not waiting for the device to reply since it should be in standby mode + + return ToStatus(status); } Status FaceAuthenticatorImpl::Unlock() @@ -1641,103 +1657,129 @@ Status FaceAuthenticatorImpl::GetUsersFaceprints(Faceprints* user_features, unsi return all_is_well ? Status::Ok : ToStatus(bad_status); } -Status FaceAuthenticatorImpl::SetUsersFaceprints(UserFaceprints_t* user_features, unsigned int num_of_users) +Status FaceAuthenticatorImpl::SendUserFaceprints(UserFaceprints_t& features) { - bool all_users_set = true; - auto status = _session.Start(_serial.get()); - if (status != PacketManager::SerialStatus::Ok) - { - LOG_ERROR(LOG_TAG, "Session start failed with status %d", static_cast(status)); - return ToStatus(status); - } - for (unsigned int i = 0; i < num_of_users; i++) - { - try + try + { + const char* user_id = features.user_id; + if (!ValidateUserId(user_id)) { - UserFaceprints_t& user_desc = user_features[i]; - const char* user_id = user_desc.user_id; - if (!ValidateUserId(user_id)) - { - return Status::Error; - } - char buffer[sizeof(DBFaceprintsElement) + PacketManager::MaxUserIdSize + 1] = {0}; - strncpy(buffer, user_id, PacketManager::MaxUserIdSize + 1); - size_t offset = PacketManager::MaxUserIdSize + 1; - DBFaceprintsElement* desc = (DBFaceprintsElement*)&user_desc.faceprints; - memcpy(buffer + offset, (char*)desc, sizeof(*desc)); - offset += sizeof(*desc); - PacketManager::DataPacket data_packet {PacketManager::MsgId::SetUserFeatures, buffer, offset}; - - status = _session.SendPacket(data_packet); - if (status != PacketManager::SerialStatus::Ok) - { - LOG_ERROR(LOG_TAG, "Failed sending data packet (status %d)", (int)status); - all_users_set = false; - continue; - } - - status = _session.RecvDataPacket(data_packet); - if (status != PacketManager::SerialStatus::Ok) - { - LOG_ERROR(LOG_TAG, "Failed receiving data packet (status %d)", (int)status); - all_users_set = false; - continue; - } - if (data_packet.header.id != PacketManager::MsgId::SetUserFeatures) - { - LOG_ERROR(LOG_TAG, "Error updating/adding user to DB: %d", (int)status); - all_users_set = false; - continue; - } + return Status::Error; } - catch (std::exception& ex) + char buffer[sizeof(DBFaceprintsElement) + PacketManager::MaxUserIdSize + 1] = {0}; + strncpy(buffer, user_id, PacketManager::MaxUserIdSize + 1); + size_t offset = PacketManager::MaxUserIdSize + 1; + DBFaceprintsElement* desc = &(features.faceprints.data); + memcpy(buffer + offset, (char*)desc, sizeof(DBFaceprintsElement)); + offset += sizeof(*desc); + PacketManager::DataPacket data_packet {PacketManager::MsgId::SetUserFeatures, buffer, offset}; + + auto status = _session.SendPacket(data_packet); + if (status != PacketManager::SerialStatus::Ok) { - LOG_EXCEPTION(LOG_TAG, ex); - all_users_set = false; - continue; + LOG_ERROR(LOG_TAG, "Failed sending data packet (status %d)", (int)status); + return ToStatus(status); } - catch (...) + + status = _session.RecvDataPacket(data_packet); + if (status != PacketManager::SerialStatus::Ok) { - LOG_ERROR(LOG_TAG, "Unknown exception"); - all_users_set = false; - continue; + LOG_ERROR(LOG_TAG, "Failed receiving data packet (status %d)", (int)status); + return ToStatus(status); + } + if (data_packet.header.id != PacketManager::MsgId::SetUserFeatures) + { + LOG_ERROR(LOG_TAG, "Error updating/adding user to DB: %d", (int)status); + return Status::Error; } + return Status::Ok; } - if (!all_users_set) + catch (std::exception& ex) { + LOG_EXCEPTION(LOG_TAG, ex); return Status::Error; } - - // If succeeded setting all users, tell the device to save the detures DB to its storage - auto save_db_packet = std::make_unique(PacketManager::MsgId::SaveDatabase); - status = _session.SendPacket(*save_db_packet); - if (status != PacketManager::SerialStatus::Ok) - { - LOG_ERROR(LOG_TAG, "Failed sending SaveDatabase packet (status %d)", (int)status); - all_users_set = false; - } - // Wait for savedb reply - status = _session.RecvFaPacket(*save_db_packet); - if (status != PacketManager::SerialStatus::Ok) - { - LOG_ERROR(LOG_TAG, "Failed receiving savedb reply packet (status %d)", static_cast(status)); - return ToStatus(status); - } - auto msg_id = save_db_packet->header.id; - if (PacketManager::MsgId::Reply != msg_id) + catch (...) { - LOG_ERROR(LOG_TAG, "Got unexpected message id %d instead of MsgId::Reply", static_cast(msg_id)); + LOG_ERROR(LOG_TAG, "Unknown exception"); return Status::Error; } - auto status_code = save_db_packet->GetStatusCode(); - auto final_status = Status(status_code); - if (final_status != Status::Ok) +} + +// Set the device's faceprints DB with the given user faceprints. +// Do it in chunks of 50 users at a time. +Status FaceAuthenticatorImpl::SetUsersFaceprints(UserFaceprints_t* user_features, unsigned int num_of_users) +{ + // set start index and end index for chunck + const unsigned int chunk_size = 50; + auto n_chunks = (num_of_users / chunk_size) + ((num_of_users % chunk_size) ? 1 : 0); + unsigned int start_index = 0; + unsigned int end_index = 0; + for (unsigned int i = 0; i < n_chunks; i++) { - LOG_ERROR(LOG_TAG, "Failed saving DB to device. Status: %d", static_cast(status_code)); + start_index = i * chunk_size; + end_index = (std::min)(start_index + chunk_size, num_of_users); + LOG_INFO(LOG_TAG, "SetUsersFaceprints: Sending %u to %u", start_index+1, end_index); + + auto status = _session.Start(_serial.get()); + if (status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Session start failed with status %d", static_cast(status)); + return ToStatus(status); + } + + RealSenseID::Status send_status = Status::Ok; + for (unsigned int index = start_index; index < end_index; index++) + { + send_status = SendUserFaceprints(user_features[index]); + if (send_status != Status::Ok) + { + LOG_ERROR(LOG_TAG, "Failed sending user faceprints (status %d)", (int)send_status); + break; + } + } + + // ask the device to save to its storage before proceeding + auto save_db_packet = std::make_unique(PacketManager::MsgId::SaveDatabase); + status = _session.SendPacket(*save_db_packet); + if (status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Failed sending SaveDatabase packet (status %d)", (int)status); + return ToStatus(status); + } + // Wait for savedb reply + status = _session.RecvFaPacket(*save_db_packet); + if (status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Failed receiving savedb reply packet (status %d)", static_cast(status)); + return ToStatus(status); + } + auto msg_id = save_db_packet->header.id; + if (PacketManager::MsgId::Reply != msg_id) + { + LOG_ERROR(LOG_TAG, "Got unexpected message id %d instead of MsgId::Reply", static_cast(msg_id)); + return Status::Error; + } + auto status_code = save_db_packet->GetStatusCode(); + auto save_status = Status(status_code); + if (save_status != Status::Ok) + { + LOG_ERROR(LOG_TAG, "Failed saving DB to device. Status: %d", static_cast(status_code)); + return save_status; + } + + // break if not all data sent successfully for this chunk + if (send_status != Status::Ok) + { + return send_status; + } + // sleep between chunks to let the device time to perform other tasks if needed + std::this_thread::sleep_for(std::chrono::milliseconds(500)); } - return final_status; + return Status::Ok; } +#ifdef RSID_NETWORK Status FaceAuthenticatorImpl::SetLicenseKey(const std::string& license_key) { @@ -1847,9 +1889,29 @@ Status FaceAuthenticatorImpl::ProvideLicense() catch (...) { LOG_ERROR(LOG_TAG, "Unknown exception"); - return Status::Error; + return Status::Error; } } +#else +Status FaceAuthenticatorImpl::SetLicenseKey(const std::string& license_key) +{ + LOG_ERROR(LOG_TAG, "SetLicenseKey() is not enabled"); + return Status::Error; +} + +std::string FaceAuthenticatorImpl::GetLicenseKey() +{ + LOG_ERROR(LOG_TAG, "GetLicenseKey() is not enabled"); + return std::string {}; +} + +Status FaceAuthenticatorImpl::ProvideLicense() +{ + LOG_ERROR(LOG_TAG, "ProvideLicense() is not enabled"); + return Status::Error; +} + +#endif } // namespace RealSenseID diff --git a/src/FaceAuthenticatorImpl.h b/src/FaceAuthenticatorImpl.h index 4718df3..d019e62 100644 --- a/src/FaceAuthenticatorImpl.h +++ b/src/FaceAuthenticatorImpl.h @@ -73,8 +73,8 @@ class FaceAuthenticatorImpl Faceprints& updated_faceprints, ThresholdsConfidenceEnum matcher_confidence_level=ThresholdsConfidenceEnum::ThresholdsConfidenceLevel_High); Status GetUsersFaceprints(Faceprints* user_features, unsigned int& num_of_users); - Status SetUsersFaceprints(UserFaceprints* users_faceprints, unsigned int num_of_users); - + Status SetUsersFaceprints(UserFaceprints_t* users_faceprints, unsigned int num_of_users); + static Status SetLicenseKey(const std::string &license_key); static std::string GetLicenseKey(); Status ProvideLicense(); @@ -96,5 +96,6 @@ class FaceAuthenticatorImpl // wait for cancel flag while sleeping upto timeout void AuthLoopSleep(std::chrono::milliseconds timeout); static bool ValidateUserId(const char* user_id); + Status SendUserFaceprints(UserFaceprints_t& faceprints); }; } // namespace RealSenseID diff --git a/src/FwUpdate/FwUpdateEngine.cc b/src/FwUpdate/FwUpdateEngine.cc index b175124..5f34bc7 100644 --- a/src/FwUpdate/FwUpdateEngine.cc +++ b/src/FwUpdate/FwUpdateEngine.cc @@ -24,7 +24,7 @@ static const char* LOG_TAG = "FwUpdater"; static const char* DumpFilename = "fw-update.log"; static const std::set AllowedModules {"OPFW", "NNLED", "DNET", "RECOG", "YOLO", - "AS2DLR", "NNLAS", "NNLEDR", "SPOOFS", "ASDISP"}; + "AS2DLR", "NNLAS", "NNLEDR", "SPOOFS", "ASDISP", "ACCNET"}; static const std::string OPFW = "OPFW"; // Do not change static const std::string SCRAP = "SCRAP"; // Do not change diff --git a/src/Matcher/Matcher.cc b/src/Matcher/Matcher.cc index da3a815..960da96 100644 --- a/src/Matcher/Matcher.cc +++ b/src/Matcher/Matcher.cc @@ -394,111 +394,70 @@ ExtendedMatchResult Matcher::MatchFaceprintsToArray(const MatchElement& probe_fa // Does the DB entry of the user is W10type ? bool isEnrolledTypeInDbIsW10 = (FaceprintsTypeEnum::W10 == existing_faceprints_array[user_index].faceprints.data.featuresType); - // if faceprints type on the DB is W10 - we do the regular adaptive-learning flow. - if(isEnrolledTypeInDbIsW10) + // if should_update then we create an update vector such that: + // (1) the current new vector is blended into the latest adaptive vector. + // (2) then we make sure that the updated vector is not too far from the enrollment vector. + if(result.should_update) { - // if should_update then we create an update vector such that: - // (1) the current new vector is blended into the latest adaptive vector. - // (2) then we make sure that the updated vector is not too far from the enrollment vector. - if(result.should_update) + // Init updated_faceprints to the faceprints already exists in the DB + // + updated_faceprints = existing_faceprints_array[user_index].faceprints; + + const uint32_t vec_length = RSID_NUM_OF_RECOGNITION_FEATURES; + const feature_t* probeVector = &probe_faceprints.data.featuresVector[0]; + const feature_t* anchorVector = nullptr; + feature_t* galeryAdaptiveVector = nullptr; + + // handle with/without mask vectors properly. + // choose the correct adaptive vector, and set its flags (based on thresholds configuration). + switch(adaptiveThresholds.activeConfig) { - // Init updated_faceprints to the faceprints already exists in the DB - // - updated_faceprints = existing_faceprints_array[user_index].faceprints; - - const uint32_t vec_length = RSID_NUM_OF_RECOGNITION_FEATURES; - const feature_t* probeVector = &probe_faceprints.data.featuresVector[0]; - const feature_t* anchorVector = nullptr; - feature_t* galeryAdaptiveVector = nullptr; - - // handle with/without mask vectors properly. - // choose the correct adaptive vector, and set its flags (based on thresholds configuration). - switch(adaptiveThresholds.activeConfig) - { - case ThresholdsConfigEnum::ThresoldConfig_pM_gNM: - // since we are here only is should_update=true, then we - // set the adaptive withMask[] vector for the first time (with values of the new faceprints). - // - // since its the FIRST TIME - it will probably take 10-20 iterations to converge - // during LimitAdaptiveVector(). - anchorVector = &updated_faceprints.data.adaptiveDescriptorWithoutMask[0]; - galeryAdaptiveVector = &updated_faceprints.data.adaptiveDescriptorWithMask[0]; - ::memcpy(galeryAdaptiveVector, probeVector, sizeof(probe_faceprints.data.featuresVector)); - // mark the vector as "valid with mask" - galeryAdaptiveVector[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS] = FaVectorFlagsEnum::VecFlagValidWithMask; + case ThresholdsConfigEnum::ThresoldConfig_pM_gNM: + // since we are here only is should_update=true, then we + // set the adaptive withMask[] vector for the first time (with values of the new faceprints). + // + // since its the FIRST TIME - it will probably take 10-20 iterations to converge + // during LimitAdaptiveVector(). + anchorVector = &updated_faceprints.data.adaptiveDescriptorWithoutMask[0]; + galeryAdaptiveVector = &updated_faceprints.data.adaptiveDescriptorWithMask[0]; + ::memcpy(galeryAdaptiveVector, probeVector, sizeof(probe_faceprints.data.featuresVector)); + // mark the vector as "valid with mask" + galeryAdaptiveVector[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS] = FaVectorFlagsEnum::VecFlagValidWithMask; #if (RSID_MATCHER_DEBUG_LOGS) - LOG_DEBUG(LOG_TAG, "----> With-mask adaptation (first-time)."); + LOG_DEBUG(LOG_TAG, "----> With-mask adaptation (first-time)."); #endif - break; + break; - case ThresholdsConfigEnum::ThresoldConfig_pM_gM: - anchorVector = &updated_faceprints.data.adaptiveDescriptorWithoutMask[0]; - galeryAdaptiveVector = &updated_faceprints.data.adaptiveDescriptorWithMask[0]; - //galeryAdaptiveVector[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS] = FaVectorFlagsEnum::VecFlagValidWithMask; + case ThresholdsConfigEnum::ThresoldConfig_pM_gM: + anchorVector = &updated_faceprints.data.adaptiveDescriptorWithoutMask[0]; + galeryAdaptiveVector = &updated_faceprints.data.adaptiveDescriptorWithMask[0]; + //galeryAdaptiveVector[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS] = FaVectorFlagsEnum::VecFlagValidWithMask; #if (RSID_MATCHER_DEBUG_LOGS) - LOG_DEBUG(LOG_TAG, "----> With-mask adaptation (not first-time)."); + LOG_DEBUG(LOG_TAG, "----> With-mask adaptation (not first-time)."); #endif - break; + break; - case ThresholdsConfigEnum::ThresoldConfig_pNM_gNM: - default: - anchorVector = &updated_faceprints.data.enrollmentDescriptor[0]; - galeryAdaptiveVector = &updated_faceprints.data.adaptiveDescriptorWithoutMask[0]; - // galeryAdaptiveVector[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS] = FaVectorFlagsEnum::VecFlagValidWithoutMask; + case ThresholdsConfigEnum::ThresoldConfig_pNM_gNM: + default: + anchorVector = &updated_faceprints.data.enrollmentDescriptor[0]; + galeryAdaptiveVector = &updated_faceprints.data.adaptiveDescriptorWithoutMask[0]; + // galeryAdaptiveVector[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS] = FaVectorFlagsEnum::VecFlagValidWithoutMask; #if (RSID_MATCHER_DEBUG_LOGS) - LOG_DEBUG(LOG_TAG, "----> Without-mask adaptation."); + LOG_DEBUG(LOG_TAG, "----> Without-mask adaptation."); #endif - break; - } + break; + } - // blend the current adaptive galery vector with the new vector - BlendAverageVector(galeryAdaptiveVector, probeVector, vec_length); + // blend the current adaptive galery vector with the new vector + BlendAverageVector(galeryAdaptiveVector, probeVector, vec_length); - // make sure blended adaptive vector is not too far from enrollment vector - bool update_was_ok = LimitAdaptiveVector(galeryAdaptiveVector, anchorVector, - adaptiveThresholds, vec_length); + // make sure blended adaptive vector is not too far from enrollment vector + bool update_was_ok = LimitAdaptiveVector(galeryAdaptiveVector, anchorVector, + adaptiveThresholds, vec_length); - // disable update flag if something went wrong in the update process. - result.should_update = result.should_update && update_was_ok; - } + // disable update flag if something went wrong in the update process. + result.should_update = result.should_update && update_was_ok; } - // But we act differently if the DB faceprints of the user is RGB. - else // if(isEnrolledTypeInDbIsRgb) - { - // here DB data type of this user is RGB - so we'll replace it on the DB with the current authentication data (W10 type). - // note that we CAN'T do it if user hasMask at this authentication. - // - bool currentHasMask = (probe_faceprints.data.featuresVector[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS] == FaVectorFlagsEnum::VecFlagValidWithMask); - bool currentTypeIsW10 = (probe_faceprints.data.featuresType == FaceprintsTypeEnum::W10); - - if (result.isSame && currentTypeIsW10) - { - if(currentHasMask) - { - LOG_DEBUG(LOG_TAG, "---> We cannot allow mask after rgb enrollment"); - result.isSame = false; - } - else - { - LOG_DEBUG(LOG_TAG, "---> Going to update RGB image-based enrollment in the DB..."); - - // reset the DB entry of that user (like it was an W10 enrollment procedure). - updated_faceprints.data.featuresType = probe_faceprints.data.featuresType; - updated_faceprints.data.version = probe_faceprints.data.version; - // set the 2 vectors. - ::memcpy(&updated_faceprints.data.adaptiveDescriptorWithoutMask[0], &probe_faceprints.data.featuresVector[0], - sizeof(probe_faceprints.data.featuresVector)); - ::memcpy(&updated_faceprints.data.enrollmentDescriptor[0], &probe_faceprints.data.featuresVector[0], - sizeof(probe_faceprints.data.featuresVector)); - // mark the withMask vector as not-set. - updated_faceprints.data.adaptiveDescriptorWithMask[RSID_INDEX_IN_FEATURES_VECTOR_TO_FLAGS] = FaVectorFlagsEnum::VecFlagNotSet; - - // force should_update so the DB entry will be replaced. - result.should_update = true; - } - } - - } // information log message here. LOG_DEBUG(LOG_TAG, "match Score: %d, isSame: %d, shouldUpdate: %d, hasMask: %d, activeStrongTH: %d, activeUpdateTH: %d, activeThreshConfig: %d, confidenceLevel: %d.", diff --git a/src/Matcher/MatcherImplDefines.h b/src/Matcher/MatcherImplDefines.h index f904936..e4392c8 100644 --- a/src/Matcher/MatcherImplDefines.h +++ b/src/Matcher/MatcherImplDefines.h @@ -34,7 +34,7 @@ #define RSID_STRONG_THRESHOLD_PNM_GNM_HIGH_CONFIDENCE_LEVEL (768) #define RSID_STRONG_THRESHOLD_PM_GNM_HIGH_CONFIDENCE_LEVEL (1199) #define RSID_STRONG_THRESHOLD_PM_GM_HIGH_CONFIDENCE_LEVEL (1679) -#define RSID_STRONG_THRESHOLD_PNM_GNM_RGB_IMG_ENROLL_HIGH_CONFIDENCE_LEVEL (600) // for enroll from image W10 vs. RGB features. +#define RSID_STRONG_THRESHOLD_PNM_GNM_RGB_IMG_ENROLL_HIGH_CONFIDENCE_LEVEL (768) // for enroll from image W10 vs. RGB features. //--- #define RSID_UPDATE_THRESHOLD_PNM_GNM_HIGH_CONFIDENCE_LEVEL (1745) #define RSID_UPDATE_THRESHOLD_PM_GM_HIGH_CONFIDENCE_LEVEL (1745) @@ -46,7 +46,7 @@ #define RSID_STRONG_THRESHOLD_PNM_GNM_MEDIUM_CONFIDENCE_LEVEL (662) #define RSID_STRONG_THRESHOLD_PM_GNM_MEDIUM_CONFIDENCE_LEVEL (1071) #define RSID_STRONG_THRESHOLD_PM_GM_MEDIUM_CONFIDENCE_LEVEL (1485) -#define RSID_STRONG_THRESHOLD_PNM_GNM_RGB_IMG_ENROLL_MEDIUM_CONFIDENCE_LEVEL (600) // for enroll from image W10 vs. RGB features. +#define RSID_STRONG_THRESHOLD_PNM_GNM_RGB_IMG_ENROLL_MEDIUM_CONFIDENCE_LEVEL (662) // for enroll from image W10 vs. RGB features. //--- #define RSID_UPDATE_THRESHOLD_PNM_GNM_MEDIUM_CONFIDENCE_LEVEL (1745) #define RSID_UPDATE_THRESHOLD_PM_GM_MEDIUM_CONFIDENCE_LEVEL (1745) @@ -58,7 +58,7 @@ #define RSID_STRONG_THRESHOLD_PNM_GNM_LOW_CONFIDENCE_LEVEL (593) #define RSID_STRONG_THRESHOLD_PM_GNM_LOW_CONFIDENCE_LEVEL (966) #define RSID_STRONG_THRESHOLD_PM_GM_LOW_CONFIDENCE_LEVEL (1316) -#define RSID_STRONG_THRESHOLD_PNM_GNM_RGB_IMG_ENROLL_LOW_CONFIDENCE_LEVEL (600) // for enroll from image W10 vs. RGB features. +#define RSID_STRONG_THRESHOLD_PNM_GNM_RGB_IMG_ENROLL_LOW_CONFIDENCE_LEVEL (593) // for enroll from image W10 vs. RGB features. //--- #define RSID_UPDATE_THRESHOLD_PNM_GNM_LOW_CONFIDENCE_LEVEL (1745) #define RSID_UPDATE_THRESHOLD_PM_GM_LOW_CONFIDENCE_LEVEL (1745) diff --git a/src/StatusHelper.cc b/src/StatusHelper.cc index 657976c..02d5622 100644 --- a/src/StatusHelper.cc +++ b/src/StatusHelper.cc @@ -88,6 +88,8 @@ const char* Description(EnrollStatus status) return "LicenseError"; case RealSenseID::EnrollStatus::LicenseCheck: return "LicenseCheck"; + case RealSenseID::EnrollStatus::Spoof: + return "Spoof"; case RealSenseID::EnrollStatus::Spoof_2D: return "Spoof_2D"; case RealSenseID::EnrollStatus::Spoof_3D: @@ -100,10 +102,14 @@ const char* Description(EnrollStatus status) return "Spoof_Disparity"; case RealSenseID::EnrollStatus::InvalidFeatures: return "Invalid_Features"; + case RealSenseID::EnrollStatus::Spoof_2D_Right: + return "Spoof_2D_Right"; case RealSenseID::EnrollStatus::Spoof_Plane_Disparity: return "Spoof_Plane_Disparity"; case RealSenseID::EnrollStatus::AmbiguiousFace: return "Ambiguious_Face"; + case RealSenseID::EnrollStatus::Sunglasses: + return "Sunglasses"; default: return "Unknown Status"; } @@ -200,10 +206,14 @@ const char* Description(AuthenticateStatus status) return "TooManySpoofs"; case RealSenseID::AuthenticateStatus::InvalidFeatures: return "Invalid_Features"; + case RealSenseID::AuthenticateStatus::Spoof_2D_Right: + return "Spoof_2D_Right"; case RealSenseID::AuthenticateStatus::Spoof_Plane_Disparity: return "Spoof_Plane_Disparity"; case RealSenseID::AuthenticateStatus::AmbiguiousFace: return "Ambiguious_Face"; + case RealSenseID::AuthenticateStatus::Sunglasses: + return "Sunglasses"; default: return "Unknown Status"; } @@ -269,18 +279,6 @@ const char* Description(DeviceConfig::MatcherConfidenceLevel matcher_confidence_ } } -const char* Description(DeviceConfig::FaceSelectionPolicy policy) -{ - switch (policy) - { - case DeviceConfig::FaceSelectionPolicy::Single: - return "Single"; - case DeviceConfig::FaceSelectionPolicy::All: - return "All"; - default: - return "Unknown value"; - } -} const char* Description(DeviceConfig::DumpMode dump_mode) { diff --git a/src/UpdateChecker.cc b/src/UpdateChecker.cc index 773d13e..3259462 100644 --- a/src/UpdateChecker.cc +++ b/src/UpdateChecker.cc @@ -38,14 +38,6 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ReleaseInfoInternal, release_url, release_notes_url ) - -ReleaseInfo::~ReleaseInfo() -{ - delete[] sw_version_str; - delete[] fw_version_str; - delete[] release_url; - delete[] release_notes_url; -} } static const std::string RELEASE_ADDRESS = "https://raw.githubusercontent.com/IntelRealSense/RealSenseID/master/release_info.json"; diff --git a/src/UpdateCheckerNotImpl.cc b/src/UpdateCheckerNotImpl.cc new file mode 100644 index 0000000..0f18812 --- /dev/null +++ b/src/UpdateCheckerNotImpl.cc @@ -0,0 +1,22 @@ +#include "RealSenseID/UpdateChecker.h" +#include "Logger.h" + + +static const char* LOG_TAG = "UpdateCheckerNotImpl"; + +namespace RealSenseID +{ + +Status UpdateCheck::UpdateChecker::GetRemoteReleaseInfo(ReleaseInfo& release_info) const +{ + LOG_ERROR(LOG_TAG, "GetRemoteReleaseInfo(..) not implemented"); + return Status::Error; +} + +Status UpdateCheck::UpdateChecker::GetLocalReleaseInfo(const RealSenseID::SerialConfig& serial_config, + ReleaseInfo& release_info) const +{ + LOG_ERROR(LOG_TAG, "GetLocalReleaseInfo(..) not implemented"); + return Status::Error; +} +} // namespace RealSenseID diff --git a/tools/rsid-cli/main.cc b/tools/rsid-cli/main.cc index 59ce7e8..e93cf3c 100644 --- a/tools/rsid-cli/main.cc +++ b/tools/rsid-cli/main.cc @@ -268,7 +268,6 @@ void get_device_config(const RealSenseID::SerialConfig& serial_config) std::cout << " * Rotation: " << device_config.camera_rotation << std::endl; std::cout << " * Security: " << device_config.security_level << std::endl; std::cout << " * Algo flow Mode: " << device_config.algo_flow << std::endl; - std::cout << " * Face policy : " << device_config.face_selection_policy << std::endl; std::cout << " * Dump Mode: " << device_config.dump_mode << std::endl; std::cout << " * Matcher Confidence Level : " << device_config.matcher_confidence_level << std::endl; std::cout << " * Max spoof attempts: " << static_cast(device_config.max_spoofs) << std::endl; @@ -493,6 +492,7 @@ void unlock(const RealSenseID::SerialConfig& serial_config) // SetDeviceConfig void provide_license(const RealSenseID::SerialConfig& serial_config) { +#ifdef RSID_NETWORK using RealSenseID::FaceAuthenticator; auto authenticator = CreateAuthenticator(serial_config); auto license_key = FaceAuthenticator::GetLicenseKey(); @@ -513,6 +513,9 @@ void provide_license(const RealSenseID::SerialConfig& serial_config) } std::cout << "Status: " << status << std::endl << std::endl; +#else + std::cout << "** License handler is not enabled in this build\n"; +#endif // RSID_NETWORK } // get logs from the device and display last 2 KB @@ -1063,19 +1066,7 @@ void sample_loop(const RealSenseID::SerialConfig& serial_config) { config.camera_rotation = RealSenseID::DeviceConfig::CameraRotation::Rotation_180_Deg; } - - std::cout << "Set multiple face policy (single/all): "; - std::getline(std::cin, sec_level); - if (sec_level.find("all") != std::string::npos) - { - config.face_selection_policy = RealSenseID::DeviceConfig::FaceSelectionPolicy::All; - } - else - { - config.face_selection_policy = RealSenseID::DeviceConfig::FaceSelectionPolicy::Single; - } - - + // input max spoof attempts while (true) { diff --git a/tools/rsid-viewer/AuthSettingsInput.xaml b/tools/rsid-viewer/AuthSettingsInput.xaml index 6fbfa4d..5f2d802 100644 --- a/tools/rsid-viewer/AuthSettingsInput.xaml +++ b/tools/rsid-viewer/AuthSettingsInput.xaml @@ -17,19 +17,6 @@ - - - - - - - - - - - - - diff --git a/tools/rsid-viewer/AuthSettingsInput.xaml.cs b/tools/rsid-viewer/AuthSettingsInput.xaml.cs index 717ceeb..f6abca7 100644 --- a/tools/rsid-viewer/AuthSettingsInput.xaml.cs +++ b/tools/rsid-viewer/AuthSettingsInput.xaml.cs @@ -54,10 +54,7 @@ public AuthSettingsInput(string fwVersion, DeviceConfig? config, PreviewConfig = previewConfig.Value; UpdateUiSettingsValues(config.Value, previewConfig.Value, flowMode); } - - FaceSelectionPolicySingle.IsEnabled = hasConfig; - FaceSelectionPolicyAll.IsEnabled = hasConfig; - + AlgoFlow_All.IsEnabled = hasConfig; AlgoFlow_DetectionOnly.IsEnabled = hasConfig; AlgoFlow_RecognitionOnly.IsEnabled = hasConfig; @@ -83,14 +80,15 @@ public AuthSettingsInput(string fwVersion, DeviceConfig? config, DumpModeNone.IsEnabled = previewEnabledAuth; DumpModeFace.IsEnabled = previewEnabledAuth; DumpModeFull.IsEnabled = previewEnabledAuth; + #if !RSID_NETWORK + ActivateLicenseLink.Visibility = Visibility.Hidden; + CheckForUpdatesLink.Visibility = Visibility.Hidden; + #endif } private void UpdateUiSettingsValues(DeviceConfig deviceConfig, PreviewConfig previewConfig, MainWindow.FlowMode flowMode) - { - FaceSelectionPolicySingle.IsChecked = deviceConfig.faceSelectionPolicy == DeviceConfig.FaceSelectionPolicy.Single; - FaceSelectionPolicyAll.IsChecked = deviceConfig.faceSelectionPolicy == DeviceConfig.FaceSelectionPolicy.All; - + { AlgoFlow_All.IsChecked = deviceConfig.algoFlow == DeviceConfig.AlgoFlow.All; AlgoFlow_DetectionOnly.IsChecked = deviceConfig.algoFlow == DeviceConfig.AlgoFlow.FaceDetectionOnly; AlgoFlow_RecognitionOnly.IsChecked = deviceConfig.algoFlow == DeviceConfig.AlgoFlow.RecognitionOnly; @@ -122,14 +120,7 @@ void QueryUiSettingsValues(out DeviceConfig deviceConfig, out PreviewConfig prev { deviceConfig = new DeviceConfig(); previewConfig = new PreviewConfig(); - - - // policy - if (FaceSelectionPolicyAll.IsChecked.GetValueOrDefault()) - deviceConfig.faceSelectionPolicy = DeviceConfig.FaceSelectionPolicy.All; - else - deviceConfig.faceSelectionPolicy = DeviceConfig.FaceSelectionPolicy.Single; - + // algo flow if (AlgoFlow_All.IsChecked.GetValueOrDefault()) deviceConfig.algoFlow = DeviceConfig.AlgoFlow.All; @@ -240,18 +231,7 @@ private void SettingsApplyButton_Click(object sender, RoutedEventArgs e) errDialog.ShowDialog(); DialogResult = null; return; - } - - if (config.dumpMode == DeviceConfig.DumpMode.CroppedFace && - config.faceSelectionPolicy == DeviceConfig.FaceSelectionPolicy.All) - { - var errDialog = new ErrorDialog("Config Not Supported", - "Face Selection->All does not support cropped dump mode."); - errDialog.ShowDialog(); - DialogResult = null; - return; - } - + } DialogResult = true; } diff --git a/tools/rsid-viewer/DatabaseSerializer.cs b/tools/rsid-viewer/DatabaseSerializer.cs index 0fbd20a..c0094c7 100644 --- a/tools/rsid-viewer/DatabaseSerializer.cs +++ b/tools/rsid-viewer/DatabaseSerializer.cs @@ -22,6 +22,7 @@ public static bool Serialize(List<(rsid.Faceprints, string)> users, int db_versi try { JavaScriptSerializer js = new JavaScriptSerializer(); + js.MaxJsonLength = 1024 * 1024 * 10; DbObj json_root = new DbObj(); List jsonstring = new List(); foreach (var (faceprintsDb, userIdDb) in users) @@ -54,6 +55,7 @@ public static bool Serialize(List<(rsid.Faceprints, string)> users, int db_versi { using (StreamReader reader = new StreamReader(filename)) { JavaScriptSerializer js = new JavaScriptSerializer(); + js.MaxJsonLength = 1024 * 1024 * 10; DbObj obj = js.Deserialize(reader.ReadToEnd()); var usr_array = new List<(rsid.Faceprints, string)>(); foreach (var uf in obj.db) diff --git a/tools/rsid-viewer/FrameDumper.cs b/tools/rsid-viewer/FrameDumper.cs index e2f5562..f77b1c6 100644 --- a/tools/rsid-viewer/FrameDumper.cs +++ b/tools/rsid-viewer/FrameDumper.cs @@ -31,14 +31,14 @@ public FrameDumper(string dumpDir, string title) _fileNamePrefix = title.Contains("Enroll") ? "REG" : "AUTH"; } - public string DumpPreviewImage(rsid.PreviewImage image) + public string DumpPreviewImage(rsid.PreviewImage image, string additionalInfo) { lock (_mutex) { using (var bmp = new Bitmap(image.width, image.height, image.stride, PixelFormat.Format24bppRgb, image.buffer)) { var bmpSrc = ToBitmapSource(bmp); - var filename = GetJpgFilename(image); + var filename = GetJpgFilename(image, additionalInfo); var fullPath = Path.Combine(_dumpDir, filename); DumpBitmapImage(bmpSrc, fullPath); return fullPath; @@ -50,13 +50,13 @@ public string DumpPreviewImage(rsid.PreviewImage image) // Frame timestamp in micros // Face detection status // sensorID, led - public string DumpRawImage(rsid.PreviewImage image) - { + public string DumpRawImage(rsid.PreviewImage image, string additionalInfo) + { lock (_mutex) { var byteArray = new Byte[image.size]; Marshal.Copy(image.buffer, byteArray, 0, image.size); - var filename = GetRaw10Filename(image); + var filename = GetRaw10Filename(image, additionalInfo); var fullPath = Path.Combine(_dumpDir, filename); using (var fs = new FileStream(fullPath, FileMode.Create, FileAccess.Write)) { @@ -80,7 +80,7 @@ public void Cancel() } } - private static string GetRaw10Filename(rsid.PreviewImage image) + private static string GetRaw10Filename(rsid.PreviewImage image, string additionalInfo) { var timestampAvailable = image.metadata.timestamp != 0; var prefix = timestampAvailable ? $"timestamp_{image.metadata.timestamp}" : $"frame_{image.number}"; @@ -90,8 +90,8 @@ private static string GetRaw10Filename(rsid.PreviewImage image) uint gain = image.metadata.gain; var ledStr = (image.metadata.led != 0) ? "led_on" : "led_off"; var sensorStr = (image.metadata.sensor_id != 0) ? "right" : "left"; - uint status = image.metadata.status; - return $"{_fileNamePrefix}_{prefix}_exp_{exposure}_gain_{gain}_{ledStr}_sensor_{sensorStr}_status_{status}{Raw10Extension}"; + uint status = image.metadata.status; + return $"{_fileNamePrefix}_{prefix}_exp_{exposure}_gain_{gain}_{ledStr}_sensor_{sensorStr}_status_{status}{additionalInfo}{Raw10Extension}"; } else // metadata isn't valid { @@ -100,15 +100,15 @@ private static string GetRaw10Filename(rsid.PreviewImage image) } // get filename for jpg snapshots - private static string GetJpgFilename(rsid.PreviewImage image) - { + private static string GetJpgFilename(rsid.PreviewImage image, string additionalInfo) + { var timestampAvailable = image.metadata.timestamp != 0; var prefix = timestampAvailable ? $"timestamp_{image.metadata.timestamp}" : $"frame_{image.number}"; if (timestampAvailable) { uint exposure = image.metadata.exposure; uint gain = image.metadata.gain; - return $"{_fileNamePrefix}_{prefix}_exp_{exposure}_gain_{gain}{JpgExtension}"; + return $"{_fileNamePrefix}_{prefix}_exp_{exposure}_gain_{gain}{additionalInfo}{JpgExtension}"; } else // metadata isn't valid diff --git a/tools/rsid-viewer/MainWindow.xaml.cs b/tools/rsid-viewer/MainWindow.xaml.cs index c9d79a5..716e9b3 100644 --- a/tools/rsid-viewer/MainWindow.xaml.cs +++ b/tools/rsid-viewer/MainWindow.xaml.cs @@ -68,6 +68,7 @@ public enum FlowMode private bool _cancelWasCalled; private string _lastEnrolledUserId; private AuthStatus _lastAuthHint = AuthStatus.Serial_Ok; // To show only changed hints. + private bool _sunglassesDetected; private IntPtr _signatureHelpeHandle = IntPtr.Zero; private Database _db;// = new Database(); @@ -455,87 +456,83 @@ private async void FetchDeviceLog_Click(object sender, RoutedEventArgs e) } } - private void ExportButton_Click(object sender, RoutedEventArgs e) + private void ExportDatabaseJob(string dbfilename) { - SaveFileDialog sfd = new SaveFileDialog - { - Title = "Select File export DB to", - Filter = "db files (*.db)|*.db", - FilterIndex = 1 - }; - if (sfd.ShowDialog() == false) - return; - SetUiEnabled(false); - var dbfilename = sfd.FileName; if (!ConnectAuth()) return; - var db = new Database(dbfilename); - var exportedDb = _authenticator.GetUsersFaceprints(); - if (exportedDb == null) - { - ShowErrorMessage("Export DB", "Error while exporting users"); - OnStopSession(); - _authenticator.Disconnect(); - return; - } + OnStartSession("Exporting..", false); try { + ShowProgressTitle("Exporting.."); + var db = new Database(dbfilename); + var exportedDb = _authenticator.GetUsersFaceprints(); + if (exportedDb == null) + { + throw new Exception("Error while exporting users"); + } + foreach (var uf in exportedDb) { db.Push(uf.faceprints, uf.userID); } db.Save(); - } - catch (Exception ex) - { - Console.WriteLine("Exception: " + ex.Message); + + if (exportedDb.Count > 0) + { + ShowSuccessTitle($"Exported {exportedDb.Count} users"); + } + else + { + ShowFailedTitle("No users were exported"); + ShowErrorMessage("Export DB", "Error while exporting users"); + } } finally { - SetUiEnabled(true); - } - if (exportedDb.Count > 0) - ShowSuccessTitle("Database file was created successfully"); - else - { - ShowFailedTitle("No users were exported"); - ShowErrorMessage("Export DB", "Error while exporting users"); + OnStopSession(); + _authenticator.Disconnect(); } - OnStopSession(); - _authenticator.Disconnect(); } - private void ImportButton_Click(object sender, RoutedEventArgs e) + private void ExportButton_Click(object sender, RoutedEventArgs e) { - var openFileDialog = new OpenFileDialog + SaveFileDialog sfd = new SaveFileDialog { - Multiselect = false, - Title = "Select File to import from", + Title = "Select File export DB to", Filter = "db files (*.db)|*.db", FilterIndex = 1 }; - - if (openFileDialog.ShowDialog() == false) + if (sfd.ShowDialog() == false) return; - var dbfilename = openFileDialog.FileName; - if (!ConnectAuth()) return; - var usersFromDb = new List(); - - var db = new Database(dbfilename); - db.Load(); - - var uf = new UserFaceprints(); - foreach (var (faceprintsDb, userIdDb) in db.FaceprintsArray) - { - uf.userID = userIdDb; - uf.faceprints = faceprintsDb; - usersFromDb.Add(uf); - } + Task.Run(() => ExportDatabaseJob(sfd.FileName)); + } + private void ImportDatabaseJob(string dbfilename) + { try { - SetUiEnabled(false); + var db = new Database(dbfilename); + if (db.Load() < 0) + { + ShowFailedTitle("Invalid DB"); + ShowErrorMessage("Import DB", "Error while importing users"); + return; + } + + if (!ConnectAuth()) return; + OnStartSession($"Importing {db.FaceprintsArray.Count} users..", false); + ShowProgressTitle($"Importing {db.FaceprintsArray.Count} users.."); + var usersFromDb = new List(); + + var uf = new UserFaceprints(); + foreach (var (faceprintsDb, userIdDb) in db.FaceprintsArray) + { + uf.userID = userIdDb; + uf.faceprints = faceprintsDb; + usersFromDb.Add(uf); + } + if (_authenticator.SetUsersFaceprints(usersFromDb)) ShowSuccessTitle("All users imported successfully!"); else @@ -555,11 +552,31 @@ private void ImportButton_Click(object sender, RoutedEventArgs e) { OnStopSession(); _authenticator.Disconnect(); - SetUiEnabled(true); } } + private void ImportButton_Click(object sender, RoutedEventArgs e) + { + var openFileDialog = new OpenFileDialog + { + Multiselect = false, + Title = "Select File to import from", + Filter = "db files (*.db)|*.db", + FilterIndex = 1 + }; + + if (openFileDialog.ShowDialog() == false) + return; + + var dbfilename = openFileDialog.FileName; + + + Task.Run(() => ImportDatabaseJob(dbfilename)); + + } + + private void TogglePreviewOpacity(bool isActive) { @@ -941,7 +958,6 @@ private void LogDeviceConfig(DeviceConfig deviceConfig) ShowLog(" * Camera Rotation: " + deviceConfig.cameraRotation.ToString()); ShowLog(" * AntiSpoof Level: " + deviceConfig.securityLevel.ToString()); ShowLog(" * Algo Flow: " + deviceConfig.algoFlow); - ShowLog(" * Face Selection Policy: " + deviceConfig.faceSelectionPolicy); ShowLog(" * Dump Mode: " + deviceConfig.dumpMode.ToString()); ShowLog(" * Host Mode: " + _flowMode); ShowLog(" * Camera Index: " + _deviceState.PreviewConfig.cameraNumber); @@ -1313,11 +1329,14 @@ private void DumpImage(PreviewImage image) { try { + var additionalInfo = _sunglassesDetected ? "_sunglasses" : null; if (_deviceState.DeviceConfig.dumpMode == DeviceConfig.DumpMode.FullFrame) - _frameDumper.DumpRawImage(image); + { + _frameDumper.DumpRawImage(image, additionalInfo); + } else { - var filename = _frameDumper.DumpPreviewImage(image); + var filename = _frameDumper.DumpPreviewImage(image, additionalInfo); ShowDumpFile(filename); } @@ -1377,6 +1396,7 @@ private void OnStartSession(string title, bool activateDumps) RedDot.Visibility = Visibility.Visible; _cancelWasCalled = false; _lastAuthHint = AuthStatus.Serial_Ok; + _sunglassesDetected = false; AuthenticatingTextBlock.Text = "Authenticating..."; EnrollingTextBlock.Text = "Enrolling user..."; CancelAuthenticationButton.IsEnabled = true; @@ -1407,14 +1427,18 @@ private void OnStopSession() // Enroll callbacks private void OnEnrollHint(EnrollStatus hint, IntPtr ctx) { - ShowLog(hint.ToString()); + if (hint == EnrollStatus.Sunglasses) + { + _sunglassesDetected = true; + } + ShowLog("Hint: " + hint.ToString()); if (hint != EnrollStatus.Success) ShowProgressTitle(FriendlyString(hint)); } private void OnEnrollProgress(FacePose pose, IntPtr ctx) { - ShowLog(pose.ToString()); + ShowLog("Prgrs: " + pose.ToString()); } private void OnEnrollResult(EnrollStatus status, IntPtr ctx) @@ -1423,7 +1447,8 @@ private void OnEnrollResult(EnrollStatus status, IntPtr ctx) if (_cancelWasCalled) { - ShowSuccessTitle("Canceled"); + _lastEnrolledUserId = null; + ShowSuccessTitle("Canceled"); } else { @@ -1436,17 +1461,15 @@ private void OnEnrollResult(EnrollStatus status, IntPtr ctx) else if (status == EnrollStatus.EnrollWithMaskIsForbidden) { logmsg = "Enroll with mask is forbidden"; + _lastEnrolledUserId = null; } else { logmsg = FriendlyString(status); + _lastEnrolledUserId = null; } - - string guimsg = logmsg; - - ShowLog(logmsg); - + string guimsg = logmsg + (_sunglassesDetected ? " (sunglasses)" : String.Empty); VerifyResult(status == EnrollStatus.Success, guimsg, guimsg); } } @@ -1490,6 +1513,10 @@ private void OnEnrollExtractionResult(EnrollStatus status, IntPtr faceprintsHand guimsg += $" Faceprints version mismatch : DB backuped and cleaned."; } + if (_sunglassesDetected) + { + guimsg += " (sunglasses)"; + } ShowLog(logmsg); // handle enroll @@ -1501,7 +1528,6 @@ private void OnEnrollExtractionResult(EnrollStatus status, IntPtr faceprintsHand } RefreshUserListServer(); }); - } } // Return friendly string from authenticate or enroll status @@ -1529,6 +1555,10 @@ private void OnAuthHint(AuthStatus hint, IntPtr ctx) { ShowFailedTitle("No face detected"); } + if (hint == AuthStatus.Sunglasses) + { + _sunglassesDetected = true; + } } private void OnAuthResult(AuthStatus status, string userId, IntPtr ctx) @@ -1540,9 +1570,17 @@ private void OnAuthResult(AuthStatus status, string userId, IntPtr ctx) } else { - VerifyResultAuth(status, $"{userId}", FriendlyString(status), null, userId); + if (_sunglassesDetected) + { + VerifyResultAuth(status, $"{userId} (sunglasses)", FriendlyString(status), null, userId); + } + else + { + VerifyResultAuth(status, $"{userId}", FriendlyString(status), null, userId); + } } _lastAuthHint = AuthStatus.Serial_Ok; // show next hint, session is done + _sunglassesDetected = false; } private void OnFaceDeteced(IntPtr facesArr, int faceCount, uint ts, IntPtr ctx) @@ -1576,6 +1614,7 @@ public void OnAuthLoopExtractionResult(AuthStatus status, IntPtr faceprintsHandl VerifyResultAuth(status, string.Empty, FriendlyString(status)); } _lastAuthHint = AuthStatus.Serial_Ok; // show next hint, session is done + _sunglassesDetected = false; } private void OnAuthExtractionResult(AuthStatus status, IntPtr faceprintsHandle, IntPtr ctx) @@ -1597,6 +1636,7 @@ private void OnAuthExtractionResult(AuthStatus status, IntPtr faceprintsHandle, VerifyResultAuth(status, string.Empty, FriendlyString(status)); } _lastAuthHint = AuthStatus.Serial_Ok; // show next hint, session is done + _sunglassesDetected = false; } @@ -1654,7 +1694,8 @@ private void UpdateUsersUiList(string[] users) private void RefreshUserList() { // Query users and update the user list display - ShowLog("Query users.."); + ShowLog("Fetching users.."); + ShowProgressTitle("Fetching users.."); SetInstructionsToRefreshUsers(true); string[] users; var rv = _authenticator.QueryUserIds(out users); @@ -1662,6 +1703,7 @@ private void RefreshUserList() { throw new Exception("Query error: " + rv.ToString()); } + ClearTitle(); ShowLog($"{users.Length} users"); @@ -1732,8 +1774,16 @@ private void RefreshUserListServer() ShowLog($"S/N: {device.SerialNumber}\n"); BackgroundDispatch(() => { + // add fw version to the title (replace if already exists) if (!string.IsNullOrEmpty(device.FirmwareVersion)) - Title += $" (firmware {device.FirmwareVersion})"; + { + var idx = Title.IndexOf(" (firmware"); + if (idx != -1) + { + Title = Title.Substring(0, idx); + } + Title += $" (firmware {device.FirmwareVersion})"; + } SNText.Text = $"S/N: {device.SerialNumber}"; }); @@ -2013,9 +2063,10 @@ private void EnrollJob(Object threadContext) if (!ConnectAuth()) return; OnStartSession($"Enroll {userId}", true); - IntPtr userIdCtx = Marshal.StringToHGlobalUni(userId); + IntPtr userIdCtx = Marshal.StringToHGlobalUni(userId); try { + _lastEnrolledUserId = userId; ShowProgressTitle("Enroll in progress..."); _busy = true; var enrollArgs = new EnrollArgs @@ -2028,12 +2079,14 @@ private void EnrollJob(Object threadContext) ctx = userIdCtx }; var status = _authenticator.Enroll(enrollArgs); - if (status == Status.Ok) - { + if (status == Status.Ok && _lastEnrolledUserId != null) + { + // give some time to show the success message and refresh user list + Task.Delay(1600).Wait(); HideEnrollingLabelPanel(); RefreshUserList(); } - else + else if(status != Status.Ok) { ShowFailedTitle(status.ToString()); } @@ -2049,6 +2102,7 @@ private void EnrollJob(Object threadContext) _busy = false; _authenticator.Disconnect(); Marshal.FreeHGlobal(userIdCtx); + _lastEnrolledUserId = null; } } @@ -2320,8 +2374,14 @@ private void DeleteSingleUserJob(Object threadContext) { ShowProgressTitle("Deleting.."); bool successAll = true; + int progressCounter = 0; foreach (string userId in usersIds) { + progressCounter++; + if (usersIds.Count > 1) + { + ShowProgressTitle($"Deleting {progressCounter}/{usersIds.Count}"); + } ShowLog($"Delete user {userId}"); var status = _authenticator.RemoveUser(userId); if (status == Status.Ok) @@ -2334,7 +2394,6 @@ private void DeleteSingleUserJob(Object threadContext) successAll = false; } } - VerifyResult(successAll, "Delete success", "Delete failed"); RefreshUserList(); } diff --git a/wrappers/c/include/rsid_c/rsid_client.h b/wrappers/c/include/rsid_c/rsid_client.h index 65002f6..6db4ebe 100644 --- a/wrappers/c/include/rsid_c/rsid_client.h +++ b/wrappers/c/include/rsid_c/rsid_client.h @@ -26,8 +26,7 @@ extern "C" { rsid_camera_rotation_type camera_rotation; rsid_security_level_type security_level; - rsid_algo_mode_type algo_mode; - rsid_face_policy_type face_selection_policy; + rsid_algo_mode_type algo_mode; rsid_dump_mode dump_mode; rsid_matcher_confidence_level_type matcher_confidence_level; unsigned char max_spoofs; diff --git a/wrappers/c/include/rsid_c/rsid_status.h b/wrappers/c/include/rsid_c/rsid_status.h index 755ad1d..c04225e 100644 --- a/wrappers/c/include/rsid_c/rsid_status.h +++ b/wrappers/c/include/rsid_c/rsid_status.h @@ -40,12 +40,7 @@ extern "C" RSID_AlgoMode_SpoofOnly = 1, // run Anti-Spoofing algo(s) only. RSID_AlgoMode_RecognitionOnly = 2 // configures device to run recognition only without AS. } rsid_algo_mode_type; - - typedef enum - { - RSID_FacePolicy_Single = 0, // default, run authentication on closest face - RSID_FacePolicy_All = 1, // run authentication on all (up to 5) detected faces - } rsid_face_policy_type; + typedef enum { @@ -98,6 +93,7 @@ extern "C" RSID_Auth_TooManySpoofs, RSID_Auth_InvalidFeatures, RSID_Auth_AmbiguiousFace, + RSID_Auth_Sunglasses = 50, RSID_Auth_Serial_Ok = RSID_Ok, RSID_Auth_Serial_Error, RSID_Auth_Serial_SerialError, @@ -111,7 +107,8 @@ extern "C" RSID_Auth_Spoof_LR, RSID_Auth_Spoof_Disparity, RSID_Auth_Spoof_Surface, - RSID_Auth_Spoof_Plane_Disparity + RSID_Auth_Spoof_Plane_Disparity, + RSID_Auth_Spoof_2D_Right } rsid_auth_status; typedef enum @@ -138,6 +135,7 @@ extern "C" RSID_Enroll_Spoof, RSID_Enroll_InvalidFeatures, RSID_Enroll_AmbiguiousFace, + RSID_Enroll_Sunglasses = 50, RSID_Enroll_Serial_Ok = RSID_Ok, RSID_Enroll_Serial_Error, RSID_Enroll_Serial_SerialError, @@ -151,7 +149,8 @@ extern "C" RSID_Enroll_Spoof_LR, RSID_Enroll_Spoof_Disparity, RSID_Enroll_Spoof_Surface, - RSID_Enroll_Spoof_Plane_Disparity + RSID_Enroll_Spoof_Plane_Disparity, + RSID_Enroll_Spoof_2D_Right } rsid_enroll_status; diff --git a/wrappers/c/src/rsid_c_client.cc b/wrappers/c/src/rsid_c_client.cc index c5a3b2a..e03d3c9 100644 --- a/wrappers/c/src/rsid_c_client.cc +++ b/wrappers/c/src/rsid_c_client.cc @@ -416,9 +416,7 @@ RealSenseID::DeviceConfig device_config_from_c_struct(const rsid_device_config* RealSenseID::DeviceConfig config; config.camera_rotation = static_cast(device_config->camera_rotation); config.security_level = static_cast(device_config->security_level); - config.algo_flow = static_cast(device_config->algo_mode); - config.face_selection_policy = - static_cast(device_config->face_selection_policy); + config.algo_flow = static_cast(device_config->algo_mode); config.dump_mode = static_cast(device_config->dump_mode); config.matcher_confidence_level = static_cast(device_config->matcher_confidence_level); @@ -514,8 +512,7 @@ rsid_status rsid_query_device_config(rsid_authenticator* authenticator, rsid_dev device_config->camera_rotation = static_cast(config.camera_rotation); device_config->security_level = static_cast(config.security_level); - device_config->algo_mode = static_cast(config.algo_flow); - device_config->face_selection_policy = static_cast(config.face_selection_policy); + device_config->algo_mode = static_cast(config.algo_flow); device_config->dump_mode = static_cast(config.dump_mode); device_config->matcher_confidence_level = static_cast(config.matcher_confidence_level); diff --git a/wrappers/csharp/Authenticator.cs b/wrappers/csharp/Authenticator.cs index 64bc49e..d4d6bdf 100644 --- a/wrappers/csharp/Authenticator.cs +++ b/wrappers/csharp/Authenticator.cs @@ -57,6 +57,8 @@ public enum EnrollStatus EnrollWithMaskIsForbidden, // for mask-detector : we'll forbid enroll with mask. Spoof, InvalidFeatures, + RSID_Enroll_AmbiguiousFace, + Sunglasses = 50, Serial_Ok = 100, Serial_Error, Serial_SerialError, @@ -70,7 +72,8 @@ public enum EnrollStatus Spoof_LR, Spoof_Disparity, Spoof_Surface, - Spoof_Plane_Disparity + Spoof_Plane_Disparity, + Spoof_2D_Right, } public enum FacePose @@ -272,12 +275,6 @@ public enum AlgoFlow RecognitionOnly = 3 // recognition only }; - public enum FaceSelectionPolicy - { - Single = 0, // default, run authentication on closest face - All = 1 // run authenticatoin on all (up to 5) detected faces - } - public enum DumpMode { None, @@ -287,8 +284,7 @@ public enum DumpMode public CameraRotation cameraRotation; public SecurityLevel securityLevel; - public AlgoFlow algoFlow; - public FaceSelectionPolicy faceSelectionPolicy; + public AlgoFlow algoFlow; public DumpMode dumpMode; public MatcherConfidenceLevel matcherConfidenceLevel; public byte maxSpoofs; @@ -321,6 +317,7 @@ public enum AuthStatus TooManySpoofs, InvalidFeatures, AmbiguiousFace, + Sunglasses = 50, Serial_Ok = 100, Serial_Error, Serial_SerialError, @@ -334,7 +331,8 @@ public enum AuthStatus Spoof_LR, Spoof_Disparity, Spoof_Surface, - Spoof_Plane_Disparity + Spoof_Plane_Disparity, + Spoof_2D_Right, } diff --git a/wrappers/python/device_controller_py.cc b/wrappers/python/device_controller_py.cc index 6ded50f..8d66b68 100644 --- a/wrappers/python/device_controller_py.cc +++ b/wrappers/python/device_controller_py.cc @@ -58,5 +58,18 @@ void init_device_controller(pybind11::module& m) RSID_THROW_ON_ERROR(self.FetchLog(log)); return log; }, + py::call_guard()) + .def( + "set_color_gains", + [](DeviceController& self, int red, int blue) { RSID_THROW_ON_ERROR(self.SetColorGains(red, blue)); }, + py::arg("red"), py::arg("blue"), py::doc("Set red+blue color gains. Valid range: 0-511"), + py::call_guard()) + .def( + "get_color_gains", [](DeviceController& self) { + int red, blue; + RSID_THROW_ON_ERROR(self.GetColorGains(red, blue)); + return std::make_tuple(red, blue); + } + , py::doc("Get device color gains as a tuple (red,blue)"), py::call_guard()); } \ No newline at end of file diff --git a/wrappers/python/face_auth_py.cc b/wrappers/python/face_auth_py.cc index 045a085..d70dd9c 100644 --- a/wrappers/python/face_auth_py.cc +++ b/wrappers/python/face_auth_py.cc @@ -358,7 +358,9 @@ void init_face_authenticator(pybind11::module& m) .value("Spoof_LR", AuthenticateStatus::Spoof_LR) .value("Spoof_Surface", AuthenticateStatus::Spoof_Surface) .value("Spoof_Disparity", AuthenticateStatus::Spoof_Disparity) - .value("Spoof_Plane_Disparity", AuthenticateStatus::Spoof_Plane_Disparity); + .value("Spoof_2D_Right", AuthenticateStatus::Spoof_2D_Right) + .value("Spoof_Plane_Disparity", AuthenticateStatus::Spoof_Plane_Disparity) + .value("Sunglasses", AuthenticateStatus::Sunglasses); py::enum_(m, "EnrollStatus") .value("Success", EnrollStatus::Success) @@ -395,7 +397,9 @@ void init_face_authenticator(pybind11::module& m) .value("Spoof_LR", EnrollStatus::Spoof_LR) .value("Spoof_Surface", EnrollStatus::Spoof_Surface) .value("Spoof_Disparity", EnrollStatus::Spoof_Disparity) - .value("Spoof_Plane_Disparity", EnrollStatus::Spoof_Plane_Disparity); + .value("Spoof_2D_Right", EnrollStatus::Spoof_2D_Right) + .value("Spoof_Plane_Disparity", EnrollStatus::Spoof_Plane_Disparity) + .value("Sunglasses", EnrollStatus::Sunglasses); py::enum_(m, "FacePose") @@ -442,12 +446,7 @@ void init_face_authenticator(pybind11::module& m) .value("FaceDetectionOnly", DeviceConfig::AlgoFlow::FaceDetectionOnly) .value("SpoofOnly", DeviceConfig::AlgoFlow::SpoofOnly) .value("RecognitionOnly", DeviceConfig::AlgoFlow::RecognitionOnly); - - - py::enum_(m, "FaceSelectionPolicy") - .value("Single", DeviceConfig::FaceSelectionPolicy::Single) - .value("All", DeviceConfig::FaceSelectionPolicy::All); - + py::enum_(m, "DumpMode") .value("Disable", DeviceConfig::DumpMode::None) .value("CroppedFace", DeviceConfig::DumpMode::CroppedFace) @@ -460,8 +459,7 @@ void init_face_authenticator(pybind11::module& m) }) .def_readwrite("camera_rotation", &DeviceConfig::camera_rotation) .def_readwrite("security_level", &DeviceConfig::security_level) - .def_readwrite("algo_flow", &DeviceConfig::algo_flow) - .def_readwrite("face_selection_policy", &DeviceConfig::face_selection_policy) + .def_readwrite("algo_flow", &DeviceConfig::algo_flow) .def_readwrite("dump_mode", &DeviceConfig::dump_mode) .def_readwrite("matcher_confidence_level", &DeviceConfig::matcher_confidence_level) .def_readwrite("max_spoofs", &DeviceConfig::max_spoofs) @@ -472,8 +470,7 @@ void init_face_authenticator(pybind11::module& m) << "camera_rotation=" << cfg.camera_rotation << ", " << "security_level=" << cfg.security_level << ", " << "matcher_confidence_level=" << cfg.matcher_confidence_level << ", " - << "algo_flow=" << cfg.algo_flow << ", " - << "face_selection_policy=" << cfg.face_selection_policy << ", " + << "algo_flow=" << cfg.algo_flow << ", " << "dump_mode=" << cfg.dump_mode << ", " << "max_spoofs=" << static_cast(cfg.max_spoofs) << '>'; return oss.str();