Update inspireface to 1.2.0

This commit is contained in:
Jingyu
2025-03-25 00:51:26 +08:00
parent 977ea6795b
commit ca64996b84
388 changed files with 28584 additions and 13036 deletions

View File

@@ -0,0 +1,670 @@
/**
* Created by Jingyu Yan
* @date 2025-01-12
*/
#include <iostream>
#include "settings/test_settings.h"
#include "inspireface/c_api/inspireface.h"
#include "unit/test_helper/simple_csv_writer.h"
#include "unit/test_helper/test_help.h"
#include "unit/test_helper/test_tools.h"
#include "middleware/costman.h"
#ifdef ISF_ENABLE_BENCHMARK
TEST_CASE("test_BenchmarkFaceDetect", "[benchmark]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
const int loop = 1000;
SECTION("Benchmark face detection@160") {
auto pixLevel = 160;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, pixLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
// Get a face picture
HFImageStream imgHandle;
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/kun.jpg"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
inspirecv::TimeSpend timeSpend("Face Detect@160");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
// Extract basic face information from photos
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
SECTION("Benchmark face detection@320") {
auto pixLevel = 320;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, pixLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
// Get a face picture
HFImageStream imgHandle;
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/kun.jpg"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
inspirecv::TimeSpend timeSpend("Face Detect@320");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
// Extract basic face information from photos
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
SECTION("Benchmark face detection@640") {
auto pixLevel = 640;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, pixLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
// Get a face picture
HFImageStream imgHandle;
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/kun.jpg"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
inspirecv::TimeSpend timeSpend("Face Detect@640");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
// Extract basic face information from photos
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
}
TEST_CASE("test_BenchmarkFaceTrack", "[benchmark]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
const int loop = 1000;
auto pixLevel = 160;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_LIGHT_TRACK;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, pixLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
// Get a face picture
HFImageStream imgHandle;
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/kun.jpg"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
inspirecv::TimeSpend timeSpend("Face Track");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
// Extract basic face information from photos
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
TEST_CASE("test_BenchmarkFaceExtractWithAlign", "[benchmark]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
const int loop = 1000;
auto pixLevel = 160;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_LIGHT_TRACK;
HFSession session;
ret = HFCreateInspireFaceSessionOptional(HF_ENABLE_FACE_RECOGNITION, detMode, 3, -1, -1, &session);
REQUIRE(ret == HSUCCEED);
// Face track
auto dstImage = inspirecv::Image::Create(GET_DATA("data/search/Teresa_Williams_0001_1k.jpg"));
// Get a face picture
HFImageStream imgHandle;
ret = CVImageToImageStream(dstImage, imgHandle);
REQUIRE(ret == HSUCCEED);
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
inspirecv::TimeSpend timeSpend("Face Extract With Align");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
// Extract basic face information from photos
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
TEST_CASE("test_BenchmarkFaceComparison", "[benchmark]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
int loop = 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);
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/woman.png"));
HFImageStream imgHandle;
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
// Extract basic face information from photos
HFMultipleFaceData multipleFaceDataZy = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceDataZy);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceDataZy.detectedNum > 0);
HInt32 featureNum;
HFGetFeatureLength(&featureNum);
// Extract face feature
HFloat featureCacheZy[featureNum];
ret = HFFaceFeatureExtractCpy(session, imgHandle, multipleFaceDataZy.tokens[0], featureCacheZy);
HFFaceFeature featureZy = {0};
featureZy.size = featureNum;
featureZy.data = featureCacheZy;
REQUIRE(ret == HSUCCEED);
auto imageQuery = inspirecv::Image::Create(GET_DATA("data/bulk/woman_search.jpeg"));
HFImageStream imgHandleQuery;
ret = CVImageToImageStream(imageQuery, imgHandleQuery);
REQUIRE(ret == HSUCCEED);
HFMultipleFaceData multipleFaceDataQuery = {0};
ret = HFExecuteFaceTrack(session, imgHandleQuery, &multipleFaceDataQuery);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceDataQuery.detectedNum > 0);
// Extract face feature
HFloat featureCacheZyQuery[featureNum];
ret = HFFaceFeatureExtractCpy(session, imgHandleQuery, multipleFaceDataQuery.tokens[0], featureCacheZyQuery);
HFFaceFeature featureZyQuery = {0};
featureZyQuery.data = featureCacheZyQuery;
featureZyQuery.size = featureNum;
REQUIRE(ret == HSUCCEED);
inspirecv::TimeSpend timeSpend("Face Comparison");
for (int i = 0; i < loop; ++i) {
timeSpend.Start();
HFloat compRes;
ret = HFFaceComparison(featureZy, featureZyQuery, &compRes);
REQUIRE(ret == HSUCCEED);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageStream(imgHandleQuery);
REQUIRE(ret == HSUCCEED);
// Finish
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
TEST_CASE("test_BenchmarkFaceHubSearchPersistence", "[benchmark]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
SECTION("Benchmark search 1k@Persistence") {
const int loop = 1000;
HResult ret;
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
REQUIRE(ret == HSUCCEED);
std::vector<std::vector<HFloat>> baseFeatures;
size_t genSizeOfBase = 1000;
HInt32 featureLength;
HFGetFeatureLength(&featureLength);
REQUIRE(featureLength > 0);
for (int i = 0; i < genSizeOfBase; ++i) {
auto feat = GenerateRandomFeature(featureLength);
baseFeatures.push_back(feat);
// Construct face feature
HFFaceFeature feature = {0};
feature.size = feat.size();
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
HInt32 totalFace;
ret = HFFeatureHubGetFaceCount(&totalFace);
REQUIRE(ret == HSUCCEED);
REQUIRE(totalFace == genSizeOfBase);
HInt32 targetId = 800;
auto targetFeature = baseFeatures[targetId - 1];
auto searchFeat = SimulateSimilarVector(targetFeature);
HFFaceFeature searchFeature = {0};
searchFeature.size = searchFeat.size();
searchFeature.data = searchFeat.data();
HFloat confidence = 0.0f;
HFFaceFeatureIdentity mostSimilar = {0};
inspirecv::TimeSpend timeSpend("Face Search 1k@Persistence");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
ret = HFFeatureHubFaceSearch(searchFeature, &confidence, &mostSimilar);
REQUIRE(ret == HSUCCEED);
REQUIRE(mostSimilar.id == targetId);
REQUIRE(confidence > 0.88f);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HSUCCEED);
delete[] dbPathStr;
}
SECTION("Benchmark search 5k@Persistence") {
const int loop = 1000;
HResult ret;
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
REQUIRE(ret == HSUCCEED);
std::vector<std::vector<HFloat>> baseFeatures;
size_t genSizeOfBase = 5000;
HInt32 featureLength;
HFGetFeatureLength(&featureLength);
REQUIRE(featureLength > 0);
for (int i = 0; i < genSizeOfBase; ++i) {
auto feat = GenerateRandomFeature(featureLength);
baseFeatures.push_back(feat);
// Construct face feature
HFFaceFeature feature = {0};
feature.size = feat.size();
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
HInt32 totalFace;
ret = HFFeatureHubGetFaceCount(&totalFace);
REQUIRE(ret == HSUCCEED);
REQUIRE(totalFace == genSizeOfBase);
HInt32 targetId = 4800;
auto targetFeature = baseFeatures[targetId - 1];
auto searchFeat = SimulateSimilarVector(targetFeature);
HFFaceFeature searchFeature = {0};
searchFeature.size = searchFeat.size();
searchFeature.data = searchFeat.data();
HFloat confidence = 0.0f;
HFFaceFeatureIdentity mostSimilar = {0};
inspirecv::TimeSpend timeSpend("Face Search 5k@Persistence");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
ret = HFFeatureHubFaceSearch(searchFeature, &confidence, &mostSimilar);
REQUIRE(ret == HSUCCEED);
REQUIRE(mostSimilar.id == targetId);
REQUIRE(confidence > 0.88f);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HSUCCEED);
delete[] dbPathStr;
}
SECTION("Benchmark search 10k@Persistence") {
const int loop = 1000;
HResult ret;
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
REQUIRE(ret == HSUCCEED);
std::vector<std::vector<HFloat>> baseFeatures;
size_t genSizeOfBase = 10000;
HInt32 featureLength;
HFGetFeatureLength(&featureLength);
REQUIRE(featureLength > 0);
for (int i = 0; i < genSizeOfBase; ++i) {
auto feat = GenerateRandomFeature(featureLength);
baseFeatures.push_back(feat);
// Construct face feature
HFFaceFeature feature = {0};
feature.size = feat.size();
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
HInt32 totalFace;
ret = HFFeatureHubGetFaceCount(&totalFace);
REQUIRE(ret == HSUCCEED);
REQUIRE(totalFace == genSizeOfBase);
HInt32 targetId = 9800;
auto targetFeature = baseFeatures[targetId - 1];
auto searchFeat = SimulateSimilarVector(targetFeature);
HFFaceFeature searchFeature = {0};
searchFeature.size = searchFeat.size();
searchFeature.data = searchFeat.data();
HFloat confidence = 0.0f;
HFFaceFeatureIdentity mostSimilar = {0};
inspirecv::TimeSpend timeSpend("Face Search 10k@Persistence");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
ret = HFFeatureHubFaceSearch(searchFeature, &confidence, &mostSimilar);
REQUIRE(ret == HSUCCEED);
REQUIRE(mostSimilar.id == targetId);
REQUIRE(confidence > 0.88f);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HSUCCEED);
delete[] dbPathStr;
}
}
TEST_CASE("test_BenchmarkFaceHubSearchMemory", "[benchmark]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
SECTION("Benchmark search 1k@Memory") {
const int loop = 1000;
HResult ret;
HFFeatureHubConfiguration configuration;
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 0;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
ret = HFFeatureHubDataEnable(configuration);
REQUIRE(ret == HSUCCEED);
std::vector<std::vector<HFloat>> baseFeatures;
size_t genSizeOfBase = 1000;
HInt32 featureLength;
HFGetFeatureLength(&featureLength);
REQUIRE(featureLength > 0);
for (int i = 0; i < genSizeOfBase; ++i) {
auto feat = GenerateRandomFeature(featureLength);
baseFeatures.push_back(feat);
// Construct face feature
HFFaceFeature feature = {0};
feature.size = feat.size();
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
HInt32 totalFace;
ret = HFFeatureHubGetFaceCount(&totalFace);
REQUIRE(ret == HSUCCEED);
REQUIRE(totalFace == genSizeOfBase);
HInt32 targetId = 800;
auto targetFeature = baseFeatures[targetId - 1];
auto searchFeat = SimulateSimilarVector(targetFeature);
HFFaceFeature searchFeature = {0};
searchFeature.size = searchFeat.size();
searchFeature.data = searchFeat.data();
HFloat confidence = 0.0f;
HFFaceFeatureIdentity mostSimilar = {0};
inspirecv::TimeSpend timeSpend("Face Search 1k@Memory");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
ret = HFFeatureHubFaceSearch(searchFeature, &confidence, &mostSimilar);
REQUIRE(ret == HSUCCEED);
REQUIRE(mostSimilar.id == targetId);
REQUIRE(confidence > 0.88f);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HSUCCEED);
}
SECTION("Benchmark search 5k@Persistence") {
const int loop = 1000;
HResult ret;
HFFeatureHubConfiguration configuration;
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 0;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
ret = HFFeatureHubDataEnable(configuration);
REQUIRE(ret == HSUCCEED);
std::vector<std::vector<HFloat>> baseFeatures;
size_t genSizeOfBase = 5000;
HInt32 featureLength;
HFGetFeatureLength(&featureLength);
REQUIRE(featureLength > 0);
for (int i = 0; i < genSizeOfBase; ++i) {
auto feat = GenerateRandomFeature(featureLength);
baseFeatures.push_back(feat);
// Construct face feature
HFFaceFeature feature = {0};
feature.size = feat.size();
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
HInt32 totalFace;
ret = HFFeatureHubGetFaceCount(&totalFace);
REQUIRE(ret == HSUCCEED);
REQUIRE(totalFace == genSizeOfBase);
HInt32 targetId = 4800;
auto targetFeature = baseFeatures[targetId - 1];
auto searchFeat = SimulateSimilarVector(targetFeature);
HFFaceFeature searchFeature = {0};
searchFeature.size = searchFeat.size();
searchFeature.data = searchFeat.data();
HFloat confidence = 0.0f;
HFFaceFeatureIdentity mostSimilar = {0};
inspirecv::TimeSpend timeSpend("Face Search 5k@Memory");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
ret = HFFeatureHubFaceSearch(searchFeature, &confidence, &mostSimilar);
REQUIRE(ret == HSUCCEED);
REQUIRE(mostSimilar.id == targetId);
REQUIRE(confidence > 0.88f);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HSUCCEED);
}
SECTION("Benchmark search 10k@Persistence") {
const int loop = 1000;
HResult ret;
HFFeatureHubConfiguration configuration;
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 0;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
ret = HFFeatureHubDataEnable(configuration);
REQUIRE(ret == HSUCCEED);
std::vector<std::vector<HFloat>> baseFeatures;
size_t genSizeOfBase = 10000;
HInt32 featureLength;
HFGetFeatureLength(&featureLength);
REQUIRE(featureLength > 0);
for (int i = 0; i < genSizeOfBase; ++i) {
auto feat = GenerateRandomFeature(featureLength);
baseFeatures.push_back(feat);
// Construct face feature
HFFaceFeature feature = {0};
feature.size = feat.size();
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
HInt32 totalFace;
ret = HFFeatureHubGetFaceCount(&totalFace);
REQUIRE(ret == HSUCCEED);
REQUIRE(totalFace == genSizeOfBase);
HInt32 targetId = 9800;
auto targetFeature = baseFeatures[targetId - 1];
auto searchFeat = SimulateSimilarVector(targetFeature);
HFFaceFeature searchFeature = {0};
searchFeature.size = searchFeat.size();
searchFeature.data = searchFeat.data();
HFloat confidence = 0.0f;
HFFaceFeatureIdentity mostSimilar = {0};
inspirecv::TimeSpend timeSpend("Face Search 10k@Memory");
for (size_t i = 0; i < loop; i++) {
timeSpend.Start();
ret = HFFeatureHubFaceSearch(searchFeature, &confidence, &mostSimilar);
REQUIRE(ret == HSUCCEED);
REQUIRE(mostSimilar.id == targetId);
REQUIRE(confidence > 0.88f);
timeSpend.Stop();
}
std::cout << timeSpend << std::endl;
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HSUCCEED);
}
}
#endif

View File

@@ -1,11 +1,10 @@
//
// Created by Tunm-Air13 on 2024/3/26.
//
/**
* Created by Jingyu Yan
* @date 2024-10-01
*/
#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"
#include "unit/test_helper/test_tools.h"
@@ -24,24 +23,15 @@ TEST_CASE("test_Evaluation", "[face_evaluation") {
REQUIRE(ret == HSUCCEED);
float mostSim = -1.0f;
auto succ = FindMostSimilarScoreFromTwoPic(session,
GET_DATA("data/bulk/jntm.jpg"),
GET_DATA("data/bulk/kun.jpg"),
mostSim);
auto succ = FindMostSimilarScoreFromTwoPic(session, GET_DATA("data/bulk/jntm.jpg"), GET_DATA("data/bulk/kun.jpg"), mostSim);
CHECK(succ);
TEST_PRINT("kun v kun :{}", mostSim);
succ = FindMostSimilarScoreFromTwoPic(session,
GET_DATA("data/bulk/jntm.jpg"),
GET_DATA("data/bulk/Rob_Lowe_0001.jpg"),
mostSim);
succ = FindMostSimilarScoreFromTwoPic(session, GET_DATA("data/bulk/jntm.jpg"), GET_DATA("data/bulk/Rob_Lowe_0001.jpg"), mostSim);
CHECK(succ);
TEST_PRINT("kun v other :{}", mostSim);
succ = FindMostSimilarScoreFromTwoPic(session,
GET_DATA("data/bulk/kun.jpg"),
GET_DATA("data/bulk/view.jpg"),
mostSim);
succ = FindMostSimilarScoreFromTwoPic(session, GET_DATA("data/bulk/kun.jpg"), GET_DATA("data/bulk/view.jpg"), mostSim);
CHECK(!succ);
TEST_PRINT("kun v other :{}", mostSim);
@@ -50,7 +40,6 @@ TEST_CASE("test_Evaluation", "[face_evaluation") {
REQUIRE(ret == HSUCCEED);
}
SECTION("Test LFW evaluation") {
#ifdef ISF_ENABLE_TEST_EVALUATION
HResult ret;
@@ -65,14 +54,12 @@ TEST_CASE("test_Evaluation", "[face_evaluation") {
auto pairs = ReadPairs(getTestLFWFunneledEvaTxt());
// Hide cursor
show_console_cursor(false);
BlockProgressBar bar{
option::BarWidth{60},
option::Start{"["},
option::End{"]"},
option::PostfixText{"Extracting face features"},
option::ForegroundColor{Color::white} ,
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}
};
BlockProgressBar bar{option::BarWidth{60},
option::Start{"["},
option::End{"]"},
option::PostfixText{"Extracting face features"},
option::ForegroundColor{Color::white},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}};
auto progress = 0.0f;
for (int i = 0; i < pairs.size(); ++i) {
@@ -87,20 +74,16 @@ TEST_CASE("test_Evaluation", "[face_evaluation") {
person1 = pair[0];
imgNum1 = std::stoi(pair[1]);
imgNum2 = std::stoi(pair[2]);
imgPath1 = PathJoin(PathJoin(getLFWFunneledDir(), person1),
person1 + "_" + zfill(imgNum1, 4) + ".jpg");
imgPath2 = PathJoin(PathJoin(getLFWFunneledDir(), person1),
person1 + "_" + zfill(imgNum2, 4) + ".jpg");
imgPath1 = PathJoin(PathJoin(getLFWFunneledDir(), person1), person1 + "_" + zfill(imgNum1, 4) + ".jpg");
imgPath2 = PathJoin(PathJoin(getLFWFunneledDir(), person1), person1 + "_" + zfill(imgNum2, 4) + ".jpg");
match = 1;
} else {
person1 = pair[0];
imgNum1 = std::stoi(pair[1]);
person2 = pair[2];
imgNum2 = std::stoi(pair[3]);
imgPath1 = PathJoin(PathJoin(getLFWFunneledDir(), person1),
person1 + "_" + zfill(imgNum1, 4) + ".jpg");
imgPath2 = PathJoin(PathJoin(getLFWFunneledDir(), person2),
person2 + "_" + zfill(imgNum2, 4) + ".jpg");
imgPath1 = PathJoin(PathJoin(getLFWFunneledDir(), person1), person1 + "_" + zfill(imgNum1, 4) + ".jpg");
imgPath2 = PathJoin(PathJoin(getLFWFunneledDir(), person2), person2 + "_" + zfill(imgNum2, 4) + ".jpg");
match = 0;
}
@@ -132,5 +115,4 @@ TEST_CASE("test_Evaluation", "[face_evaluation") {
REQUIRE(ret == HSUCCEED);
#endif
}
}

View File

@@ -1,6 +1,7 @@
//
// Created by tunm on 2023/10/11.
//
/**
* Created by Jingyu Yan
* @date 2024-10-01
*/
#include <iostream>
#include "settings/test_settings.h"
@@ -21,6 +22,4 @@ TEST_CASE("test_FeatureContext", "[face_context]") {
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
}

View File

@@ -1,11 +1,12 @@
//
// Created by tunm on 2023/10/12.
//
/**
* Created by Jingyu Yan
* @date 2024-10-01
*/
#include <iostream>
#include "settings/test_settings.h"
#include "inspireface/c_api/inspireface.h"
#include "../test_helper/test_tools.h"
#include "../test_helper/test_help.h"
TEST_CASE("test_FacePipelineAttribute", "[face_pipeline_attribute]") {
DRAW_SPLIT_LINE
@@ -39,14 +40,14 @@ TEST_CASE("test_FacePipelineAttribute", "[face_pipeline_attribute]") {
parameter.enable_face_attribute = 1;
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
HInt32 faceDetectPixelLevel = 160;
HInt32 faceDetectPixelLevel = 320;
ret = HFCreateInspireFaceSession(parameter, detMode, 5, faceDetectPixelLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
SECTION("a black girl") {
HFImageStream imgHandle;
auto img = cv::imread(GET_DATA("data/attribute/1423.jpg"));
REQUIRE(!img.empty());
auto img = inspirecv::Image::Create(GET_DATA("data/attribute/1423.jpg"));
REQUIRE(!img.Empty());
ret = CVImageToImageStream(img, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -56,8 +57,7 @@ TEST_CASE("test_FacePipelineAttribute", "[face_pipeline_attribute]") {
REQUIRE(multipleFaceData.detectedNum == 1);
// Run pipeline
ret = HFMultipleFacePipelineProcessOptional(session, imgHandle, &multipleFaceData,
HF_ENABLE_FACE_ATTRIBUTE);
ret = HFMultipleFacePipelineProcessOptional(session, imgHandle, &multipleFaceData, HF_ENABLE_FACE_ATTRIBUTE);
REQUIRE(ret == HSUCCEED);
HFFaceAttributeResult result = {0};
@@ -77,8 +77,8 @@ TEST_CASE("test_FacePipelineAttribute", "[face_pipeline_attribute]") {
SECTION("two young white women") {
HFImageStream imgHandle;
auto img = cv::imread(GET_DATA("data/attribute/7242.jpg"));
REQUIRE(!img.empty());
auto img = inspirecv::Image::Create(GET_DATA("data/attribute/7242.jpg"));
REQUIRE(!img.Empty());
ret = CVImageToImageStream(img, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -88,8 +88,7 @@ TEST_CASE("test_FacePipelineAttribute", "[face_pipeline_attribute]") {
REQUIRE(multipleFaceData.detectedNum == 2);
// Run pipeline
ret = HFMultipleFacePipelineProcessOptional(session, imgHandle, &multipleFaceData,
HF_ENABLE_FACE_ATTRIBUTE);
ret = HFMultipleFacePipelineProcessOptional(session, imgHandle, &multipleFaceData, HF_ENABLE_FACE_ATTRIBUTE);
REQUIRE(ret == HSUCCEED);
HFFaceAttributeResult result = {0};
@@ -114,65 +113,24 @@ TEST_CASE("test_FacePipelineAttribute", "[face_pipeline_attribute]") {
REQUIRE(ret == HSUCCEED);
}
TEST_CASE("test_FacePipelineRobustness", "[robustness]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
SECTION("Exception") {
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
REQUIRE(ret == HSUCCEED);
// Input exception data
HFImageStream nullHandle = {0};
HFMultipleFaceData nullfaces = {0};
ret =
HFMultipleFacePipelineProcessOptional(session, nullHandle, &nullfaces, HF_ENABLE_NONE);
REQUIRE(ret == HERR_INVALID_IMAGE_STREAM_HANDLE);
// Get a face picture
HFImageStream img1Handle;
auto img1 = cv::imread(GET_DATA("data/bulk/image_T1.jpeg"));
ret = CVImageToImageStream(img1, img1Handle);
REQUIRE(ret == HSUCCEED);
// Input correct Image and exception faces struct
ret =
HFMultipleFacePipelineProcessOptional(session, img1Handle, &nullfaces, HF_ENABLE_NONE);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageStream(img1Handle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
// Multiple release
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HERR_INVALID_CONTEXT_HANDLE);
HFDeBugShowResourceStatistics();
}
}
TEST_CASE("test_FacePipeline", "[face_pipeline]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
SECTION("rgb liveness detect") {
#ifndef INFERENCE_WRAPPER_ENABLE_RKNN2
/** The anti spoofing model based on RGB faces seems to have some problems with quantization under RKNPU2, so it is not started yet */
HResult ret;
HFSessionCustomParameter parameter = {0};
parameter.enable_liveness = 1;
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
ret = HFCreateInspireFaceSession(parameter, detMode, 3, 320, -1, &session);
REQUIRE(ret == HSUCCEED);
// Get a face picture
HFImageStream img1Handle;
auto img1 = cv::imread(GET_DATA("data/bulk/image_T1.jpeg"));
auto img1 = inspirecv::Image::Create(GET_DATA("data/bulk/image_T1.jpeg"));
ret = CVImageToImageStream(img1, img1Handle);
REQUIRE(ret == HSUCCEED);
@@ -189,7 +147,7 @@ TEST_CASE("test_FacePipeline", "[face_pipeline]") {
TEST_PRINT("{}", confidence.confidence[0]);
REQUIRE(ret == HSUCCEED);
CHECK(confidence.num > 0);
CHECK(confidence.confidence[0] > 0.9);
CHECK(confidence.confidence[0] > 0.8);
ret = HFReleaseImageStream(img1Handle);
REQUIRE(ret == HSUCCEED);
@@ -197,7 +155,7 @@ TEST_CASE("test_FacePipeline", "[face_pipeline]") {
// fake face
HFImageStream img2Handle;
auto img2 = cv::imread(GET_DATA("data/bulk/rgb_fake.jpg"));
auto img2 = inspirecv::Image::Create(GET_DATA("data/bulk/rgb_fake.jpg"));
ret = CVImageToImageStream(img2, img2Handle);
REQUIRE(ret == HSUCCEED);
ret = HFExecuteFaceTrack(session, img2Handle, &multipleFaceData);
@@ -216,6 +174,9 @@ TEST_CASE("test_FacePipeline", "[face_pipeline]") {
ret = HFReleaseInspireFaceSession(session);
session = nullptr;
REQUIRE(ret == HSUCCEED);
#else
TEST_PRINT("The anti spoofing model based on RGB faces seems to have some problems with quantization under RKNPU2, so we skip this test.");
#endif
}
SECTION("face mask detect") {
@@ -229,7 +190,7 @@ TEST_CASE("test_FacePipeline", "[face_pipeline]") {
// Get a face picture
HFImageStream img1Handle;
auto img1 = cv::imread(GET_DATA("data/bulk/mask2.jpg"));
auto img1 = inspirecv::Image::Create(GET_DATA("data/bulk/mask2.jpg"));
ret = CVImageToImageStream(img1, img1Handle);
REQUIRE(ret == HSUCCEED);
@@ -253,7 +214,7 @@ TEST_CASE("test_FacePipeline", "[face_pipeline]") {
// no mask face
HFImageStream img2Handle;
auto img2 = cv::imread(GET_DATA("data/bulk/face_sample.png"));
auto img2 = inspirecv::Image::Create(GET_DATA("data/bulk/face_sample.png"));
ret = CVImageToImageStream(img2, img2Handle);
REQUIRE(ret == HSUCCEED);
ret = HFExecuteFaceTrack(session, img2Handle, &multipleFaceData);
@@ -280,12 +241,12 @@ TEST_CASE("test_FacePipeline", "[face_pipeline]") {
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HInt32 option = HF_ENABLE_QUALITY;
HFSession session;
ret = HFCreateInspireFaceSessionOptional(option, detMode, 3, -1, -1, &session);
ret = HFCreateInspireFaceSessionOptional(option, detMode, 3, 320, -1, &session);
REQUIRE(ret == HSUCCEED);
// Get a face picture
HFImageStream superiorHandle;
auto superior = cv::imread(GET_DATA("data/bulk/yifei.jpg"));
auto superior = inspirecv::Image::Create(GET_DATA("data/bulk/yifei.jpg"));
ret = CVImageToImageStream(superior, superiorHandle);
REQUIRE(ret == HSUCCEED);
@@ -295,18 +256,17 @@ TEST_CASE("test_FacePipeline", "[face_pipeline]") {
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum > 0);
ret =
HFMultipleFacePipelineProcessOptional(session, superiorHandle, &multipleFaceData, option);
ret = HFMultipleFacePipelineProcessOptional(session, superiorHandle, &multipleFaceData, option);
REQUIRE(ret == HSUCCEED);
HFloat quality;
ret = HFFaceQualityDetect(session, multipleFaceData.tokens[0], &quality);
REQUIRE(ret == HSUCCEED);
CHECK(quality > 0.85);
CHECK(quality > 0.8);
// blur image
HFImageStream blurHandle;
auto blur = cv::imread(GET_DATA("data/bulk/blur.jpg"));
auto blur = inspirecv::Image::Create(GET_DATA("data/bulk/blur.jpg"));
ret = CVImageToImageStream(blur, blurHandle);
REQUIRE(ret == HSUCCEED);
@@ -349,7 +309,7 @@ TEST_CASE("test_FaceReaction", "[face_reaction]") {
SECTION("open eyes") {
// Get a face picture
HFImageStream imgHandle;
auto img = cv::imread(GET_DATA("data/reaction/open_eyes.png"));
auto img = inspirecv::Image::Create(GET_DATA("data/reaction/open_eyes.png"));
ret = CVImageToImageStream(img, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -364,8 +324,8 @@ TEST_CASE("test_FaceReaction", "[face_reaction]") {
REQUIRE(ret == HSUCCEED);
// Get results
HFFaceIntereactionState result;
ret = HFGetFaceIntereactionStateResult(session, &result);
HFFaceInteractionState result;
ret = HFGetFaceInteractionStateResult(session, &result);
REQUIRE(multipleFaceData.detectedNum == result.num);
REQUIRE(ret == HSUCCEED);
@@ -380,7 +340,7 @@ TEST_CASE("test_FaceReaction", "[face_reaction]") {
SECTION("close eyes") {
// Get a face picture
HFImageStream imgHandle;
auto img = cv::imread(GET_DATA("data/reaction/close_eyes.jpeg"));
auto img = inspirecv::Image::Create(GET_DATA("data/reaction/close_eyes.jpeg"));
ret = CVImageToImageStream(img, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -395,8 +355,8 @@ TEST_CASE("test_FaceReaction", "[face_reaction]") {
REQUIRE(ret == HSUCCEED);
// Get results
HFFaceIntereactionState result;
ret = HFGetFaceIntereactionStateResult(session, &result);
HFFaceInteractionState result;
ret = HFGetFaceInteractionStateResult(session, &result);
REQUIRE(multipleFaceData.detectedNum == result.num);
REQUIRE(ret == HSUCCEED);
@@ -411,7 +371,7 @@ TEST_CASE("test_FaceReaction", "[face_reaction]") {
SECTION("Close one eye and open the other") {
// Get a face picture
HFImageStream imgHandle;
auto img = cv::imread(GET_DATA("data/reaction/close_open_eyes.jpeg"));
auto img = inspirecv::Image::Create(GET_DATA("data/reaction/close_open_eyes.jpeg"));
ret = CVImageToImageStream(img, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -426,8 +386,8 @@ TEST_CASE("test_FaceReaction", "[face_reaction]") {
REQUIRE(ret == HSUCCEED);
// Get results
HFFaceIntereactionState result;
ret = HFGetFaceIntereactionStateResult(session, &result);
HFFaceInteractionState result;
ret = HFGetFaceInteractionStateResult(session, &result);
REQUIRE(multipleFaceData.detectedNum == result.num);
REQUIRE(ret == HSUCCEED);
@@ -441,4 +401,87 @@ TEST_CASE("test_FaceReaction", "[face_reaction]") {
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
}
TEST_CASE("test_TrackModeFaceAction", "[face_action]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
HResult ret;
HFSessionCustomParameter parameter = {0};
parameter.enable_interaction_liveness = 1;
HFDetectMode detMode = HF_DETECT_MODE_LIGHT_TRACK;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
REQUIRE(ret == HSUCCEED);
#if 0
SECTION("Action Blink") {
auto start = 130, end = 150;
std::vector<std::string> filenames = generateFilenames("frame-%04d.jpg", start, end);
int count = 0;
for (size_t i = 0; i < filenames.size(); i++) {
auto filename = filenames[i];
HFImageStream imgHandle;
auto image = inspirecv::Image::Create(GET_DATA("data/video_frames/" + filename));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum > 0);
ret = HFMultipleFacePipelineProcessOptional(session, imgHandle, &multipleFaceData, HF_ENABLE_INTERACTION);
REQUIRE(ret == HSUCCEED);
HFFaceInteractionsActions result;
ret = HFGetFaceInteractionActionsResult(session, &result);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == result.num);
count += result.blink[0];
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
}
// Blink at least once
REQUIRE(count > 0);
}
#endif
#if 0
SECTION("Action Jaw Open") {
auto start = 110, end = 150;
std::vector<std::string> filenames = generateFilenames("frame-%04d.jpg", start, end);
int count = 0;
for (size_t i = 0; i < filenames.size(); i++) {
auto filename = filenames[i];
HFImageStream imgHandle;
auto image = inspirecv::Image::Create(GET_DATA("data/video_frames/" + filename));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum > 0);
ret = HFMultipleFacePipelineProcessOptional(session, imgHandle, &multipleFaceData, HF_ENABLE_INTERACTION);
REQUIRE(ret == HSUCCEED);
HFFaceInteractionsActions result;
ret = HFGetFaceInteractionActionsResult(session, &result);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == result.num);
count += result.jawOpen[0];
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
}
// Jaw open at least once
REQUIRE(count > 0);
}
#endif
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}

View File

@@ -1,14 +1,15 @@
//
// Created by tunm on 2023/10/11.
//
/**
* Created by Jingyu Yan
* @date 2024-10-01
*/
#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"
#include "unit/test_helper/test_tools.h"
#include "middleware/costman.h"
TEST_CASE("test_FaceTrack", "[face_track]") {
DRAW_SPLIT_LINE
@@ -20,11 +21,12 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
TEST_ERROR_PRINT("error ret :{}", ret);
REQUIRE(ret == HSUCCEED);
// Get a face picture
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/kun.jpg"));
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/kun.jpg"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -37,24 +39,24 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
// Detect face position
auto rect = multipleFaceData.rects[0];
HFaceRect expect = {0};
expect.x = 98;
expect.y = 146;
expect.width = 233 - expect.x;
expect.height = 272 - expect.y;
expect.x = 79;
expect.y = 104;
expect.width = 168;
expect.height = 167;
auto iou = CalculateOverlap(rect, expect);
cv::Rect cvRect(rect.x, rect.y, rect.width, rect.height);
cv::rectangle(image, cvRect, cv::Scalar(255, 0, 124), 2);
cv::imwrite("ww.jpg", image);
// The iou is allowed to have an error of 10%
CHECK(iou == Approx(1.0f).epsilon(0.3));
auto cvRect = inspirecv::Rect<int>::Create(rect.x, rect.y, rect.width, rect.height);
image.DrawRect(cvRect, {0, 0, 255}, 2);
image.Write("ww.jpg");
// The iou is allowed to have an error of 25%
CHECK(iou == Approx(1.0f).epsilon(0.25));
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
// Prepare non-face images
HFImageStream viewHandle;
auto view = cv::imread(GET_DATA("data/bulk/view.jpg"));
auto view = inspirecv::Image::Create(GET_DATA("data/bulk/view.jpg"));
ret = CVImageToImageStream(view, viewHandle);
REQUIRE(ret == HSUCCEED);
ret = HFExecuteFaceTrack(session, viewHandle, &multipleFaceData);
@@ -68,6 +70,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
REQUIRE(ret == HSUCCEED);
}
#if 0
SECTION("Face tracking stability from frames") {
HResult ret;
HFSessionCustomParameter parameter = {0};
@@ -83,7 +86,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
for (int i = 0; i < filenames.size(); ++i) {
auto filename = filenames[i];
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/video_frames/" + filename));
auto image = inspirecv::Image::Create(GET_DATA("data/video_frames/" + filename));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -96,10 +99,10 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
continue;
}
auto rect = multipleFaceData.rects[0];
cv::Rect cvRect(rect.x, rect.y, rect.width, rect.height);
cv::rectangle(image, cvRect, cv::Scalar(255, 0, 124), 2);
std::string save = GET_SAVE_DATA("data/video_frames") + "/" + std::to_string(i) + ".jpg";
cv::imwrite(save, image);
auto cvRect = inspirecv::Rect<int>::Create(rect.x, rect.y, rect.width, rect.height);
image.DrawRect(cvRect, {0, 0, 255}, 2);
std::string save = GET_SAVE_DATA("video_frames") + "/" + std::to_string(i) + ".jpg";
image.Write(save);
auto id = multipleFaceData.trackIds[0];
// TEST_PRINT("{}", id);
if (id != expectedId) {
@@ -116,6 +119,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
#endif
SECTION("Head pose estimation") {
HResult ret;
@@ -130,7 +134,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
// Left side face
HFImageStream leftHandle;
auto left = cv::imread(GET_DATA("data/pose/left_face.jpeg"));
auto left = inspirecv::Image::Create(GET_DATA("data/pose/left_face.jpeg"));
ret = CVImageToImageStream(left, leftHandle);
REQUIRE(ret == HSUCCEED);
@@ -150,7 +154,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
// Right-handed rotation
HFImageStream rightHandle;
auto right = cv::imread(GET_DATA("data/pose/right_face.png"));
auto right = inspirecv::Image::Create(GET_DATA("data/pose/right_face.png"));
ret = CVImageToImageStream(right, rightHandle);
REQUIRE(ret == HSUCCEED);
@@ -165,7 +169,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
// Rise head
HFImageStream riseHandle;
auto rise = cv::imread(GET_DATA("data/pose/rise_face.jpeg"));
auto rise = inspirecv::Image::Create(GET_DATA("data/pose/rise_face.jpeg"));
ret = CVImageToImageStream(rise, riseHandle);
REQUIRE(ret == HSUCCEED);
@@ -173,12 +177,12 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
pitch = multipleFaceData.angles.pitch[0];
CHECK(pitch > 5);
CHECK(pitch > 3);
HFReleaseImageStream(riseHandle);
// Lower head
HFImageStream lowerHandle;
auto lower = cv::imread(GET_DATA("data/pose/lower_face.jpeg"));
auto lower = inspirecv::Image::Create(GET_DATA("data/pose/lower_face.jpeg"));
ret = CVImageToImageStream(lower, lowerHandle);
REQUIRE(ret == HSUCCEED);
@@ -191,7 +195,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
// Roll head
HFImageStream leftWryneckHandle;
auto leftWryneck = cv::imread(GET_DATA("data/pose/left_wryneck.png"));
auto leftWryneck = inspirecv::Image::Create(GET_DATA("data/pose/left_wryneck.png"));
ret = CVImageToImageStream(leftWryneck, leftWryneckHandle);
REQUIRE(ret == HSUCCEED);
@@ -204,7 +208,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
// Roll head
HFImageStream rightWryneckHandle;
auto rightWryneck = cv::imread(GET_DATA("data/pose/right_wryneck.png"));
auto rightWryneck = inspirecv::Image::Create(GET_DATA("data/pose/right_wryneck.png"));
ret = CVImageToImageStream(rightWryneck, rightWryneckHandle);
REQUIRE(ret == HSUCCEED);
@@ -212,7 +216,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
roll = multipleFaceData.angles.roll[0];
CHECK(roll > 30);
CHECK(roll > 25);
HFReleaseImageStream(rightWryneckHandle);
// finish
@@ -220,117 +224,44 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
REQUIRE(ret == HSUCCEED);
}
SECTION("Face detection benchmark") {
#ifdef ISF_ENABLE_BENCHMARK
SECTION("Face detection benchmark@160") {
int loop = 1000;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
HInt32 pixLevel = 160;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, pixLevel, -1, &session);
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
REQUIRE(ret == HSUCCEED);
// Prepare an image
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/kun.jpg"));
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/kun.jpg"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
BenchmarkRecord record(getBenchmarkRecordFile());
REQUIRE(ret == HSUCCEED);
HFMultipleFaceData multipleFaceData = {0};
auto start = (double)cv::getTickCount();
auto timer = inspire::Timer();
for (int i = 0; i < loop; ++i) {
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
}
auto cost = ((double)cv::getTickCount() - start) / cv::getTickFrequency() * 1000;
auto cost = timer.GetCostTime();
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
TEST_PRINT("<Benchmark> Face Detect@160 -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop);
record.insertBenchmarkData("Face Detect@160", loop, cost, cost / loop);
TEST_PRINT("<Benchmark> Face Detect -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop);
record.insertBenchmarkData("Face Detect", loop, cost, cost / loop);
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
SECTION("Face detection benchmark@320") {
int loop = 1000;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
HInt32 pixLevel = 320;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, pixLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
// Prepare an image
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/kun.jpg"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
BenchmarkRecord record(getBenchmarkRecordFile());
REQUIRE(ret == HSUCCEED);
HFMultipleFaceData multipleFaceData = {0};
auto start = (double)cv::getTickCount();
for (int i = 0; i < loop; ++i) {
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
}
auto cost = ((double)cv::getTickCount() - start) / cv::getTickFrequency() * 1000;
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
TEST_PRINT("<Benchmark> Face Detect@320 -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop);
record.insertBenchmarkData("Face Detect@320", loop, cost, cost / loop);
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
SECTION("Face detection benchmark@640") {
int loop = 1000;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
HInt32 pixLevel = 640;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, pixLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
// Prepare an image
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/kun.jpg"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
BenchmarkRecord record(getBenchmarkRecordFile());
REQUIRE(ret == HSUCCEED);
HFMultipleFaceData multipleFaceData = {0};
auto start = (double)cv::getTickCount();
for (int i = 0; i < loop; ++i) {
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
}
auto cost = ((double)cv::getTickCount() - start) / cv::getTickFrequency() * 1000;
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
TEST_PRINT("<Benchmark> Face Detect@640 -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop);
record.insertBenchmarkData("Face Detect@640", loop, cost, cost / loop);
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
#else
TEST_PRINT("Skip the face detection benchmark test. To run it, you need to turn on the benchmark test.");
TEST_PRINT("Skip the face detection benchmark test. To run it, you need to turn on the benchmark test.");
#endif
}
SECTION("Face light track benchmark") {
#ifdef ISF_ENABLE_BENCHMARK
@@ -344,7 +275,7 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
// Prepare an image
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/kun.jpg"));
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/kun.jpg"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
BenchmarkRecord record(getBenchmarkRecordFile());
@@ -352,13 +283,13 @@ TEST_CASE("test_FaceTrack", "[face_track]") {
// Case: Execute the benchmark using the VIDEO mode(Track)
REQUIRE(ret == HSUCCEED);
HFMultipleFaceData multipleFaceData = {0};
auto start = (double)cv::getTickCount();
auto timer = inspire::Timer();
for (int i = 0; i < loop; ++i) {
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
}
auto cost = ((double)cv::getTickCount() - start) / cv::getTickFrequency() * 1000;
auto cost = timer.GetCostTime();
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum > 0);
REQUIRE(multipleFaceData.detectedNum >= 1);
TEST_PRINT("<Benchmark> Face Track -> Loop: {}, Total Time: {:.5f}ms, Average Time: {:.5f}ms", loop, cost, cost / loop);
record.insertBenchmarkData("Face Track", loop, cost, cost / loop);
@@ -377,12 +308,12 @@ TEST_CASE("test_MultipleLevelFaceDetect", "[face_detect]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
SECTION("Detect input 160px") {
SECTION("Detect input 192px") {
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
HInt32 detectPixelLevel = 160;
HInt32 detectPixelLevel = 192;
ret = HFCreateInspireFaceSession(parameter, detMode, 20, detectPixelLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
HFSessionSetTrackPreviewSize(session, detectPixelLevel);
@@ -390,7 +321,7 @@ TEST_CASE("test_MultipleLevelFaceDetect", "[face_detect]") {
// Get a face picture
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/pedestrian.png"));
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/pedestrian.png"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -422,7 +353,7 @@ TEST_CASE("test_MultipleLevelFaceDetect", "[face_detect]") {
// Get a face picture
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/pedestrian.png"));
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/pedestrian.png"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -432,7 +363,7 @@ TEST_CASE("test_MultipleLevelFaceDetect", "[face_detect]") {
REQUIRE(ret == HSUCCEED);
CHECK(multipleFaceData.detectedNum > 9);
CHECK(multipleFaceData.detectedNum < 15);
CHECK(multipleFaceData.detectedNum < 12);
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -454,7 +385,7 @@ TEST_CASE("test_MultipleLevelFaceDetect", "[face_detect]") {
// Get a face picture
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/pedestrian.png"));
auto image = inspirecv::Image::Create(GET_DATA("data/bulk/pedestrian.png"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
@@ -464,167 +395,11 @@ TEST_CASE("test_MultipleLevelFaceDetect", "[face_detect]") {
REQUIRE(ret == HSUCCEED);
CHECK(multipleFaceData.detectedNum > 15);
CHECK(multipleFaceData.detectedNum < 25);
CHECK(multipleFaceData.detectedNum < 21);
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
}
TEST_CASE("test_FaceShowLandmark", "[face_landmark]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
std::vector<std::string> images_path = {
GET_DATA("data/reaction/close_open_eyes.jpeg"),
GET_DATA("data/reaction/open_eyes.png"),
GET_DATA("data/reaction/close_eyes.jpeg"),
};
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
HInt32 detectPixelLevel = 160;
ret = HFCreateInspireFaceSession(parameter, detMode, 20, detectPixelLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
HFSessionSetTrackPreviewSize(session, detectPixelLevel);
HFSessionSetFilterMinimumFacePixelSize(session, 0);
for (size_t i = 0; i < images_path.size(); i++) {
HFImageStream imgHandle;
auto image = cv::imread(images_path[i]);
ret = CVImageToImageStream(image, 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);
HInt32 numOfLmk;
HFGetNumOfFaceDenseLandmark(&numOfLmk);
HPoint2f denseLandmarkPoints[numOfLmk];
ret = HFGetFaceDenseLandmarkFromFaceToken(multipleFaceData.tokens[0], denseLandmarkPoints, numOfLmk);
REQUIRE(ret == HSUCCEED);
for (size_t i = 0; i < numOfLmk; i++) {
cv::Point2f p(denseLandmarkPoints[i].x, denseLandmarkPoints[i].y);
cv::circle(image, p, 0, (0, 0, 255), 2);
}
cv::imwrite("lml_" + std::to_string(i) + ".jpg", image);
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
}
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
TEST_CASE("test_FaceDetectConfidence", "[face_track]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
SECTION("DetectConfidenceSchedule-1") {
// Schedule 1:
HFloat threshold = 0.4f;
HInt32 detectPixelLevel = 160;
HInt32 maxDetectNum = 20;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, maxDetectNum, detectPixelLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
ret = HFSessionSetFaceDetectThreshold(session, threshold);
REQUIRE(ret == HSUCCEED);
// Prepare an image
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/pedestrian.png"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
// Extract basic face information from photos
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
for (int i = 0; i < multipleFaceData.detectedNum; i++) {
CHECK(multipleFaceData.detConfidence[i] >= threshold);
}
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
SECTION("DetectConfidenceSchedule-2") {
// Schedule 2:
HFloat threshold = 0.7f;
HInt32 detectPixelLevel = 320;
HInt32 maxDetectNum = 10;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, maxDetectNum, detectPixelLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
ret = HFSessionSetFaceDetectThreshold(session, threshold);
REQUIRE(ret == HSUCCEED);
// Prepare an image
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/pedestrian.png"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
// Extract basic face information from photos
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
for (int i = 0; i < multipleFaceData.detectedNum; i++) {
CHECK(multipleFaceData.detConfidence[i] >= threshold);
}
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
SECTION("DetectConfidenceSchedule-3") {
// Schedule 3:
HFloat threshold = 0.80f;
HInt32 detectPixelLevel = 640;
HInt32 maxDetectNum = 20;
HResult ret;
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, maxDetectNum, detectPixelLevel, -1, &session);
REQUIRE(ret == HSUCCEED);
ret = HFSessionSetFaceDetectThreshold(session, threshold);
REQUIRE(ret == HSUCCEED);
// Prepare an image
HFImageStream imgHandle;
auto image = cv::imread(GET_DATA("data/bulk/pedestrian.png"));
ret = CVImageToImageStream(image, imgHandle);
REQUIRE(ret == HSUCCEED);
// Extract basic face information from photos
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, imgHandle, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
for (int i = 0; i < multipleFaceData.detectedNum; i++) {
CHECK(multipleFaceData.detConfidence[i] >= threshold);
}
ret = HFReleaseImageStream(imgHandle);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}

View File

@@ -1,6 +1,7 @@
//
// Created by tunm on 2024/4/13.
//
/**
* Created by Jingyu Yan
* @date 2024-10-01
*/
#include <iostream>
#include "settings/test_settings.h"
#include "inspireface/c_api/inspireface.h"
@@ -13,17 +14,17 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") {
SECTION("FeatureHub basic function") {
HResult ret;
HFFeatureHubConfiguration configuration = {0};
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.dbPath = dbPathStr;
configuration.featureBlockNum = 20;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.dbPath) != 0) {
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
@@ -37,17 +38,17 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") {
SECTION("FeatureHub search top-k") {
HResult ret;
HFFeatureHubConfiguration configuration = {0};
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.dbPath = dbPathStr;
configuration.featureBlockNum = 20;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.dbPath) != 0) {
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
@@ -61,19 +62,14 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") {
for (int i = 0; i < genSizeOfBase; ++i) {
auto feat = GenerateRandomFeature(featureLength);
baseFeatures.push_back(feat);
auto name = std::to_string(i);
// Establish a security buffer
std::vector<char> nameBuffer(name.begin(), name.end());
nameBuffer.push_back('\0');
// Construct face feature
HFFaceFeature feature = {0};
feature.size = feat.size();
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
identity.customId = i;
identity.tag = nameBuffer.data();
ret = HFFeatureHubInsertFeature(identity);
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
HInt32 totalFace;
@@ -82,8 +78,8 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") {
REQUIRE(totalFace == genSizeOfBase);
// 2000 data was imported
HInt32 targetId = 523;
auto targetFeature = baseFeatures[targetId];
HInt32 targetId = 524;
auto targetFeature = baseFeatures[targetId - 1];
std::vector<std::vector<HFloat>> similarVectors;
std::vector<HInt32> coverIds = {2, 300, 524, 789, 1024, 1995};
@@ -95,8 +91,7 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") {
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
identity.customId = coverIds[i];
identity.tag = "HOLD";
identity.id = coverIds[i];
ret = HFFeatureHubFaceUpdate(identity);
REQUIRE(ret == HSUCCEED);
}
@@ -111,12 +106,9 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") {
ret = HFFeatureHubFaceSearchTopK(searchFeature, topK, &results);
REQUIRE(ret == HSUCCEED);
coverIds.push_back(targetId);
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.ids[i]) != coverIds.end());
}
ret = HFFeatureHubDataDisable();
@@ -129,10 +121,10 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") {
HResult ret;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
HFFeatureHubConfiguration configuration = {0};
HFFeatureHubConfiguration configuration;
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 0;
configuration.dbPath = dbPathStr;
configuration.featureBlockNum = 20;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
@@ -140,20 +132,20 @@ TEST_CASE("test_FeatureHubBase", "[FeatureHub][BasicFunction]") {
REQUIRE(ret == HSUCCEED);
ret = HFFeatureHubDataEnable(configuration);
REQUIRE(ret == HERR_FT_HUB_ENABLE_REPETITION);
REQUIRE(ret == HSUCCEED);
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HSUCCEED);
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HERR_FT_HUB_DISABLE_REPETITION);
REQUIRE(ret == HSUCCEED);
delete[] dbPathStr;
}
SECTION("Only memory storage is used") {
HResult ret;
HFFeatureHubConfiguration configuration = {0};
HFFeatureHubConfiguration configuration;
configuration.enablePersistence = 0;
ret = HFFeatureHubDataEnable(configuration);
REQUIRE(ret == HSUCCEED);
@@ -170,17 +162,17 @@ TEST_CASE("test_ConcurrencyInsertion", "[FeatureHub][Concurrency]") {
TEST_PRINT_OUTPUT(true);
HResult ret;
HFFeatureHubConfiguration configuration = {0};
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.dbPath = dbPathStr;
configuration.featureBlockNum = 20;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.dbPath) != 0) {
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
@@ -199,7 +191,7 @@ TEST_CASE("test_ConcurrencyInsertion", "[FeatureHub][Concurrency]") {
auto beginGenId = 2000;
for (int i = 0; i < numThreads; ++i) {
threads.emplace_back([=]() { // 使用值捕获以避免捕获引用后变量改变
threads.emplace_back([=]() {
for (int j = 0; j < insertsPerThread; ++j) {
auto feat = GenerateRandomFeature(featureLength);
auto name = std::to_string(beginGenId + j + i * insertsPerThread);
@@ -210,10 +202,10 @@ TEST_CASE("test_ConcurrencyInsertion", "[FeatureHub][Concurrency]") {
feature.data = feat.data();
HFFaceFeatureIdentity featureIdentity = {0};
featureIdentity.feature = &feature;
featureIdentity.customId =
beginGenId + j + i * insertsPerThread; // 确保 customId 唯一
featureIdentity.tag = nameBuffer.data();
auto ret = HFFeatureHubInsertFeature(featureIdentity);
// featureIdentity.customId = beginGenId + j + i * insertsPerThread;
// featureIdentity.tag = nameBuffer.data();
HFaceId allocId;
auto ret = HFFeatureHubInsertFeature(featureIdentity, &allocId);
REQUIRE(ret == HSUCCEED);
}
});
@@ -226,9 +218,7 @@ 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);
@@ -241,17 +231,17 @@ TEST_CASE("test_ConcurrencyRemove", "[FeatureHub][Concurrency]") {
TEST_PRINT_OUTPUT(true);
HResult ret;
HFFeatureHubConfiguration configuration = {0};
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.dbPath = dbPathStr;
configuration.featureBlockNum = 20;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.dbPath) != 0) {
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
@@ -276,9 +266,10 @@ TEST_CASE("test_ConcurrencyRemove", "[FeatureHub][Concurrency]") {
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
identity.customId = i;
identity.tag = nameBuffer.data();
ret = HFFeatureHubInsertFeature(identity);
// identity.customId = i;
// identity.tag = nameBuffer.data();
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
HInt32 totalFace;
@@ -305,7 +296,8 @@ TEST_CASE("test_ConcurrencyRemove", "[FeatureHub][Concurrency]") {
HInt32 remainingCount;
ret = HFFeatureHubGetFaceCount(&remainingCount);
REQUIRE(ret == HSUCCEED);
REQUIRE(remainingCount == genSizeOfBase - numThreads * removePerThread);
// need exclude id=0
REQUIRE(remainingCount - 1 == genSizeOfBase - numThreads * removePerThread);
TEST_PRINT("Remaining Count: {}", remainingCount);
ret = HFFeatureHubDataDisable();
@@ -319,17 +311,17 @@ TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") {
TEST_PRINT_OUTPUT(true);
HResult ret;
HFFeatureHubConfiguration configuration = {0};
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.dbPath = dbPathStr;
configuration.featureBlockNum = 20;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.dbPath) != 0) {
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
@@ -353,9 +345,10 @@ TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") {
feature.data = feat.data();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
identity.customId = i;
identity.tag = nameBuffer.data();
ret = HFFeatureHubInsertFeature(identity);
// identity.customId = i;
// identity.tag = nameBuffer.data();
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
HInt32 totalFace;
@@ -372,10 +365,9 @@ TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") {
for (int i = 0; i < numberOfSimilar; ++i) {
auto index = targetIds[i];
HFFaceFeatureIdentity identity = {0};
ret = HFFeatureHubGetFaceIdentity(index, &identity);
ret = HFFeatureHubGetFaceIdentity(index + 1, &identity);
REQUIRE(ret == HSUCCEED);
std::vector<HFloat> feature(identity.feature->data,
identity.feature->data + identity.feature->size);
std::vector<HFloat> feature(identity.feature->data, identity.feature->data + identity.feature->size);
auto simFeat = SimulateSimilarVector(feature);
HFFaceFeature simFeature = {0};
simFeature.data = simFeat.data();
@@ -427,7 +419,7 @@ TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") {
HFloat score;
HFFaceFeatureIdentity identity = {0};
HFFeatureHubFaceSearch(feature, &score, &identity);
CHECK(identity.customId == targetId);
REQUIRE(identity.id == targetId + 1);
}
for (int j = 0; j < 50; ++j) {
int idx = dis(gen);
@@ -437,7 +429,7 @@ TEST_CASE("test_ConcurrencySearch", "[FeatureHub][Concurrency]") {
HFloat score;
HFFaceFeatureIdentity identity = {0};
HFFeatureHubFaceSearch(feature, &score, &identity);
CHECK(identity.customId == -1);
REQUIRE(identity.id == -1);
}
});
}
@@ -456,17 +448,17 @@ TEST_CASE("test_FeatureCache", "[FeatureHub][Concurrency]") {
TEST_PRINT_OUTPUT(true);
HResult ret;
HFFeatureHubConfiguration configuration = {0};
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.dbPath = dbPathStr;
configuration.featureBlockNum = 20;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.dbPath) != 0) {
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
@@ -478,10 +470,8 @@ TEST_CASE("test_FeatureCache", "[FeatureHub][Concurrency]") {
feature.size = randomVec.size();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
identity.tag = "FK";
identity.customId = 12;
ret = HFFeatureHubInsertFeature(identity);
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
auto simVec = SimulateSimilarVector(randomVec);
@@ -491,7 +481,7 @@ TEST_CASE("test_FeatureCache", "[FeatureHub][Concurrency]") {
for (int i = 0; i < 10; ++i) {
HFFaceFeatureIdentity capture = {0};
ret = HFFeatureHubGetFaceIdentity(12, &capture);
ret = HFFeatureHubGetFaceIdentity(allocId, &capture);
REQUIRE(ret == HSUCCEED);
HFFaceFeature target = {0};
@@ -510,108 +500,53 @@ TEST_CASE("test_FeatureCache", "[FeatureHub][Concurrency]") {
delete[] dbPathStr;
}
TEST_CASE("test_DataPersistence", "[feature_manage]") {
TEST_CASE("test_FeatureHubManualInput", "[FeatureHub][ManualInput]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
HResult ret;
HFFeatureHubConfiguration configuration;
configuration.primaryKeyMode = HF_PK_MANUAL_INPUT;
configuration.enablePersistence = 0;
TEST_PRINT("Start enable feature hub");
ret = HFFeatureHubDataEnable(configuration);
REQUIRE(ret == HSUCCEED);
TEST_PRINT("Enable feature hub success");
// Generate 10 random feature
std::vector<std::vector<HFloat>> features;
std::vector<std::string> identities;
for (int i = 0; i < 10; ++i) {
auto feat = GenerateRandomFeature(512);
features.push_back(feat);
identities.push_back("id_" + std::to_string(i));
std::vector<HFaceId> ids = {10086, 23541, 2124, 24, 204};
for (auto id : ids) {
auto randomVec = GenerateRandomFeature(512);
HFFaceFeature feature = {0};
feature.data = randomVec.data();
feature.size = randomVec.size();
HFFaceFeatureIdentity identity = {0};
identity.feature = &feature;
identity.id = id;
HFaceId allocId;
ret = HFFeatureHubInsertFeature(identity, &allocId);
REQUIRE(ret == HSUCCEED);
}
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<char *>(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;
HFFeatureHubExistingIds existingIds = {0};
ret = HFFeatureHubGetExistingIds(&existingIds);
REQUIRE(ret == HSUCCEED);
REQUIRE(existingIds.size == ids.size());
for (int i = 0; i < existingIds.size; ++i) {
TEST_PRINT("Existing ID: {}", existingIds.ids[i]);
REQUIRE(existingIds.ids[i] == ids[i]);
}
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 = HFFeatureHubViewDBTable();
REQUIRE(ret == HSUCCEED);
ret = HFFeatureHubDataEnable(configuration);
// query
for (auto id : ids) {
HFFaceFeatureIdentity query = {0};
ret = HFFeatureHubGetFaceIdentity(id, &query);
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;
REQUIRE(query.id == id);
}
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HSUCCEED);
}

View File

@@ -1,7 +1,8 @@
//
// Created by tunm on 2023/10/11.
//
/**
* Created by Jingyu Yan
* @date 2024-10-01
*/
#if 0
#include <iostream>
#include "settings/test_settings.h"
#include "inspireface/c_api/inspireface.h"
@@ -978,3 +979,4 @@ TEST_CASE("test_FeatureBenchmark", "[feature_benchmark]") {
#endif
}
}
#endif

View File

@@ -1,14 +1,15 @@
//
// Created by Tunm-Air13 on 2024/3/20.
//
/**
* Created by Jingyu Yan
* @date 2024-10-01
*/
#include <iostream>
#include "settings/test_settings.h"
#include "../test_helper/test_help.h"
TEST_CASE("test_HelpTools", "[help_tools]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
SECTION("Load lfw funneled data") {
#ifdef ISF_ENABLE_USE_LFW_DATA
@@ -19,17 +20,17 @@ TEST_CASE("test_HelpTools", "[help_tools]") {
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
REQUIRE(ret == HSUCCEED);
HFFeatureHubConfiguration configuration = {0};
HFFeatureHubConfiguration configuration;
auto dbPath = GET_SAVE_DATA(".test");
HString dbPathStr = new char[dbPath.size() + 1];
std::strcpy(dbPathStr, dbPath.c_str());
configuration.primaryKeyMode = HF_PK_AUTO_INCREMENT;
configuration.enablePersistence = 1;
configuration.dbPath = dbPathStr;
configuration.featureBlockNum = 20;
configuration.persistenceDbPath = dbPathStr;
configuration.searchMode = HF_SEARCH_MODE_EXHAUSTIVE;
configuration.searchThreshold = 0.48f;
// Delete the previous data before testing
if (std::remove(configuration.dbPath) != 0) {
if (std::remove(configuration.persistenceDbPath) != 0) {
spdlog::trace("Error deleting file");
}
ret = HFFeatureHubDataEnable(configuration);
@@ -46,8 +47,8 @@ TEST_CASE("test_HelpTools", "[help_tools]") {
REQUIRE(ret == HSUCCEED);
CHECK(count == numOfNeedImport);
// ret = HF_ViewFaceDBTable(session);
// REQUIRE(ret == HSUCCEED);
// ret = HF_ViewFaceDBTable(session);
// REQUIRE(ret == HSUCCEED);
// Finish
ret = HFReleaseInspireFaceSession(session);
@@ -56,7 +57,7 @@ TEST_CASE("test_HelpTools", "[help_tools]") {
ret = HFFeatureHubDataDisable();
REQUIRE(ret == HSUCCEED);
delete []dbPathStr;
delete[] dbPathStr;
#else
TEST_PRINT("The test case that uses LFW is not enabled, so it will be skipped.");

View File

@@ -0,0 +1,45 @@
#include <iostream>
#include "settings/test_settings.h"
#include "inspireface/c_api/inspireface.h"
#include <cstdio>
TEST_CASE("test_ImageBitmap", "[image_bitmap]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
HFImageBitmap handle;
HResult ret = HFCreateImageBitmapFromFilePath(GET_DATA("data/bulk/r90.jpg").c_str(), 3, &handle);
REQUIRE(ret == HSUCCEED);
HFImageStream stream;
ret = HFCreateImageStreamFromImageBitmap(handle, HF_CAMERA_ROTATION_90, &stream);
REQUIRE(ret == HSUCCEED);
HFSessionCustomParameter parameter = {0};
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
TEST_ERROR_PRINT("error ret :{}", ret);
REQUIRE(ret == HSUCCEED);
// Extract basic face information from photos
HFMultipleFaceData multipleFaceData = {0};
ret = HFExecuteFaceTrack(session, stream, &multipleFaceData);
REQUIRE(ret == HSUCCEED);
REQUIRE(multipleFaceData.detectedNum == 1);
auto rect = multipleFaceData.rects[0];
HColor color = {0, 0, 255};
HFImageBitmapDrawRect(handle, rect, color, 2);
HFImageBitmapWriteToFile(handle, "bitmap_draw_test.jpg");
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageStream(stream);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageBitmap(handle);
REQUIRE(ret == HSUCCEED);
}

View File

@@ -0,0 +1,215 @@
#include <iostream>
#include "settings/test_settings.h"
#include "inspireface/c_api/inspireface.h"
#include <cstdio>
uint8_t* ReadNV21File(const char* filepath, size_t* fileSize) {
FILE* fp = fopen(filepath, "rb");
if (!fp) {
if (fileSize)
*fileSize = 0;
return nullptr;
}
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp);
fseek(fp, 0, SEEK_SET);
uint8_t* data = new uint8_t[size];
size_t read_size = fread(data, 1, size, fp);
fclose(fp);
if (read_size != size) {
delete[] data;
if (fileSize)
*fileSize = 0;
return nullptr;
}
if (fileSize)
*fileSize = size;
return data;
}
TEST_CASE("test_ImageProcessRotateNV21", "[image_process]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
HFImageBitmap originBmp;
size_t fileSize;
uint8_t* data = ReadNV21File(GET_DATA("data/bulk/r0_w330_h409_c3.nv21").c_str(), &fileSize);
REQUIRE(data != nullptr);
HFImageData imageData;
imageData.data = data;
imageData.width = 330;
imageData.height = 409;
imageData.rotation = HF_CAMERA_ROTATION_0;
imageData.format = HF_STREAM_YUV_NV21;
HFImageStream stream;
HResult ret = HFCreateImageStream(&imageData, &stream);
REQUIRE(ret == HSUCCEED);
ret = HFCreateImageBitmapFromImageStreamProcess(stream, &originBmp, 1, 1.0f);
REQUIRE(ret == HSUCCEED);
HFImageBitmapData originData;
ret = HFImageBitmapGetData(originBmp, &originData);
REQUIRE(ret == HSUCCEED);
// compare with eps(0~1)
float eps = 0.01;
SECTION("rotate 90") {
size_t fileSize;
uint8_t* r90nv21 = ReadNV21File(GET_DATA("data/bulk/r90_w409_h330_c3.nv21").c_str(), &fileSize);
REQUIRE(r90nv21 != nullptr);
HFImageData imageData;
imageData.data = r90nv21;
imageData.width = 409;
imageData.height = 330;
imageData.rotation = HF_CAMERA_ROTATION_90;
imageData.format = HF_STREAM_YUV_NV21;
HFImageStream stream;
ret = HFCreateImageStream(&imageData, &stream);
REQUIRE(ret == HSUCCEED);
HFImageBitmap rot90;
ret = HFCreateImageBitmapFromImageStreamProcess(stream, &rot90, 1, 1.0f);
REQUIRE(ret == HSUCCEED);
// HFImageBitmapShow(rot90, "w", 0);
HFImageBitmapData rot90Data;
ret = HFImageBitmapGetData(rot90, &rot90Data);
REQUIRE(ret == HSUCCEED);
REQUIRE_EQ_IMAGE_WITH_EPS(originData.data, rot90Data.data, originData.height, originData.width, originData.channels, eps);
ret = HFReleaseImageBitmap(rot90);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageStream(stream);
REQUIRE(ret == HSUCCEED);
delete[] r90nv21;
}
ret = HFReleaseImageStream(stream);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageBitmap(originBmp);
REQUIRE(ret == HSUCCEED);
delete[] data;
}
TEST_CASE("test_ImageProcessRotate", "[image_process]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
HFImageBitmap originBmp;
HResult ret = HFCreateImageBitmapFromFilePath(GET_DATA("data/bulk/r0.jpg").c_str(), 3, &originBmp);
REQUIRE(ret == HSUCCEED);
HFImageBitmapData originData;
ret = HFImageBitmapGetData(originBmp, &originData);
REQUIRE(ret == HSUCCEED);
// compare with eps(0~1)
float eps = 0.001;
SECTION("rotate 90") {
HFImageBitmap bitmap;
HResult ret = HFCreateImageBitmapFromFilePath(GET_DATA("data/bulk/r90.jpg").c_str(), 3, &bitmap);
REQUIRE(ret == HSUCCEED);
HFImageStream stream;
ret = HFCreateImageStreamFromImageBitmap(bitmap, HF_CAMERA_ROTATION_90, &stream);
REQUIRE(ret == HSUCCEED);
HFImageBitmap rot90;
ret = HFCreateImageBitmapFromImageStreamProcess(stream, &rot90, 1, 1.0f);
REQUIRE(ret == HSUCCEED);
HFImageBitmapData rot90Data;
ret = HFImageBitmapGetData(rot90, &rot90Data);
REQUIRE(ret == HSUCCEED);
REQUIRE_EQ_IMAGE_WITH_EPS(originData.data, rot90Data.data, originData.height, originData.width, originData.channels, eps);
ret = HFReleaseImageBitmap(rot90);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageStream(stream);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageBitmap(bitmap);
REQUIRE(ret == HSUCCEED);
}
SECTION("rotate 180") {
HFImageBitmap bitmap;
HResult ret = HFCreateImageBitmapFromFilePath(GET_DATA("data/bulk/r180.jpg").c_str(), 3, &bitmap);
REQUIRE(ret == HSUCCEED);
HFImageStream stream;
ret = HFCreateImageStreamFromImageBitmap(bitmap, HF_CAMERA_ROTATION_180, &stream);
REQUIRE(ret == HSUCCEED);
HFImageBitmap rot180;
ret = HFCreateImageBitmapFromImageStreamProcess(stream, &rot180, 1, 1.0f);
REQUIRE(ret == HSUCCEED);
HFImageBitmapData rot180Data;
ret = HFImageBitmapGetData(rot180, &rot180Data);
REQUIRE(ret == HSUCCEED);
REQUIRE_EQ_IMAGE_WITH_EPS(originData.data, rot180Data.data, originData.height, originData.width, originData.channels, eps);
ret = HFReleaseImageBitmap(rot180);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageStream(stream);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageBitmap(bitmap);
REQUIRE(ret == HSUCCEED);
}
SECTION("rotate 270") {
HFImageBitmap bitmap;
HResult ret = HFCreateImageBitmapFromFilePath(GET_DATA("data/bulk/r270.jpg").c_str(), 3, &bitmap);
REQUIRE(ret == HSUCCEED);
HFImageStream stream;
ret = HFCreateImageStreamFromImageBitmap(bitmap, HF_CAMERA_ROTATION_270, &stream);
REQUIRE(ret == HSUCCEED);
HFImageBitmap rot270;
ret = HFCreateImageBitmapFromImageStreamProcess(stream, &rot270, 1, 1.0f);
REQUIRE(ret == HSUCCEED);
HFImageBitmapData rot270Data;
ret = HFImageBitmapGetData(rot270, &rot270Data);
REQUIRE(ret == HSUCCEED);
REQUIRE_EQ_IMAGE_WITH_EPS(originData.data, rot270Data.data, originData.height, originData.width, originData.channels, eps);
ret = HFReleaseImageBitmap(rot270);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageStream(stream);
REQUIRE(ret == HSUCCEED);
ret = HFReleaseImageBitmap(bitmap);
REQUIRE(ret == HSUCCEED);
}
ret = HFReleaseImageBitmap(originBmp);
REQUIRE(ret == HSUCCEED);
}

View File

@@ -0,0 +1,153 @@
/**
* Created by Jingyu Yan
* @date 2024-10-01
*/
#include <iostream>
#include "settings/test_settings.h"
#include "inspireface/c_api/inspireface.h"
#include "unit/test_helper/test_help.h"
#include "inspireface/middleware/thread/resource_pool.h"
#include <thread>
TEST_CASE("test_SessionParallel", "[Session][Parallel]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
auto image1 = inspirecv::Image::Create(GET_DATA("data/bulk/kun.jpg"));
auto image2 = inspirecv::Image::Create(GET_DATA("data/bulk/jntm.jpg"));
int loop = 100;
// Run it once to make sure the similarity is stable
HFSessionCustomParameter parameter = {0};
parameter.enable_recognition = 1;
HFDetectMode detMode = HF_DETECT_MODE_ALWAYS_DETECT;
HFSession session;
HResult ret = HFCreateInspireFaceSession(parameter, detMode, 3, -1, -1, &session);
REQUIRE(ret == HSUCCEED);
float expectedSimilarity = GenerateRandomNumbers(1, 0, 100)[0] / 100.0f;
ret = CompareTwoFaces(session, image1, image2, expectedSimilarity);
REQUIRE(ret);
TEST_PRINT("Expected similarity: {}", expectedSimilarity);
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
SECTION("Serial") {
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);
float similarity = 0.0f;
inspirecv::TimeSpend timeSpend("Serial loop: " + std::to_string(loop));
timeSpend.Start();
for (int i = 0; i < loop; ++i) {
ret = CompareTwoFaces(session, image1, image2, similarity);
REQUIRE(ret);
REQUIRE(similarity == Approx(expectedSimilarity).epsilon(0.01));
}
timeSpend.Stop();
std::cout << timeSpend << std::endl;
ret = HFReleaseInspireFaceSession(session);
REQUIRE(ret == HSUCCEED);
}
SECTION("Parallel") {
int N = 4; // Use 4 sessions in parallel
#ifdef ISF_RKNPU_RV1106
N = 1; // Use 1 session in parallel
#endif
inspire::parallel::ResourcePool<HFSession> sessionPool(N, [](HFSession& session) {
auto ret = HFReleaseInspireFaceSession(session);
if (ret != HSUCCEED) {
TEST_ERROR_PRINT("Failed to release session: {}", ret);
}
});
// Example Initialize N sessions to the resource pool
for (int i = 0; i < N; ++i) {
HFSessionCustomParameter parameter = {0};
parameter.enable_recognition = 1;
HFSession session;
HResult ret = HFCreateInspireFaceSession(parameter, HF_DETECT_MODE_ALWAYS_DETECT, 3, -1, -1, &session);
REQUIRE(ret == HSUCCEED);
sessionPool.AddResource(std::move(session));
}
// Create a thread pool to execute a task
std::vector<std::thread> threads;
std::atomic<int> completed(0);
float similaritySum = 0.0f;
std::mutex similarityMutex;
inspirecv::TimeSpend timeSpend("Parallel loop: " + std::to_string(loop) + ", thread: " + std::to_string(N));
timeSpend.Start();
// Start worker thread
int tasksPerThread = loop / N;
int remainingTasks = loop % N;
for (int i = 0; i < N; ++i) {
int taskCount = tasksPerThread + (i < remainingTasks ? 1 : 0);
threads.emplace_back([&, taskCount]() {
for (int j = 0; j < taskCount; ++j) {
auto sessionGuard = sessionPool.AcquireResource();
float similarity = 0.0f;
HResult ret = CompareTwoFaces(*sessionGuard, image1, image2, similarity);
REQUIRE(ret);
REQUIRE(similarity == Approx(expectedSimilarity).epsilon(0.01));
{
std::lock_guard<std::mutex> lock(similarityMutex);
similaritySum += similarity;
}
completed++;
}
});
}
// Wait for all threads to complete
for (auto& thread : threads) {
thread.join();
}
timeSpend.Stop();
std::cout << timeSpend << std::endl;
// Optional: Output average similarity(stability)
TEST_PRINT("Average similarity: {}", (similaritySum / loop));
}
}
TEST_CASE("test_SessionParallel_Memory", "[Session][Parallel][Memory]") {
size_t memoryUsage = getCurrentMemoryUsage();
TEST_PRINT("Current memory usage: {}MB", memoryUsage);
int loop = 4;
#ifdef ISF_RKNPU_RV1106
loop = 1;
#endif
std::vector<HFSession> sessions;
for (int i = 0; i < loop; ++i) {
HFSessionCustomParameter parameter = {0};
parameter.enable_recognition = 1;
HFSession session;
HResult ret = HFCreateInspireFaceSession(parameter, HF_DETECT_MODE_ALWAYS_DETECT, 3, -1, -1, &session);
REQUIRE(ret == HSUCCEED);
sessions.push_back(session);
size_t memoryUsage = getCurrentMemoryUsage();
TEST_PRINT("[alloc{}] Current memory usage: {}MB", i + 1, memoryUsage);
}
// Release all sessions
for (int i = 0; i < loop; ++i) {
auto ret = HFReleaseInspireFaceSession(sessions[i]);
REQUIRE(ret == HSUCCEED);
size_t memoryUsage = getCurrentMemoryUsage();
TEST_PRINT("[free{}] Current memory usage: {}MB", i + 1, memoryUsage);
}
}

View File

@@ -0,0 +1,51 @@
/**
* Created by Jingyu Yan
* @date 2025-01-20
*/
#include <iostream>
#include "settings/test_settings.h"
#include "unit/test_helper/test_help.h"
#include "inspireface/recognition_module/similarity_converter.h"
TEST_CASE("test_similarity_converter", "[similarity_converter]") {
DRAW_SPLIT_LINE
TEST_PRINT_OUTPUT(true);
SECTION("test_similarity_converter_0.42") {
inspire::SimilarityConverterConfig config;
config.threshold = 0.42;
config.middleScore = 0.6;
config.steepness = 8.0;
config.outputMin = 0.01;
config.outputMax = 1.0;
inspire::SimilarityConverter similarity_converter(config);
std::vector<double> test_points = {-0.80, -0.20, 0.02, 0.10, 0.25, 0.30, 0.48, 0.70, 0.80, 0.90, 1.00};
std::vector<double> expected_scores = {0.0101, 0.0201, 0.0661, 0.1113, 0.2819, 0.3673, 0.7074, 0.9334, 0.9689, 0.9858, 0.9936};
REQUIRE(test_points.size() == expected_scores.size());
for (size_t i = 0; i < test_points.size(); ++i) {
double cosine = test_points[i];
double similarity = similarity_converter.convert(cosine);
REQUIRE(similarity == Approx(expected_scores[i]).epsilon(0.01));
}
}
SECTION("test_similarity_converter_0.32") {
inspire::SimilarityConverterConfig config;
config.threshold = 0.32;
config.middleScore = 0.6;
config.steepness = 10.0;
config.outputMin = 0.02;
config.outputMax = 1.0;
inspire::SimilarityConverter similarity_converter(config);
std::vector<double> test_points = {-0.80, -0.20, 0.02, 0.10, 0.25, 0.32, 0.50, 0.70, 0.80, 0.90, 1.00};
std::vector<double> expected_scores = {0.0200, 0.0278, 0.0860, 0.1557, 0.4302, 0.6000, 0.8997, 0.9851, 0.9945, 0.9980, 0.9992};
REQUIRE(test_points.size() == expected_scores.size());
for (size_t i = 0; i < test_points.size(); ++i) {
double cosine = test_points[i];
double similarity = similarity_converter.convert(cosine);
REQUIRE(similarity == Approx(expected_scores[i]).epsilon(0.01));
}
}
}

View File

@@ -1,3 +1,4 @@
#if 0
#include <iostream>
#include "settings/test_settings.h"
#include "inspireface/c_api/inspireface.h"
@@ -265,4 +266,6 @@ TEST_CASE("test_SystemStreamReleaseCase", "[system]") {
REQUIRE(ret == HSUCCEED);
REQUIRE(count == 0);
}
}
}
#endif