人脸特征向量base64解码
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
#include <unistd.h>
#include <thread>
#include <nlohmann/json.hpp>
#include <fstream>
#include <experimental/filesystem>
//base64解码
// // // Base64字符映射表
// static const std::string base64_chars =
// "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// "abcdefghijklmnopqrstuvwxyz"
// "0123456789+/";
// Base64字符映射表
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// 检查字符是否是Base64字符
bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
// Base64解码函数
std::string base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j < 4; j++)
char_array_4[j] = 0;
for (j = 0; j < 4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
函数调用(以512维人脸特征举例,std::string feature为base64编码的人脸特征向量字符串)
decoded_string = base64_decode(feature);
// decoded_string2 = base64_decode(featuer_string2);
float buf[512];
// float buf2[512];
std::memcpy(buf, decoded_string.data(), sizeof(buf));
// std::memcpy(buf2, decoded_string2.data(), sizeof(buf2));
// 创建一个空的向量来保存数组元素
std::vector<float> decoded_vec1;
// std::vector<float> decoded_vec2;
std::cout << "[" ;
for (int i = 0; i < 512; ++i) {
std::cout << buf[i] << ", ";
decoded_vec1.push_back(buf[i]);
}
std::cout << "]" << std::endl;
for (float value : decoded_vec1) {
std::cout << value << ' ';
}
std::cout << std::endl;
计算相似度
// 计算两个向量的点积
double dotProduct(const std::vector<float>& vec1, const std::vector<float>& vec2) {
double product = 0.0;
for (size_t i = 0; i < vec1.size(); ++i) {
product += vec1[i] * vec2[i];
}
return product;
}
// 计算向量的模
double magnitude(const std::vector<float>& vec) {
double sum = 0.0;
for (float val : vec) {
sum += val * val;
}
return std::sqrt(sum);
}
// 计算余弦相似度
double cosineSimilarity(const std::vector<float>& vec1, const std::vector<float>& vec2) {
double product = dotProduct(vec1, vec2);
double magVec1 = magnitude(vec1);
std::cout<<"magVec1:" << magVec1<< std::endl;
double magVec2 = magnitude(vec2);
std::cout<<"magVec2:" << magVec2<< std::endl;
return product / (magVec1 * magVec2);
}
调用,解码人脸特征向量和人脸数据库比对相似度
double similarity = cosineSimilarity(decoded_vec1, feature_vector["vector"])
将识别结果图进行编码,然后通过http协议送出
#include <curl/curl.h>
// 用于libcurl的写数据回调函数
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
// Base64编码函数
std::string base64_encode(const std::vector<uchar>& buffer) {
std::string out;
int val = 0, valb = -6;
for (uchar c : buffer) {
val = (val << 8) + c;
valb += 8;
while (valb >= 0) {
out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val >> valb) & 0x3F]);
valb -= 6;
}
}
if (valb > -6) out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val << 8) >> (valb + 8)) & 0x3F]);
while (out.size() % 4) out.push_back('=');
return out;
}
// 初始化libcurl
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
// 设置目标URL
curl_easy_setopt(curl, CURLOPT_URL, "your url");
// 忽略证书验证
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
// 将OpenCV Mat转换为vector<uchar>
std::vector<uchar> buf;
cv::imencode(".jpg", img, buf);
// 编码为Base64
std::string encoded_string = base64_encode(buf);
// 构建JSON数据
json json_post;
json_post["method"] = "reportEvent";
json_post["params"]["ability"] = "alarm_notification";
json_post["params"]["events"] = json::array({{
{"eventId", "event123"},
{"eventType", "fire_alarm"},
{"happenTime", "2024-10-22T14:00:00Z"},
{"picBase64", encoded_string},
{"srcIndex", "sensor001"},
{"srcType", "smoke_detector"},
{"status", 1},
{"stopTime", "2024-10-22T14:10:00Z"}
}});
json_post["params"]["sendTime"] = "2024-10-22T14:15:00Z";
// 将JSON数据转换为字符串
std::string json_data_post = json_post.dump();
// 设置HTTP头部信息
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// 设置POST数据
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data_post.c_str());
// 设置写数据回调函数
std::string readBuffer;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
// 启用 verbose 选项以获得详细的调试信息
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// 执行HTTP请求
res = curl_easy_perform(curl);
// 检查错误
if(res != CURLE_OK) {
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
} else {
// 打印响应内容
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
std::cout << "HTTP status code: " << http_code << std::endl;
std::cout << "Response body: " << readBuffer << std::endl;
}
// 清理
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
}
判断非空数据,并建立对象保存数组
if (!Person_data.empty()){
// 要保存图片的路径
std::string outputFolderPath = "/output/";
std::string outputImageName2 = std::to_string(frameCount) + "_.jpg";
// 指定输出图片的完整路径
std::string outputImagePath = outputFolderPath + outputImageName2;
// 保存图片
bool isSuccess = cv::imwrite(outputImagePath, img);
//post发送数据
// 初始化libcurl
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
// 设置目标URL
curl_easy_setopt(curl, CURLOPT_URL, "your url");
// 忽略证书验证
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
// 将OpenCV Mat转换为vector<uchar>
std::vector<uchar> buf;
cv::imencode(".jpg", img, buf);
// 编码为Base64
std::string encoded_string = base64_encode(buf);
std::string img_Index = std::to_string(frameCount);
// 获取当前时间
std::time_t end = std::time(nullptr);
// 使用localtime将time_t转换为tm结构体,以便格式化
std::tm* local_Now = std::localtime(&end);
// 使用ostringstream进行字符串格式化
std::ostringstream oss_end;
oss_end << std::put_time(local_Now, "%Y-%m-%dT%H:%M:%S+08:00");
// 输出格式化后的时间字符串
std::string end_timeString = oss_end.str();
std::cout << "End time: " << end_timeString << std::endl;
std::cout << "timeString: " << timeString << std::endl;
using json = nlohmann::json;
// // 创建一个 JSON 数组
// json j_Person_data = json::array();
// // 遍历 vector 并将每个 PersonData 结构转换为 JSON 对象
// for (const auto& person : Person_data) {
// j_Person_data.push_back({
// {"personId", person.personId},
// {"score", person.score}
// });
// }
// 创建一个 JSON 对象来保存 persons 数组
nlohmann::json j_Person_data = nlohmann::json::object(); // 使用对象而不是数组
nlohmann::json j_persons = nlohmann::json::array(); // 创建一个 JSON 数组来保存 persons
// 遍历 vector 并将每个 PersonData 结构转换为 JSON 对象
for (const auto& person : Person_data) {
j_persons.push_back({
{"personId", person.personId},
{"score", person.score}
});
}
// 将 persons 数组添加到 j_Person_data 对象中
j_Person_data["persons"] = j_persons;
// 输出 JSON 字符串
std::cout << j_Person_data.dump(4) << std::endl; // 使用 4 个空格缩进
// 构建JSON数据
json json_post;
json_post["method"] = "OnEventNotify";
json_post["params"]["ability"] = "None";
json_post["params"]["events"] = json::array({{
{"eventId", "event123"},
{"eventType", "personnelFall"},
{"happenTime", timeString},
{"picBase64", encoded_string},
{"srcIndex", img_Index},
{"srcType", "base64"},
{"status", 1},
{"stopTime", end_timeString},
{"videoUrl", "None"},
{"data", j_Person_data}
}});
json_post["params"]["sendTime"] = end_timeString;
// 将JSON数据转换为字符串
std::string json_data_post = json_post.dump();
// 设置HTTP头部信息
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// 设置POST数据
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data_post.c_str());
// 设置写数据回调函数
std::string readBuffer;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
// 启用 verbose 选项以获得详细的调试信息
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// 执行HTTP请求
res = curl_easy_perform(curl);
// 检查错误
if(res != CURLE_OK) {
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
} else {
// 打印响应内容
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
std::cout << "HTTP status code: " << http_code << std::endl;
std::cout << "Response body: " << readBuffer << std::endl;
}
// 清理
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
}
}