From 052d9e3c7e049c4ef4170452fefb3f17b86a105a Mon Sep 17 00:00:00 2001 From: tunm Date: Mon, 30 Sep 2024 10:45:42 +0800 Subject: [PATCH] update to 1.1.7 --- cpp-package/inspireface/CMakeLists.txt | 2 +- cpp-package/inspireface/README.md | 2 + .../cpp/inspireface/c_api/inspireface.h | 2 +- .../cpp/inspireface/track_module/face_track.h | 2 +- .../cpp/sample/cpp/sample_face_track.cpp | 44 ++++-- .../cpp/test/unit/api/test_feature_hub.cpp | 146 +++++++++++++++--- .../cpp/test/unit/api/test_feature_manage.cpp | 141 ++++++++++------- 7 files changed, 236 insertions(+), 103 deletions(-) diff --git a/cpp-package/inspireface/CMakeLists.txt b/cpp-package/inspireface/CMakeLists.txt index a570bfe..23c3a63 100644 --- a/cpp-package/inspireface/CMakeLists.txt +++ b/cpp-package/inspireface/CMakeLists.txt @@ -10,7 +10,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") # Current version set(INSPIRE_FACE_VERSION_MAJOR 1) set(INSPIRE_FACE_VERSION_MINOR 1) -set(INSPIRE_FACE_VERSION_PATCH 6) +set(INSPIRE_FACE_VERSION_PATCH 7) # Converts the version number to a string string(CONCAT INSPIRE_FACE_VERSION_MAJOR_STR ${INSPIRE_FACE_VERSION_MAJOR}) diff --git a/cpp-package/inspireface/README.md b/cpp-package/inspireface/README.md index 3b30198..d6977b8 100644 --- a/cpp-package/inspireface/README.md +++ b/cpp-package/inspireface/README.md @@ -13,6 +13,8 @@ Please contact [contact@insightface.ai](mailto:contact@insightface.ai?subject=In ## Change Logs +**`2024-09-30`** Fixed some bugs in the feature hub. + **`2024-08-18`** Updating [Benchmark](doc/Benchmark-Remark(Updating).md): Using CoreML with Apple's Neural Engine (ANE) on the iPhone 13, the combined processes of **Face Detection** + **Alignment** + **Feature Extraction** take less than **2ms**. **`2024-07-17`** Add global resource statistics monitoring to prevent memory leaks. diff --git a/cpp-package/inspireface/cpp/inspireface/c_api/inspireface.h b/cpp-package/inspireface/cpp/inspireface/c_api/inspireface.h index c9dcb34..446d485 100644 --- a/cpp-package/inspireface/cpp/inspireface/c_api/inspireface.h +++ b/cpp-package/inspireface/cpp/inspireface/c_api/inspireface.h @@ -242,7 +242,7 @@ HYPER_CAPI_EXPORT extern HResult HFSessionSetTrackPreviewSize(HFSession session, * this number will be filtered. * * @param session Handle to the session. - * @param minSize The minimum pixel value, default value is 24. + * @param minSize The minimum pixel value, default value is 0. * @return HResult indicating the success or failure of the operation. */ HYPER_CAPI_EXPORT extern HResult HFSessionSetFilterMinimumFacePixelSize(HFSession session, diff --git a/cpp-package/inspireface/cpp/inspireface/track_module/face_track.h b/cpp-package/inspireface/cpp/inspireface/track_module/face_track.h index 730d991..078a3b0 100644 --- a/cpp-package/inspireface/cpp/inspireface/track_module/face_track.h +++ b/cpp-package/inspireface/cpp/inspireface/track_module/face_track.h @@ -176,7 +176,7 @@ private: double det_use_time_; ///< Time used for detection. double track_total_use_time_; ///< Total time used for tracking. int track_preview_size_; ///< Size of the tracking preview. - int filter_minimum_face_px_size = 24; ///< Minimum face pixel allowed to be retained (take the edge with the smallest Rect). + int filter_minimum_face_px_size = 0; ///< Minimum face pixel allowed to be retained (take the edge with the smallest Rect). private: diff --git a/cpp-package/inspireface/cpp/sample/cpp/sample_face_track.cpp b/cpp-package/inspireface/cpp/sample/cpp/sample_face_track.cpp index 2d498cc..f3c92f2 100644 --- a/cpp-package/inspireface/cpp/sample/cpp/sample_face_track.cpp +++ b/cpp-package/inspireface/cpp/sample/cpp/sample_face_track.cpp @@ -37,9 +37,11 @@ int main(int argc, char* argv[]) { return ret; } - // Enable the functions in the pipeline: mask detection, live detection, and face quality detection + // Enable the functions in the pipeline: mask detection, live detection, and face quality + // detection HOption option = HF_ENABLE_QUALITY | HF_ENABLE_MASK_DETECT | HF_ENABLE_LIVENESS; - // Non-video or frame sequence mode uses IMAGE-MODE, which is always face detection without tracking + // Non-video or frame sequence mode uses IMAGE-MODE, which is always face detection without + // tracking HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT; // Maximum number of faces detected HInt32 maxDetectNum = 20; @@ -47,7 +49,8 @@ int main(int argc, char* argv[]) { HInt32 detectPixelLevel = 160; // Handle of the current face SDK algorithm context HFSession session = {0}; - ret = HFCreateInspireFaceSessionOptional(option, detMode, maxDetectNum, detectPixelLevel, -1, &session); + ret = HFCreateInspireFaceSessionOptional(option, detMode, maxDetectNum, detectPixelLevel, -1, + &session); if (ret != HSUCCEED) { std::cout << "Create FaceContext error: " << ret << std::endl; return ret; @@ -55,7 +58,7 @@ int main(int argc, char* argv[]) { HFSessionSetTrackPreviewSize(session, detectPixelLevel); HFSessionSetFilterMinimumFacePixelSize(session, 32); - + // Load a image cv::Mat image = cv::imread(sourcePath); if (image.empty()) { @@ -64,9 +67,9 @@ int main(int argc, char* argv[]) { } // Prepare an image parameter structure for configuration HFImageData imageParam = {0}; - imageParam.data = image.data; // Data buffer - imageParam.width = image.cols; // Target view width - imageParam.height = image.rows; // Target view width + imageParam.data = image.data; // Data buffer + imageParam.width = image.cols; // Target view width + imageParam.height = image.rows; // Target view width // Set rotation based on input parameter switch (rotation) { @@ -113,22 +116,25 @@ int main(int argc, char* argv[]) { std::cout << "Token size: " << multipleFaceData.tokens[index].size << std::endl; std::cout << "Process face index: " << index << std::endl; // Use OpenCV's Rect to receive face bounding boxes - auto rect = cv::Rect(multipleFaceData.rects[index].x, multipleFaceData.rects[index].y, - multipleFaceData.rects[index].width, multipleFaceData.rects[index].height); + auto rect = + cv::Rect(multipleFaceData.rects[index].x, multipleFaceData.rects[index].y, + multipleFaceData.rects[index].width, multipleFaceData.rects[index].height); cv::rectangle(draw, rect, cv::Scalar(0, 100, 255), 4); // Print FaceID, In IMAGE-MODE it is changing, in VIDEO-MODE it is fixed, but it may be lost std::cout << "FaceID: " << multipleFaceData.trackIds[index] << std::endl; - // Print Head euler angle, It can often be used to judge the quality of a face by the Angle of the head + // Print Head euler angle, It can often be used to judge the quality of a face by the Angle + // of the head std::cout << "Roll: " << multipleFaceData.angles.roll[index] - << ", Yaw: " << multipleFaceData.angles.roll[index] + << ", Yaw: " << multipleFaceData.angles.yaw[index] << ", Pitch: " << multipleFaceData.angles.pitch[index] << std::endl; HInt32 numOfLmk; HFGetNumOfFaceDenseLandmark(&numOfLmk); HPoint2f denseLandmarkPoints[numOfLmk]; - ret = HFGetFaceDenseLandmarkFromFaceToken(multipleFaceData.tokens[index], denseLandmarkPoints, numOfLmk); + ret = HFGetFaceDenseLandmarkFromFaceToken(multipleFaceData.tokens[index], + denseLandmarkPoints, numOfLmk); if (ret != HSUCCEED) { std::cerr << "HFGetFaceDenseLandmarkFromFaceToken error!!" << std::endl; return -1; @@ -137,14 +143,19 @@ int main(int argc, char* argv[]) { cv::Point2f p(denseLandmarkPoints[i].x, denseLandmarkPoints[i].y); cv::circle(draw, p, 0, (0, 0, 255), 2); } + auto& rt = multipleFaceData.rects[index]; + float area = ((float)(rt.height * rt.width)) / (imageParam.width * imageParam.height); + std::cout << "area: " << area << std::endl; } cv::imwrite("draw_detected.jpg", draw); // Run pipeline function - // Select the pipeline function that you want to execute, provided that it is already enabled when FaceContext is created! + // Select the pipeline function that you want to execute, provided that it is already enabled + // when FaceContext is created! auto pipelineOption = HF_ENABLE_QUALITY | HF_ENABLE_MASK_DETECT | HF_ENABLE_LIVENESS; // In this loop, all faces are processed - ret = HFMultipleFacePipelineProcessOptional(session, imageHandle, &multipleFaceData, pipelineOption); + ret = HFMultipleFacePipelineProcessOptional(session, imageHandle, &multipleFaceData, + pipelineOption); if (ret != HSUCCEED) { std::cout << "Execute Pipeline error: " << ret << std::endl; return ret; @@ -171,14 +182,13 @@ int main(int argc, char* argv[]) { std::cout << "Process face index from pipeline: " << index << std::endl; std::cout << "Mask detect result: " << maskConfidence.confidence[index] << std::endl; std::cout << "Quality predict result: " << qualityConfidence.confidence[index] << std::endl; - // We set the threshold of wearing a mask as 0.85. If it exceeds the threshold, it will be judged as wearing a mask. - // The threshold can be adjusted according to the scene + // We set the threshold of wearing a mask as 0.85. If it exceeds the threshold, it will be + // judged as wearing a mask. The threshold can be adjusted according to the scene if (maskConfidence.confidence[index] > 0.85) { std::cout << "Mask" << std::endl; } else { std::cout << "Non Mask" << std::endl; } - } ret = HFReleaseImageStream(imageHandle); diff --git a/cpp-package/inspireface/cpp/test/unit/api/test_feature_hub.cpp b/cpp-package/inspireface/cpp/test/unit/api/test_feature_hub.cpp index 529381b..8220a8a 100644 --- a/cpp-package/inspireface/cpp/test/unit/api/test_feature_hub.cpp +++ b/cpp-package/inspireface/cpp/test/unit/api/test_feature_hub.cpp @@ -32,7 +32,7 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") { ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; + delete[] dbPathStr; } SECTION("FeatureHub search top-k") { @@ -115,13 +115,14 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") { REQUIRE(coverIds.size() == results.size); for (int i = 0; i < results.size; ++i) { - REQUIRE(std::find(coverIds.begin(), coverIds.end(), results.customIds[i]) != coverIds.end()); + REQUIRE(std::find(coverIds.begin(), coverIds.end(), results.customIds[i]) != + coverIds.end()); } ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; + delete[] dbPathStr; } SECTION("Repeat the enable and disable tests") { @@ -135,7 +136,6 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") { configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE; configuration.searchThreshold = 0.48f; - ret = HFFeatureHubDataEnable(configuration); REQUIRE(ret == HSUCCEED); @@ -148,7 +148,7 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") { ret = HFFeatureHubDataDisable(); REQUIRE(ret == HERR_FT_HUB_DISABLE_REPETITION); - delete []dbPathStr; + delete[] dbPathStr; } SECTION("Only memory storage is used") { @@ -162,9 +162,7 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") { ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - } - } TEST_CASE("test_ConcurrencyInsertion", "[FeatureHub][Concurrency]") { @@ -212,7 +210,8 @@ TEST_CASE("test_ConcurrencyInsertion", "[FeatureHub][Concurrency]") { feature.data = feat.data(); HFFaceFeatureIdentity featureIdentity = {0}; featureIdentity.feature = &feature; - featureIdentity.customId = beginGenId + j + i * insertsPerThread; // 确保 customId 唯一 + featureIdentity.customId = + beginGenId + j + i * insertsPerThread; // 确保 customId 唯一 featureIdentity.tag = nameBuffer.data(); auto ret = HFFeatureHubInsertFeature(featureIdentity); REQUIRE(ret == HSUCCEED); @@ -227,15 +226,16 @@ TEST_CASE("test_ConcurrencyInsertion", "[FeatureHub][Concurrency]") { HInt32 count; ret = HFFeatureHubGetFaceCount(&count); REQUIRE(ret == HSUCCEED); - REQUIRE(count == baseNum + numThreads * insertsPerThread); // Ensure that the previous base data is added to the newly inserted data + REQUIRE(count == + baseNum + numThreads * insertsPerThread); // Ensure that the previous base data is + // added to the newly inserted data ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; + delete[] dbPathStr; } - TEST_CASE("test_ConcurrencyRemove", "[FeatureHub][Concurrency]") { DRAW_SPLIT_LINE TEST_PRINT_OUTPUT(true); @@ -311,8 +311,7 @@ TEST_CASE("test_ConcurrencyRemove", "[FeatureHub][Concurrency]") { ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; - + delete[] dbPathStr; } TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") { @@ -375,7 +374,8 @@ TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") { HFFaceFeatureIdentity identity = {0}; ret = HFFeatureHubGetFaceIdentity(index, &identity); REQUIRE(ret == HSUCCEED); - std::vector feature(identity.feature->data, identity.feature->data + identity.feature->size); + std::vector feature(identity.feature->data, + identity.feature->data + identity.feature->size); auto simFeat = SimulateSimilarVector(feature); HFFaceFeature simFeature = {0}; simFeature.data = simFeat.data(); @@ -388,7 +388,6 @@ TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") { REQUIRE(ret == HSUCCEED); REQUIRE(cosine > 0.80f); similarFeatures.push_back(feature); - } REQUIRE(similarFeatures.size() == numberOfSimilar); @@ -419,7 +418,7 @@ TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") { std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(0, preDataSample - 1); - for (int j = 0; j < 50; ++j) { // Each thread performs 50 similar searches + for (int j = 0; j < 50; ++j) { // Each thread performs 50 similar searches int idx = dis(gen); auto targetId = targetIds[idx]; HFFaceFeature feature = {0}; @@ -449,11 +448,9 @@ TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") { ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - - delete []dbPathStr; + delete[] dbPathStr; } - TEST_CASE("test_FeatureCache", "[FeatureHub][Concurrency]") { DRAW_SPLIT_LINE TEST_PRINT_OUTPUT(true); @@ -492,7 +489,6 @@ TEST_CASE("test_FeatureCache", "[FeatureHub][Concurrency]") { simFeature.data = simVec.data(); simFeature.size = simVec.size(); - for (int i = 0; i < 10; ++i) { HFFaceFeatureIdentity capture = {0}; ret = HFFeatureHubGetFaceIdentity(12, &capture); @@ -506,12 +502,116 @@ TEST_CASE("test_FeatureCache", "[FeatureHub][Concurrency]") { ret = HFFaceComparison(target, simFeature, &cosine); REQUIRE(cosine > 0.8f); REQUIRE(ret == HSUCCEED); - } ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; + delete[] dbPathStr; +} -} \ No newline at end of file +TEST_CASE("test_DataPersistence", "[feature_manage]") { + DRAW_SPLIT_LINE + TEST_PRINT_OUTPUT(true); + + // Generate 10 random feature + std::vector> features; + std::vector identities; + for (int i = 0; i < 10; ++i) { + auto feat = GenerateRandomFeature(512); + features.push_back(feat); + identities.push_back("id_" + std::to_string(i)); + } + + SECTION("Insert") { + HResult ret; + HFFeatureHubConfiguration configuration = {0}; + auto dbPath = GET_SAVE_DATA(".test"); + HString dbPathStr = new char[dbPath.size() + 1]; + std::strcpy(dbPathStr, dbPath.c_str()); + configuration.enablePersistence = 1; + configuration.dbPath = dbPathStr; + configuration.featureBlockNum = 20; + configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE; + configuration.searchThreshold = 0.48f; + + if (std::remove(configuration.dbPath) != 0) { + spdlog::trace("Maybe the file does not exist"); + } + + ret = HFFeatureHubDataEnable(configuration); + REQUIRE(ret == HSUCCEED); + + for (size_t i = 0; i < features.size(); i++) { + HFFaceFeature feature = {0}; + feature.data = features[i].data(); + feature.size = features[i].size(); + HFFaceFeatureIdentity identity = {0}; + identity.feature = &feature; + identity.tag = const_cast(identities[i].c_str()); + identity.customId = i; + + ret = HFFeatureHubInsertFeature(identity); + REQUIRE(ret == HSUCCEED); + + // Get the feature from the database + HFFaceFeatureIdentity capture = {0}; + ret = HFFeatureHubGetFaceIdentity(i, &capture); + REQUIRE(ret == HSUCCEED); + + // Check the feature + HFFaceFeature target = {0}; + target.data = capture.feature->data; + target.size = capture.feature->size; + HFloat cosine; + ret = HFFaceComparison(target, feature, &cosine); + REQUIRE(ret == HSUCCEED); + REQUIRE(cosine > 0.99f); + } + // Check number of faces + HInt32 count; + ret = HFFeatureHubGetFaceCount(&count); + REQUIRE(ret == HSUCCEED); + REQUIRE(count == features.size()); + + ret = HFFeatureHubDataDisable(); + REQUIRE(ret == HSUCCEED); + + delete[] dbPathStr; + } + + SECTION("Check") { + HResult ret; + HFFeatureHubConfiguration configuration = {0}; + auto dbPath = GET_SAVE_DATA(".test"); + HString dbPathStr = new char[dbPath.size() + 1]; + std::strcpy(dbPathStr, dbPath.c_str()); + configuration.enablePersistence = 1; + configuration.dbPath = dbPathStr; + configuration.featureBlockNum = 20; + + ret = HFFeatureHubDataEnable(configuration); + REQUIRE(ret == HSUCCEED); + + // Check number of faces + HInt32 count; + ret = HFFeatureHubGetFaceCount(&count); + REQUIRE(ret == HSUCCEED); + REQUIRE(count == features.size()); + + // Check every face vector + for (size_t i = 0; i < features.size(); i++) { + HFFaceFeatureIdentity identity = {0}; + ret = HFFeatureHubGetFaceIdentity(i, &identity); + REQUIRE(ret == HSUCCEED); + REQUIRE(identity.customId == i); + REQUIRE(std::string(identity.tag) == identities[i]); + REQUIRE(identity.feature->size == features[i].size()); + } + + ret = HFFeatureHubDataDisable(); + REQUIRE(ret == HSUCCEED); + + delete[] dbPathStr; + } +} diff --git a/cpp-package/inspireface/cpp/test/unit/api/test_feature_manage.cpp b/cpp-package/inspireface/cpp/test/unit/api/test_feature_manage.cpp index 7ce7c21..9fd745a 100644 --- a/cpp-package/inspireface/cpp/test/unit/api/test_feature_manage.cpp +++ b/cpp-package/inspireface/cpp/test/unit/api/test_feature_manage.cpp @@ -102,18 +102,16 @@ TEST_CASE("test_FeatureManage", "[feature_manage]") { REQUIRE(ret == HSUCCEED); CHECK(num == 0); - // Finish ret = HFReleaseInspireFaceSession(session); REQUIRE(ret == HSUCCEED); - ret = HFReleaseImageStream(imgHandle); REQUIRE(ret == HSUCCEED); ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete[]dbPathStr; + delete[] dbPathStr; } SECTION("Import a large faces data") { @@ -151,12 +149,11 @@ TEST_CASE("test_FeatureManage", "[feature_manage]") { REQUIRE(ret == HSUCCEED); CHECK(count == numOfNeedImport); - // Finish ret = HFReleaseInspireFaceSession(session); REQUIRE(ret == HSUCCEED); - delete[]dbPathStr; + delete[] dbPathStr; #else TEST_PRINT("The test case that uses LFW is not enabled, so it will be skipped."); @@ -165,7 +162,8 @@ TEST_CASE("test_FeatureManage", "[feature_manage]") { SECTION("Faces feature CURD") { #ifdef ISF_ENABLE_USE_LFW_DATA - // This section needs to be connected to the "Import a large faces data" section before it can be executed + // This section needs to be connected to the "Import a large faces data" section before it + // can be executed HResult ret; HFSessionCustomParameter parameter = {0}; parameter.enable_recognition = 1; @@ -213,7 +211,7 @@ TEST_CASE("test_FeatureManage", "[feature_manage]") { REQUIRE(ret == HSUCCEED); // Search again ret = HFFeatureHubFaceSearch(feature, &confidence, &searchedIdentity); -// spdlog::info("{}", confidence); + // spdlog::info("{}", confidence); REQUIRE(ret == HSUCCEED); CHECK(searchedIdentity.customId == -1); @@ -225,7 +223,6 @@ TEST_CASE("test_FeatureManage", "[feature_manage]") { ret = HFFeatureHubInsertFeature(againIdentity); REQUIRE(ret == HSUCCEED); - // Search again HFFaceFeatureIdentity searchedAgainIdentity = {0}; ret = HFFeatureHubFaceSearch(feature, &confidence, &searchedAgainIdentity); @@ -267,7 +264,7 @@ TEST_CASE("test_FeatureManage", "[feature_manage]") { ret = HFFeatureHubFaceUpdate(updateIdentity); REQUIRE(ret == HSUCCEED); -// + // // Prepare a zy query image cv::Mat zyImageQuery = cv::imread(GET_DATA("data/bulk/woman_search.jpeg")); HFImageData imageDataZyQuery = {0}; @@ -279,16 +276,17 @@ TEST_CASE("test_FeatureManage", "[feature_manage]") { HFImageStream imgHandleZyQuery; ret = HFCreateImageStream(&imageDataZyQuery, &imgHandleZyQuery); REQUIRE(ret == HSUCCEED); -// + // // Extract basic face information from photos HFMultipleFaceData multipleFaceDataZyQuery = {0}; ret = HFExecuteFaceTrack(session, imgHandleZyQuery, &multipleFaceDataZyQuery); REQUIRE(ret == HSUCCEED); REQUIRE(multipleFaceDataZyQuery.detectedNum > 0); -// + // // Extract face feature HFFaceFeature featureZyQuery = {0}; - ret = HFFaceFeatureExtract(session, imgHandleZyQuery, multipleFaceDataZyQuery.tokens[0], &featureZyQuery); + ret = HFFaceFeatureExtract(session, imgHandleZyQuery, multipleFaceDataZyQuery.tokens[0], + &featureZyQuery); REQUIRE(ret == HSUCCEED); ret = HFReleaseImageStream(imgHandleZyQuery); @@ -311,7 +309,6 @@ TEST_CASE("test_FeatureManage", "[feature_manage]") { TEST_PRINT("The test case that uses LFW is not enabled, so it will be skipped."); #endif } - } TEST_CASE("test_SearchTopK", "[feature_search_top_k]") { @@ -356,16 +353,22 @@ TEST_CASE("test_SearchTopK", "[feature_search_top_k]") { // Prepare multiple photos of a person std::vector photos = { - GET_DATA("data/RD/d1.jpeg"), - GET_DATA("data/RD/d2.jpeg"), - GET_DATA("data/RD/d3.jpeg"), - GET_DATA("data/RD/d4.jpeg"), + GET_DATA("data/RD/d1.jpeg"), + GET_DATA("data/RD/d2.jpeg"), + GET_DATA("data/RD/d3.jpeg"), + GET_DATA("data/RD/d4.jpeg"), }; std::vector tags = { - "d1", "d2", "d3", "d4", + "d1", + "d2", + "d3", + "d4", }; std::vector updateIds = { - 5, 163, 670, 971, + 5, + 163, + 670, + 971, }; REQUIRE(photos.size() == tags.size()); REQUIRE(updateIds.size() == tags.size()); @@ -395,8 +398,8 @@ TEST_CASE("test_SearchTopK", "[feature_search_top_k]") { ret = HFFaceFeatureExtract(session, imgHandle, multipleFaceData.tokens[0], &feature); REQUIRE(ret == HSUCCEED); - char* cstr = new char[tags[i].size() + 1]; // Dynamically allocate memory for the name - strcpy(cstr, tags[i].c_str()); // Copy the name into the allocated memory + char* cstr = new char[tags[i].size() + 1]; // Dynamically allocate memory for the name + strcpy(cstr, tags[i].c_str()); // Copy the name into the allocated memory // Create identity HFFaceFeatureIdentity identity = {0}; @@ -410,7 +413,7 @@ TEST_CASE("test_SearchTopK", "[feature_search_top_k]") { ret = HFReleaseImageStream(imgHandle); REQUIRE(ret == HSUCCEED); - delete[] cstr; // Clean up the dynamically allocated memory + delete[] cstr; // Clean up the dynamically allocated memory } // Prepare a target photo for a face top-k search @@ -443,7 +446,8 @@ TEST_CASE("test_SearchTopK", "[feature_search_top_k]") { CHECK(topk.size == photos.size()); for (int i = 0; i < topk.size; ++i) { TEST_PRINT("Top-{} -> id: {}, {}", i + 1, topk.customIds[i], topk.confidence[i]); - CHECK(std::find(updateIds.begin(), updateIds.end(), topk.customIds[i]) != updateIds.end()); + CHECK(std::find(updateIds.begin(), updateIds.end(), topk.customIds[i]) != + updateIds.end()); } ret = HFReleaseImageStream(imgHandle); @@ -455,13 +459,12 @@ TEST_CASE("test_SearchTopK", "[feature_search_top_k]") { ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete[]dbPathStr; + delete[] dbPathStr; } #endif } TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { - // Test the search time at 1k, 5k and 10k of the face library (the target face is at the back). SECTION("Search face benchmark from 1k") { #if defined(ISF_ENABLE_BENCHMARK) && defined(ISF_ENABLE_USE_LFW_DATA) @@ -492,7 +495,7 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { auto lfwDir = getLFWFunneledDir(); auto dataList = LoadLFWFunneledValidData(lfwDir, getTestLFWFunneledTxt()); -// TEST_PRINT("{}", dataList.size()); + // TEST_PRINT("{}", dataList.size()); auto importStatus = ImportLFWFunneledValidData(session, dataList, numOfNeedImport); REQUIRE(importStatus); HInt32 count; @@ -526,17 +529,20 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { // Search for a face HFloat confidence; HFFaceFeatureIdentity searchedIdentity = {0}; - auto start = (double) cv::getTickCount(); + auto start = (double)cv::getTickCount(); for (int i = 0; i < loop; ++i) { ret = HFFeatureHubFaceSearch(feature, &confidence, &searchedIdentity); } - auto cost = ((double) cv::getTickCount() - start) / cv::getTickFrequency() * 1000; + auto cost = ((double)cv::getTickCount() - start) / cv::getTickFrequency() * 1000; REQUIRE(ret == HSUCCEED); REQUIRE(searchedIdentity.customId == 999); REQUIRE(std::string(searchedIdentity.tag) == "Teresa_Williams"); - TEST_PRINT(" Search Face from 1k -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop); + TEST_PRINT( + " Search Face from 1k -> Loop: {}, Total Time: {:.5f}ms, Average Time: " + "{:.5f}ms", + loop, cost, cost / loop); BenchmarkRecord record(getBenchmarkRecordFile()); record.insertBenchmarkData("Search Face from 1k", loop, cost, cost / loop); @@ -544,15 +550,15 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { ret = HFReleaseInspireFaceSession(session); REQUIRE(ret == HSUCCEED); - ret = HFReleaseImageStream(imgHandle); REQUIRE(ret == HSUCCEED); ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; + delete[] dbPathStr; #else - TEST_PRINT("Skip face search benchmark test, you need to enable both lfw and benchmark test."); + TEST_PRINT( + "Skip face search benchmark test, you need to enable both lfw and benchmark test."); #endif } @@ -620,17 +626,20 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { // Search for a face HFloat confidence; HFFaceFeatureIdentity searchedIdentity = {0}; - auto start = (double) cv::getTickCount(); + auto start = (double)cv::getTickCount(); for (int i = 0; i < loop; ++i) { ret = HFFeatureHubFaceSearch(feature, &confidence, &searchedIdentity); } - auto cost = ((double) cv::getTickCount() - start) / cv::getTickFrequency() * 1000; + auto cost = ((double)cv::getTickCount() - start) / cv::getTickFrequency() * 1000; REQUIRE(ret == HSUCCEED); REQUIRE(searchedIdentity.customId == 4998); REQUIRE(std::string(searchedIdentity.tag) == "Mary_Katherine_Smart"); - TEST_PRINT(" Search Face from 5k -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop); + TEST_PRINT( + " Search Face from 5k -> Loop: {}, Total Time: {:.5f}ms, Average Time: " + "{:.5f}ms", + loop, cost, cost / loop); BenchmarkRecord record(getBenchmarkRecordFile()); record.insertBenchmarkData("Search Face from 5k", loop, cost, cost / loop); @@ -643,9 +652,10 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; + delete[] dbPathStr; #else - TEST_PRINT("Skip face search benchmark test, you need to enable both lfw and benchmark test."); + TEST_PRINT( + "Skip face search benchmark test, you need to enable both lfw and benchmark test."); #endif } @@ -680,7 +690,7 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { auto lfwDir = getLFWFunneledDir(); auto dataList = LoadLFWFunneledValidData(lfwDir, getTestLFWFunneledTxt()); -// TEST_PRINT("{}", dataList.size()); + // TEST_PRINT("{}", dataList.size()); auto importStatus = ImportLFWFunneledValidData(session, dataList, numOfNeedImport); REQUIRE(importStatus); HInt32 count; @@ -748,17 +758,20 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { // Search for a face HFloat confidence; HFFaceFeatureIdentity searchedIdentity = {0}; - auto start = (double) cv::getTickCount(); + auto start = (double)cv::getTickCount(); for (int i = 0; i < loop; ++i) { ret = HFFeatureHubFaceSearch(feature, &confidence, &searchedIdentity); } - auto cost = ((double) cv::getTickCount() - start) / cv::getTickFrequency() * 1000; + auto cost = ((double)cv::getTickCount() - start) / cv::getTickFrequency() * 1000; REQUIRE(ret == HSUCCEED); REQUIRE(searchedIdentity.customId == updateId); REQUIRE(std::string(searchedIdentity.tag) == "ZY"); - TEST_PRINT(" Search Face from 10k -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop); + TEST_PRINT( + " Search Face from 10k -> Loop: {}, Total Time: {:.5f}ms, Average Time: " + "{:.5f}ms", + loop, cost, cost / loop); BenchmarkRecord record(getBenchmarkRecordFile()); record.insertBenchmarkData("Search Face from 10k", loop, cost, cost / loop); @@ -767,15 +780,15 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { ret = HFReleaseInspireFaceSession(session); REQUIRE(ret == HSUCCEED); - ret = HFReleaseImageStream(imgHandle); REQUIRE(ret == HSUCCEED); ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; + delete[] dbPathStr; #else - TEST_PRINT("Skip face search benchmark test, you need to enable both lfw and benchmark test."); + TEST_PRINT( + "Skip face search benchmark test, you need to enable both lfw and benchmark test."); #endif } @@ -789,7 +802,7 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { parameter.enable_recognition = 1; HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT; HFSession session; - ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session); + ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session); REQUIRE(ret == HSUCCEED); HFFeatureHubConfiguration configuration = {0}; auto dbPath = GET_SAVE_DATA(".test"); @@ -829,7 +842,8 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { // Extract face feature HFloat featureCacheZy[featureNum]; - ret = HFFaceFeatureExtractCpy(session, imgHandleZy, multipleFaceDataZy.tokens[0], featureCacheZy); + ret = HFFaceFeatureExtractCpy(session, imgHandleZy, multipleFaceDataZy.tokens[0], + featureCacheZy); HFFaceFeature featureZy = {0}; featureZy.size = featureNum; featureZy.data = featureCacheZy; @@ -845,29 +859,32 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { HFImageStream imgHandleZyQuery; ret = HFCreateImageStream(&imageDataZyQuery, &imgHandleZyQuery); REQUIRE(ret == HSUCCEED); -// + // // Extract basic face information from photos HFMultipleFaceData multipleFaceDataZyQuery = {0}; ret = HFExecuteFaceTrack(session, imgHandleZyQuery, &multipleFaceDataZyQuery); REQUIRE(ret == HSUCCEED); REQUIRE(multipleFaceDataZyQuery.detectedNum > 0); -// + // // Extract face feature HFloat featureCacheZyQuery[featureNum]; - ret = HFFaceFeatureExtractCpy(session, imgHandleZyQuery, multipleFaceDataZyQuery.tokens[0], featureCacheZyQuery); + ret = HFFaceFeatureExtractCpy(session, imgHandleZyQuery, multipleFaceDataZyQuery.tokens[0], + featureCacheZyQuery); HFFaceFeature featureZyQuery = {0}; featureZyQuery.data = featureCacheZyQuery; featureZyQuery.size = featureNum; REQUIRE(ret == HSUCCEED); - auto start = (double) cv::getTickCount(); + auto start = (double)cv::getTickCount(); for (int i = 0; i < loop; ++i) { HFloat compRes; ret = HFFaceComparison(featureZy, featureZyQuery, &compRes); } - auto cost = ((double) cv::getTickCount() - start) / cv::getTickFrequency() * 1000; + auto cost = ((double)cv::getTickCount() - start) / cv::getTickFrequency() * 1000; REQUIRE(ret == HSUCCEED); - TEST_PRINT(" Face Comparison -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop); + TEST_PRINT( + " Face Comparison -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", + loop, cost, cost / loop); BenchmarkRecord record(getBenchmarkRecordFile()); record.insertBenchmarkData("Face Comparison", loop, cost, cost / loop); @@ -880,7 +897,7 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { REQUIRE(ret == HSUCCEED); ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; + delete[] dbPathStr; #else TEST_PRINT("The benchmark is not enabled, so all relevant test cases are skipped."); #endif @@ -896,7 +913,7 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { parameter.enable_recognition = 1; HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT; HFSession session; - ret = HFCreateInspireFaceSession(parameter, detMode, 3,-1, -1, &session); + ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session); REQUIRE(ret == HSUCCEED); HFFeatureHubConfiguration configuration = {0}; auto dbPath = GET_SAVE_DATA(".test"); @@ -934,13 +951,15 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { // Extract face feature HFFaceFeature feature = {0}; - auto start = (double) cv::getTickCount(); + auto start = (double)cv::getTickCount(); for (int i = 0; i < loop; ++i) { ret = HFFaceFeatureExtract(session, imgHandle, multipleFaceData.tokens[0], &feature); } - auto cost = ((double) cv::getTickCount() - start) / cv::getTickFrequency() * 1000; + auto cost = ((double)cv::getTickCount() - start) / cv::getTickFrequency() * 1000; REQUIRE(ret == HSUCCEED); - TEST_PRINT(" Face Extract -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop); + TEST_PRINT( + " Face Extract -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", + loop, cost, cost / loop); BenchmarkRecord record(getBenchmarkRecordFile()); record.insertBenchmarkData("Face Extract", loop, cost, cost / loop); @@ -951,9 +970,11 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") { REQUIRE(ret == HSUCCEED); ret = HFFeatureHubDataDisable(); REQUIRE(ret == HSUCCEED); - delete []dbPathStr; + delete[] dbPathStr; #else - TEST_PRINT("Skip the face feature extraction benchmark test. To run it, you need to turn on the benchmark test."); + TEST_PRINT( + "Skip the face feature extraction benchmark test. To run it, you need to turn on the " + "benchmark test."); #endif } -} \ No newline at end of file +}