人脸识别base64解码及相似度计算C++

人脸特征向量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);
        }
       }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值