mirror of
https://github.com/deepinsight/insightface.git
synced 2025-12-30 16:12:27 +00:00
981 lines
38 KiB
C++
981 lines
38 KiB
C++
//
|
|
// Created by tunm on 2023/10/11.
|
|
//
|
|
|
|
#include <iostream>
|
|
#include "settings/test_settings.h"
|
|
#include "inspireface/c_api/inspireface.h"
|
|
#include "opencv2/opencv.hpp"
|
|
#include "unit/test_helper/simple_csv_writer.h"
|
|
#include "unit/test_helper/test_help.h"
|
|
|
|
TEST_CASE("test_FeatureManage", "[feature_manage]") {
|
|
DRAW_SPLIT_LINE
|
|
TEST_PRINT_OUTPUT(true);
|
|
|
|
SECTION("Face feature management basic functions") {
|
|
HResult ret;
|
|
HFSessionCustomParameter parameter = {0};
|
|
parameter.enable_recognition = 1;
|
|
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
|
|
HFSession session;
|
|
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
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;
|
|
// Delete the previous data before testing
|
|
if (std::remove(configuration.dbPath) != 0) {
|
|
spdlog::trace("Error deleting file");
|
|
}
|
|
ret = HFFeatureHubDataEnable(configuration);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Get a face picture
|
|
cv::Mat kunImage = cv::imread(GET_DATA("data/bulk/kun.jpg"));
|
|
HFImageData imageData = {0};
|
|
imageData.data = kunImage.data;
|
|
imageData.height = kunImage.rows;
|
|
imageData.width = kunImage.cols;
|
|
imageData.format = HF_STREAM_BGR;
|
|
imageData.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandle;
|
|
ret = HFCreateImageStream(&imageData, &imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceData = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceData.detectedNum > 0);
|
|
|
|
// Extract face feature
|
|
HFFaceFeature feature = {0};
|
|
ret = HFFaceFeatureExtract(session, imgHandle, multipleFaceData.tokens[0], &feature);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Insert data into feature management
|
|
HFFaceFeatureIdentity identity = {0};
|
|
identity.feature = &feature;
|
|
identity.tag = "chicken";
|
|
identity.customId = 1234;
|
|
ret = HFFeatureHubInsertFeature(identity);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Check number
|
|
HInt32 num;
|
|
ret = HFFeatureHubGetFaceCount(&num);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(num == 1);
|
|
|
|
// Update Face info
|
|
HFFaceFeatureIdentity updatedIdentity = {0};
|
|
updatedIdentity.feature = identity.feature;
|
|
updatedIdentity.customId = identity.customId;
|
|
updatedIdentity.tag = "iKun";
|
|
ret = HFFeatureHubFaceUpdate(updatedIdentity);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Trying to update an identity that doesn't exist
|
|
HFFaceFeatureIdentity nonIdentity = {0};
|
|
nonIdentity.customId = 234;
|
|
nonIdentity.tag = "no";
|
|
nonIdentity.feature = &feature;
|
|
ret = HFFeatureHubFaceUpdate(nonIdentity);
|
|
REQUIRE(ret != HSUCCEED);
|
|
|
|
// Trying to delete an identity that doesn't exist
|
|
ret = HFFeatureHubFaceRemove(nonIdentity.customId);
|
|
REQUIRE(ret != HSUCCEED);
|
|
|
|
// Delete kunkun
|
|
ret = HFFeatureHubFaceRemove(identity.customId);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFFeatureHubGetFaceCount(&num);
|
|
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;
|
|
}
|
|
|
|
SECTION("Import a large faces data") {
|
|
#ifdef ISF_ENABLE_USE_LFW_DATA
|
|
HResult ret;
|
|
HFSessionCustomParameter parameter = {0};
|
|
parameter.enable_recognition = 1;
|
|
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
|
|
HFSession session;
|
|
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
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;
|
|
// Delete the previous data before testing
|
|
if (std::remove(configuration.dbPath) != 0) {
|
|
spdlog::trace("Error deleting file");
|
|
}
|
|
ret = HFFeatureHubDataEnable(configuration);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
auto lfwDir = getLFWFunneledDir();
|
|
auto dataList = LoadLFWFunneledValidData(lfwDir, getTestLFWFunneledTxt());
|
|
size_t numOfNeedImport = 1000;
|
|
auto importStatus = ImportLFWFunneledValidData(session, dataList, numOfNeedImport);
|
|
REQUIRE(importStatus);
|
|
HInt32 count;
|
|
ret = HFFeatureHubGetFaceCount(&count);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(count == numOfNeedImport);
|
|
|
|
// Finish
|
|
ret = HFReleaseInspireFaceSession(session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
delete[] dbPathStr;
|
|
|
|
#else
|
|
TEST_PRINT("The test case that uses LFW is not enabled, so it will be skipped.");
|
|
#endif
|
|
}
|
|
|
|
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
|
|
HResult ret;
|
|
HFSessionCustomParameter parameter = {0};
|
|
parameter.enable_recognition = 1;
|
|
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
|
|
HFSession session;
|
|
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Face track
|
|
cv::Mat dstImage = cv::imread(GET_DATA("data/bulk/Nathalie_Baye_0002.jpg"));
|
|
HFImageData imageData = {0};
|
|
imageData.data = dstImage.data;
|
|
imageData.height = dstImage.rows;
|
|
imageData.width = dstImage.cols;
|
|
imageData.format = HF_STREAM_BGR;
|
|
imageData.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandle;
|
|
ret = HFCreateImageStream(&imageData, &imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceData = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceData.detectedNum > 0);
|
|
|
|
// Extract face feature
|
|
HFFaceFeature feature = {0};
|
|
ret = HFFaceFeatureExtract(session, imgHandle, multipleFaceData.tokens[0], &feature);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFReleaseImageStream(imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Search for a face
|
|
HFloat confidence;
|
|
HFFaceFeatureIdentity searchedIdentity = {0};
|
|
ret = HFFeatureHubFaceSearch(feature, &confidence, &searchedIdentity);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(searchedIdentity.customId == 898);
|
|
CHECK(std::string(searchedIdentity.tag) == "Nathalie_Baye");
|
|
|
|
// Delete kunkun and search
|
|
ret = HFFeatureHubFaceRemove(searchedIdentity.customId);
|
|
REQUIRE(ret == HSUCCEED);
|
|
// Search again
|
|
ret = HFFeatureHubFaceSearch(feature, &confidence, &searchedIdentity);
|
|
// spdlog::info("{}", confidence);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(searchedIdentity.customId == -1);
|
|
|
|
// Insert again
|
|
HFFaceFeatureIdentity againIdentity = {0};
|
|
againIdentity.customId = 898;
|
|
againIdentity.tag = "Cover";
|
|
againIdentity.feature = &feature;
|
|
ret = HFFeatureHubInsertFeature(againIdentity);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Search again
|
|
HFFaceFeatureIdentity searchedAgainIdentity = {0};
|
|
ret = HFFeatureHubFaceSearch(feature, &confidence, &searchedAgainIdentity);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(searchedAgainIdentity.customId == 898);
|
|
|
|
// Update any feature
|
|
HInt32 updateId = 909;
|
|
cv::Mat zyImage = cv::imread(GET_DATA("data/bulk/woman.png"));
|
|
HFImageData imageDataZy = {0};
|
|
imageDataZy.data = zyImage.data;
|
|
imageDataZy.height = zyImage.rows;
|
|
imageDataZy.width = zyImage.cols;
|
|
imageDataZy.format = HF_STREAM_BGR;
|
|
imageDataZy.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandleZy;
|
|
ret = HFCreateImageStream(&imageDataZy, &imgHandleZy);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceDataZy = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandleZy, &multipleFaceDataZy);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceDataZy.detectedNum > 0);
|
|
|
|
// Extract face feature
|
|
HFFaceFeature featureZy = {0};
|
|
ret = HFFaceFeatureExtract(session, imgHandleZy, multipleFaceDataZy.tokens[0], &featureZy);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFReleaseImageStream(imgHandleZy);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Update id: 11297
|
|
HFFaceFeatureIdentity updateIdentity = {0};
|
|
updateIdentity.customId = updateId;
|
|
updateIdentity.tag = "ZY";
|
|
updateIdentity.feature = &featureZy;
|
|
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};
|
|
imageDataZyQuery.data = zyImageQuery.data;
|
|
imageDataZyQuery.height = zyImageQuery.rows;
|
|
imageDataZyQuery.width = zyImageQuery.cols;
|
|
imageDataZyQuery.format = HF_STREAM_BGR;
|
|
imageDataZyQuery.rotation = HF_CAMERA_ROTATION_0;
|
|
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);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFReleaseImageStream(imgHandleZyQuery);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Search
|
|
HFloat confidenceQuery;
|
|
HFFaceFeatureIdentity searchedIdentityQuery = {0};
|
|
ret = HFFeatureHubFaceSearch(featureZyQuery, &confidenceQuery, &searchedIdentityQuery);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(searchedIdentityQuery.customId == updateId);
|
|
|
|
ret = HFFeatureHubDataDisable();
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFReleaseInspireFaceSession(session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
#else
|
|
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]") {
|
|
#ifdef ISF_ENABLE_USE_LFW_DATA
|
|
DRAW_SPLIT_LINE
|
|
TEST_PRINT_OUTPUT(true);
|
|
|
|
SECTION("Face feature management basic functions") {
|
|
HResult ret;
|
|
HFSessionCustomParameter parameter = {0};
|
|
parameter.enable_recognition = 1;
|
|
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
|
|
HFSession session;
|
|
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
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.46f;
|
|
// Delete the previous data before testing
|
|
if (std::remove(configuration.dbPath) != 0) {
|
|
spdlog::trace("Error deleting file");
|
|
}
|
|
ret = HFFeatureHubDataEnable(configuration);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Import 1k faces
|
|
auto lfwDir = getLFWFunneledDir();
|
|
auto dataList = LoadLFWFunneledValidData(lfwDir, getTestLFWFunneledTxt());
|
|
size_t numOfNeedImport = 1000;
|
|
auto importStatus = ImportLFWFunneledValidData(session, dataList, numOfNeedImport);
|
|
REQUIRE(importStatus);
|
|
HInt32 count;
|
|
ret = HFFeatureHubGetFaceCount(&count);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(count == numOfNeedImport);
|
|
|
|
// Prepare multiple photos of a person
|
|
std::vector<std::string> 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"),
|
|
};
|
|
std::vector<std::string> tags = {
|
|
"d1",
|
|
"d2",
|
|
"d3",
|
|
"d4",
|
|
};
|
|
std::vector<HInt32> updateIds = {
|
|
5,
|
|
163,
|
|
670,
|
|
971,
|
|
};
|
|
REQUIRE(photos.size() == tags.size());
|
|
REQUIRE(updateIds.size() == tags.size());
|
|
|
|
// Replace the face features in the photo with each target in FeatureHub
|
|
for (int i = 0; i < photos.size(); ++i) {
|
|
// Face track
|
|
cv::Mat dstImage = cv::imread(photos[i]);
|
|
HFImageData imageData = {0};
|
|
imageData.data = dstImage.data;
|
|
imageData.height = dstImage.rows;
|
|
imageData.width = dstImage.cols;
|
|
imageData.format = HF_STREAM_BGR;
|
|
imageData.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandle;
|
|
ret = HFCreateImageStream(&imageData, &imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceData = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceData.detectedNum > 0);
|
|
|
|
// Extract face feature
|
|
HFFaceFeature feature = {0};
|
|
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
|
|
|
|
// Create identity
|
|
HFFaceFeatureIdentity identity = {0};
|
|
identity.customId = updateIds[i];
|
|
identity.feature = &feature;
|
|
identity.tag = cstr;
|
|
|
|
// Update
|
|
ret = HFFeatureHubFaceUpdate(identity);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFReleaseImageStream(imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
delete[] cstr; // Clean up the dynamically allocated memory
|
|
}
|
|
|
|
// Prepare a target photo for a face top-k search
|
|
cv::Mat image = cv::imread(GET_DATA("data/RD/d5.jpeg"));
|
|
HFImageData imageData = {0};
|
|
imageData.data = image.data;
|
|
imageData.height = image.rows;
|
|
imageData.width = image.cols;
|
|
imageData.format = HF_STREAM_BGR;
|
|
imageData.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandle;
|
|
ret = HFCreateImageStream(&imageData, &imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
HFMultipleFaceData multipleFaceData = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceData.detectedNum > 0);
|
|
|
|
HFFaceFeature feature = {0};
|
|
ret = HFFaceFeatureExtract(session, imgHandle, multipleFaceData.tokens[0], &feature);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Run the top-k search
|
|
HFSearchTopKResults topk;
|
|
ret = HFFeatureHubFaceSearchTopK(feature, 10, &topk);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Check whether the top-k result is consistent with the expectation
|
|
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());
|
|
}
|
|
|
|
ret = HFReleaseImageStream(imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Finish
|
|
ret = HFReleaseInspireFaceSession(session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFFeatureHubDataDisable();
|
|
REQUIRE(ret == HSUCCEED);
|
|
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)
|
|
size_t loop = 1000;
|
|
size_t numOfNeedImport = 1000;
|
|
HResult ret;
|
|
HFSessionCustomParameter parameter = {0};
|
|
parameter.enable_recognition = 1;
|
|
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
|
|
HFSession session;
|
|
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
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;
|
|
// Delete the previous data before testing
|
|
if (std::remove(configuration.dbPath) != 0) {
|
|
spdlog::trace("Error deleting file");
|
|
}
|
|
ret = HFFeatureHubDataEnable(configuration);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
auto lfwDir = getLFWFunneledDir();
|
|
auto dataList = LoadLFWFunneledValidData(lfwDir, getTestLFWFunneledTxt());
|
|
// TEST_PRINT("{}", dataList.size());
|
|
auto importStatus = ImportLFWFunneledValidData(session, dataList, numOfNeedImport);
|
|
REQUIRE(importStatus);
|
|
HInt32 count;
|
|
ret = HFFeatureHubGetFaceCount(&count);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(count == numOfNeedImport);
|
|
|
|
// Face track
|
|
cv::Mat dstImage = cv::imread(GET_DATA("data/search/Teresa_Williams_0001_1k.jpg"));
|
|
HFImageData imageData = {0};
|
|
imageData.data = dstImage.data;
|
|
imageData.height = dstImage.rows;
|
|
imageData.width = dstImage.cols;
|
|
imageData.format = HF_STREAM_BGR;
|
|
imageData.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandle;
|
|
ret = HFCreateImageStream(&imageData, &imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceData = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceData.detectedNum > 0);
|
|
|
|
// Extract face feature
|
|
HFFaceFeature feature = {0};
|
|
ret = HFFaceFeatureExtract(session, imgHandle, multipleFaceData.tokens[0], &feature);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Search for a face
|
|
HFloat confidence;
|
|
HFFaceFeatureIdentity searchedIdentity = {0};
|
|
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;
|
|
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(searchedIdentity.customId == 999);
|
|
REQUIRE(std::string(searchedIdentity.tag) == "Teresa_Williams");
|
|
|
|
TEST_PRINT(
|
|
"<Benchmark> 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);
|
|
// Finish
|
|
ret = HFReleaseInspireFaceSession(session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFReleaseImageStream(imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFFeatureHubDataDisable();
|
|
REQUIRE(ret == HSUCCEED);
|
|
delete[] dbPathStr;
|
|
#else
|
|
TEST_PRINT(
|
|
"Skip face search benchmark test, you need to enable both lfw and benchmark test.");
|
|
#endif
|
|
}
|
|
|
|
SECTION("Search face benchmark from 5k") {
|
|
#if defined(ISF_ENABLE_BENCHMARK) && defined(ISF_ENABLE_USE_LFW_DATA)
|
|
size_t loop = 1000;
|
|
size_t numOfNeedImport = 5000;
|
|
HResult ret;
|
|
std::string modelPath = GET_MODEL_FILE();
|
|
HPath path = modelPath.c_str();
|
|
HFSessionCustomParameter parameter = {0};
|
|
parameter.enable_recognition = 1;
|
|
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
|
|
HFSession session;
|
|
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
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;
|
|
// Delete the previous data before testing
|
|
if (std::remove(configuration.dbPath) != 0) {
|
|
spdlog::trace("Error deleting file");
|
|
}
|
|
ret = HFFeatureHubDataEnable(configuration);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
auto lfwDir = getLFWFunneledDir();
|
|
auto dataList = LoadLFWFunneledValidData(lfwDir, getTestLFWFunneledTxt());
|
|
auto importStatus = ImportLFWFunneledValidData(session, dataList, numOfNeedImport);
|
|
REQUIRE(importStatus);
|
|
HInt32 count;
|
|
ret = HFFeatureHubGetFaceCount(&count);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(count == numOfNeedImport);
|
|
|
|
// Face track
|
|
cv::Mat dstImage = cv::imread(GET_DATA("data/search/Mary_Katherine_Smart_0001_5k.jpg"));
|
|
HFImageData imageData = {0};
|
|
imageData.data = dstImage.data;
|
|
imageData.height = dstImage.rows;
|
|
imageData.width = dstImage.cols;
|
|
imageData.format = HF_STREAM_BGR;
|
|
imageData.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandle;
|
|
ret = HFCreateImageStream(&imageData, &imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceData = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceData.detectedNum > 0);
|
|
|
|
// Extract face feature
|
|
HFFaceFeature feature = {0};
|
|
ret = HFFaceFeatureExtract(session, imgHandle, multipleFaceData.tokens[0], &feature);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Search for a face
|
|
HFloat confidence;
|
|
HFFaceFeatureIdentity searchedIdentity = {0};
|
|
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;
|
|
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(searchedIdentity.customId == 4998);
|
|
REQUIRE(std::string(searchedIdentity.tag) == "Mary_Katherine_Smart");
|
|
|
|
TEST_PRINT(
|
|
"<Benchmark> 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);
|
|
// Finish
|
|
ret = HFReleaseInspireFaceSession(session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFReleaseImageStream(imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFFeatureHubDataDisable();
|
|
REQUIRE(ret == HSUCCEED);
|
|
delete[] dbPathStr;
|
|
#else
|
|
TEST_PRINT(
|
|
"Skip face search benchmark test, you need to enable both lfw and benchmark test.");
|
|
#endif
|
|
}
|
|
|
|
SECTION("Search face benchmark from 10k") {
|
|
#if defined(ISF_ENABLE_BENCHMARK) && defined(ISF_ENABLE_USE_LFW_DATA)
|
|
size_t loop = 1000;
|
|
size_t numOfNeedImport = 10000;
|
|
HResult ret;
|
|
std::string modelPath = GET_MODEL_FILE();
|
|
HPath path = modelPath.c_str();
|
|
HFSessionCustomParameter parameter = {0};
|
|
parameter.enable_recognition = 1;
|
|
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
|
|
HFSession session;
|
|
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
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;
|
|
// Delete the previous data before testing
|
|
if (std::remove(configuration.dbPath) != 0) {
|
|
spdlog::trace("Error deleting file");
|
|
}
|
|
ret = HFFeatureHubDataEnable(configuration);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
auto lfwDir = getLFWFunneledDir();
|
|
auto dataList = LoadLFWFunneledValidData(lfwDir, getTestLFWFunneledTxt());
|
|
// TEST_PRINT("{}", dataList.size());
|
|
auto importStatus = ImportLFWFunneledValidData(session, dataList, numOfNeedImport);
|
|
REQUIRE(importStatus);
|
|
HInt32 count;
|
|
ret = HFFeatureHubGetFaceCount(&count);
|
|
REQUIRE(ret == HSUCCEED);
|
|
CHECK(count == numOfNeedImport);
|
|
|
|
// Update any feature
|
|
HInt32 updateId = numOfNeedImport - 1;
|
|
cv::Mat zyImage = cv::imread(GET_DATA("data/bulk/woman.png"));
|
|
HFImageData imageDataZy = {0};
|
|
imageDataZy.data = zyImage.data;
|
|
imageDataZy.height = zyImage.rows;
|
|
imageDataZy.width = zyImage.cols;
|
|
imageDataZy.format = HF_STREAM_BGR;
|
|
imageDataZy.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandleZy;
|
|
ret = HFCreateImageStream(&imageDataZy, &imgHandleZy);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceDataZy = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandleZy, &multipleFaceDataZy);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceDataZy.detectedNum > 0);
|
|
|
|
// Extract face feature
|
|
HFFaceFeature featureZy = {0};
|
|
ret = HFFaceFeatureExtract(session, imgHandleZy, multipleFaceDataZy.tokens[0], &featureZy);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Update id: 11297
|
|
HFFaceFeatureIdentity updateIdentity = {0};
|
|
updateIdentity.customId = updateId;
|
|
updateIdentity.tag = "ZY";
|
|
updateIdentity.feature = &featureZy;
|
|
ret = HFFeatureHubFaceUpdate(updateIdentity);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
HFReleaseImageStream(imgHandleZy);
|
|
|
|
// Face track
|
|
cv::Mat dstImage = cv::imread(GET_DATA("data/bulk/woman_search.jpeg"));
|
|
HFImageData imageData = {0};
|
|
imageData.data = dstImage.data;
|
|
imageData.height = dstImage.rows;
|
|
imageData.width = dstImage.cols;
|
|
imageData.format = HF_STREAM_BGR;
|
|
imageData.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandle;
|
|
ret = HFCreateImageStream(&imageData, &imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceData = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceData.detectedNum > 0);
|
|
|
|
// Extract face feature
|
|
HFFaceFeature feature = {0};
|
|
ret = HFFaceFeatureExtract(session, imgHandle, multipleFaceData.tokens[0], &feature);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Search for a face
|
|
HFloat confidence;
|
|
HFFaceFeatureIdentity searchedIdentity = {0};
|
|
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;
|
|
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(searchedIdentity.customId == updateId);
|
|
REQUIRE(std::string(searchedIdentity.tag) == "ZY");
|
|
|
|
TEST_PRINT(
|
|
"<Benchmark> 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);
|
|
|
|
// Finish
|
|
ret = HFReleaseInspireFaceSession(session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFReleaseImageStream(imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
ret = HFFeatureHubDataDisable();
|
|
REQUIRE(ret == HSUCCEED);
|
|
delete[] dbPathStr;
|
|
#else
|
|
TEST_PRINT(
|
|
"Skip face search benchmark test, you need to enable both lfw and benchmark test.");
|
|
#endif
|
|
}
|
|
|
|
SECTION("Face comparison benchmark") {
|
|
#ifdef ISF_ENABLE_BENCHMARK
|
|
int loop = 1000;
|
|
HResult ret;
|
|
std::string modelPath = GET_MODEL_FILE();
|
|
HPath path = modelPath.c_str();
|
|
HFSessionCustomParameter parameter = {0};
|
|
parameter.enable_recognition = 1;
|
|
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
|
|
HFSession session;
|
|
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
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;
|
|
// Delete the previous data before testing
|
|
if (std::remove(configuration.dbPath) != 0) {
|
|
spdlog::trace("Error deleting file");
|
|
}
|
|
ret = HFFeatureHubDataEnable(configuration);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
cv::Mat zyImage = cv::imread(GET_DATA("data/bulk/woman.png"));
|
|
HFImageData imageDataZy = {0};
|
|
imageDataZy.data = zyImage.data;
|
|
imageDataZy.height = zyImage.rows;
|
|
imageDataZy.width = zyImage.cols;
|
|
imageDataZy.format = HF_STREAM_BGR;
|
|
imageDataZy.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandleZy;
|
|
ret = HFCreateImageStream(&imageDataZy, &imgHandleZy);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceDataZy = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandleZy, &multipleFaceDataZy);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceDataZy.detectedNum > 0);
|
|
|
|
HInt32 featureNum;
|
|
HFGetFeatureLength(&featureNum);
|
|
|
|
// Extract face feature
|
|
HFloat featureCacheZy[featureNum];
|
|
ret = HFFaceFeatureExtractCpy(session, imgHandleZy, multipleFaceDataZy.tokens[0],
|
|
featureCacheZy);
|
|
HFFaceFeature featureZy = {0};
|
|
featureZy.size = featureNum;
|
|
featureZy.data = featureCacheZy;
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
cv::Mat zyImageQuery = cv::imread(GET_DATA("data/bulk/woman_search.jpeg"));
|
|
HFImageData imageDataZyQuery = {0};
|
|
imageDataZyQuery.data = zyImageQuery.data;
|
|
imageDataZyQuery.height = zyImageQuery.rows;
|
|
imageDataZyQuery.width = zyImageQuery.cols;
|
|
imageDataZyQuery.format = HF_STREAM_BGR;
|
|
imageDataZyQuery.rotation = HF_CAMERA_ROTATION_0;
|
|
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);
|
|
HFFaceFeature featureZyQuery = {0};
|
|
featureZyQuery.data = featureCacheZyQuery;
|
|
featureZyQuery.size = featureNum;
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
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;
|
|
REQUIRE(ret == HSUCCEED);
|
|
TEST_PRINT(
|
|
"<Benchmark> 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);
|
|
|
|
HFReleaseImageStream(imgHandleZy);
|
|
HFReleaseImageStream(imgHandleZyQuery);
|
|
|
|
// Finish
|
|
ret = HFReleaseInspireFaceSession(session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
ret = HFFeatureHubDataDisable();
|
|
REQUIRE(ret == HSUCCEED);
|
|
delete[] dbPathStr;
|
|
#else
|
|
TEST_PRINT("The benchmark is not enabled, so all relevant test cases are skipped.");
|
|
#endif
|
|
}
|
|
|
|
SECTION("Face feature extract benchmark") {
|
|
#ifdef ISF_ENABLE_BENCHMARK
|
|
int loop = 1000;
|
|
HResult ret;
|
|
std::string modelPath = GET_MODEL_FILE();
|
|
HPath path = modelPath.c_str();
|
|
HFSessionCustomParameter parameter = {0};
|
|
parameter.enable_recognition = 1;
|
|
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
|
|
HFSession session;
|
|
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
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;
|
|
// Delete the previous data before testing
|
|
if (std::remove(configuration.dbPath) != 0) {
|
|
spdlog::trace("Error deleting file");
|
|
}
|
|
ret = HFFeatureHubDataEnable(configuration);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Face track
|
|
cv::Mat dstImage = cv::imread(GET_DATA("data/search/Teresa_Williams_0001_1k.jpg"));
|
|
HFImageData imageData = {0};
|
|
imageData.data = dstImage.data;
|
|
imageData.height = dstImage.rows;
|
|
imageData.width = dstImage.cols;
|
|
imageData.format = HF_STREAM_BGR;
|
|
imageData.rotation = HF_CAMERA_ROTATION_0;
|
|
HFImageStream imgHandle;
|
|
ret = HFCreateImageStream(&imageData, &imgHandle);
|
|
REQUIRE(ret == HSUCCEED);
|
|
|
|
// Extract basic face information from photos
|
|
HFMultipleFaceData multipleFaceData = {0};
|
|
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
|
|
REQUIRE(ret == HSUCCEED);
|
|
REQUIRE(multipleFaceData.detectedNum > 0);
|
|
|
|
// Extract face feature
|
|
HFFaceFeature feature = {0};
|
|
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;
|
|
REQUIRE(ret == HSUCCEED);
|
|
TEST_PRINT(
|
|
"<Benchmark> 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);
|
|
|
|
HFReleaseImageStream(imgHandle);
|
|
// Finish
|
|
ret = HFReleaseInspireFaceSession(session);
|
|
REQUIRE(ret == HSUCCEED);
|
|
ret = HFFeatureHubDataDisable();
|
|
REQUIRE(ret == HSUCCEED);
|
|
delete[] dbPathStr;
|
|
#else
|
|
TEST_PRINT(
|
|
"Skip the face feature extraction benchmark test. To run it, you need to turn on the "
|
|
"benchmark test.");
|
|
#endif
|
|
}
|
|
}
|