std::string detectNet::Mat2Base64(const cv::Mat &image, std::string imgType){
std::vector buf;
cv::imencode(imgType, image, buf);
//uchar *enc_msg = reinterpret_cast(buf.data());
std::string img_data = base64_encode(buf.data(), buf.size(), false);
return img_data;
}
void detectNet::send_json_people(cv::Mat img, std::string label, std::string level, std::string rtsp){
std::string out = Mat2Base64(img,".jpg");
//std::cout << out << std::endl;
ImgInfo imgInfo(out, label, level, rtsp);
static auto client = httplib::Client("127.0.0.1", 18080);
auto result = client.Post("/uploadAlgorithmResult", imgInfo.to_json_people(), "application/json");
if (result != nullptr && result->status == 200) {
std::cout << result->body << std::endl;
}
}
其中 ImgInfo 类为:
#ifndef HTTP_DEMO_IMGINFO_H
#define HTTP_DEMO_IMGINFO_H
#include
#include "cJSON.h"
#include "base64.h"
#define RTSP_URL "rtsp://admin:[email protected]:554/h264/ch1/main/av_stream/1"
#define AlgorithmType "hook_detection"
#define AlgorithmType_people "danger_zone"
#define AlgorithmType_crooked "crooked"
class ImgInfo {
private:
std::string img;
std::string label;
std::string rtsp;
std::string level;
public:
ImgInfo(std::string img, std::string label,
std::string level, std::string rtsp) : img(std::move(img)), label(std::move(label)),
level(std::move(level)), rtsp(std::move(rtsp)) {}
std::string to_json_people() {
auto *root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "image", img.c_str());
cJSON_AddStringToObject(root, "level", level.c_str());
cJSON_AddStringToObject(root, "rtsp", rtsp.c_str());
cJSON_AddStringToObject(root, "type", AlgorithmType_people);
cJSON_AddStringToObject(root, "label", label.c_str());
/*
cJSON *label_array = cJSON_CreateArray();
for (auto &i: label) {
cJSON_AddItemToArray(label_array, cJSON_CreateString(i.c_str()));
}
cJSON_AddItemToObject(root, "label", label_array);
*/
char *out = cJSON_Print(root);
std::string res = out;
free(out);
cJSON_Delete(root);
return res;
}
};
#endif //HTTP_DEMO_IMGINFO_H
上述代码中json数据有五个部分:image为图片数据,level是告警等级,rtsp为数据流地址,type是算法类型,label是算法标签等,所以数据发送为这五个内容。
HttpServer.cpp如下:
//#include
//#include
#include "HttpServer.h"
#include
#include
//#include "QString"
//#include "TimeUtils.hpp"
//#include "AlgorithmCommon.h"
//#include "QJsonObject"
//#include "QJsonDocument"
//#include "QJsonArray"
//#include "httplib.h"
//#include "log.h"
//#include "cJSON.h"
HttpServer::HttpServer(std::string ip, int port) : server_ip(ip), server_port(port) {
//event_handler = new AlgorithmAlarmHandler();
}
HttpServer::~HttpServer() {
stopListen();
if (read_thd.joinable()) {
read_thd.join();
}
}
void HttpServer::startListen() {
read_thd = std::thread([=]() {
serverListen();
});
//event_handler->startHandlerThread();
}
void HttpServer::stopListen() {
if (server.is_running()) {
server.stop();
}
}
void HttpServer::serverListen() {
if (!server.is_valid()) {
std::cout << "http server invalid" << std::endl;
return;
}
// 服务器状态
server.Get("/server/status", [&](const Request &req, Response &res) {
onServerStatus(req, res);
});
// 上传算法结果
server.Post("/uploadAlgorithmResult", [&](const Request &req, Response &res) {
onUploadAlgorithmResult(req, res);
});
// 错误处理
server.set_error_handler([&](const Request &req, Response &res) {
onErrorHandle(req, res);
});
//qDebug() << "server start listen";
server.listen(server_ip.c_str(), server_port);
}
void HttpServer::onServerStatus(const httplib::Request &req, httplib::Response &res) {
res.body = R"({"code": 200,"msg": "Server is already Running"})";
}
void HttpServer::onUploadAlgorithmResult(const httplib::Request &req, httplib::Response &res) {
std::string content_type = httputillib::GetContentType(req.headers);
//if (content_type != "application/json") {
// qDebug() << "contentType 异常, content_type:" << QString::fromStdString(content_type);
//}
bool parseRet = parseAlgorithmResult(req.body);
//bool parseRet = true;
std::string rspMsg;
if (parseRet) {
rspMsg = std::string(R"({"msg":"Recv Success, Parse Success."})");
} else {
rspMsg = std::string(R"({"msg":"Recv Success, Parse Failed."})");
}
res.body = std::move(rspMsg);
}
// 错误请求处理
void HttpServer::onErrorHandle(const httplib::Request &req, httplib::Response &res) {
const char *fmt = {"\"error\": \"服务器不支持该方法\""};
char buf[BUFSIZ] = {0};
snprintf(buf, sizeof(buf), fmt, res.status);
res.set_content(buf, "application/json");
}
bool HttpServer::parseAlgorithmResult(const std::string &body) {
//std::cout << "body:" << body << std::endl;
Json::Reader reader;
Json::Value root;
//std::ifstream in(body, std::ios::binary);
//if (!in.is_open()) {
// std::cout << "open file failed" << std::endl;
// return false;
//}
if (!reader.parse(body, root)) {
std::cout << "parse failed" << std::endl;
return false;
}
std::string rtsp = root["rtsp"].asString();
std::cout << "rtsp:" << rtsp << std::endl;
std::string level = root["level"].asString();
std::cout << "level:" << level << std::endl;
std::string type = root["type"].asString();
std::cout << "type:" << type << std::endl;
std::string image = root["image"].asString();
//std::cout << "image:" << image << std::endl;
std::string out = base64_decode(image);
std::string decoded_jpeg = std::move(out);
//std::cout << "decoded_jpeg: " << decoded_jpeg << std::endl;
cv::Mat mat2(1, decoded_jpeg.size(), CV_8U, (char*)decoded_jpeg.data());
cv::Mat dst = cv::imdecode(mat2, CV_LOAD_IMAGE_COLOR);
cv::imwrite(rtsp.substr(1) + ".jpg", dst);
return true;
}
HttpServer.h如下:
//#ifndef CPPHTTPSERVER_HTTPSERVER_H
//#define CPPHTTPSERVER_HTTPSERVER_H
#include "httputillib.h"
#include "httplib.h"
#include "base64.h"
//#include "thread"
#include
#include
#include
class HttpServer{
public:
HttpServer(std::string ip, int port);
~HttpServer();
void startListen();
void stopListen();
private:
void serverListen();
// 回调函数: 错误请求处理
void onErrorHandle(const httplib::Request &req, httplib::Response &res);
// 回调函数: 获取服务器状态
void onServerStatus(const httplib::Request &req, httplib::Response &res);
// 回调函数: 上传算法结果
void onUploadAlgorithmResult(const httplib::Request &req, httplib::Response &res);
// 回调函数:处理算法数据
bool parseAlgorithmResult(const std::string &body);
std::string server_ip;
int server_port;
Server server;
std::thread read_thd;
};
//#endif //CPPHTTPLIB_HTTPLIB_H
httputillib.h如下:
#include
using namespace httplib;
namespace httputillib {
// 打印请求头
static std::string DumpHeaders(const Headers &headers) {
std::string s;
char buf[BUFSIZ] = {0};
for (auto it = headers.begin(); it != headers.end(); ++it) {
const auto &x = *it;
snprintf(buf, sizeof(buf), "%s: %s\n", x.first.c_str(), x.second.c_str());
s += buf;
}
return s;
}
// 从请求同获取content type
static std::string GetContentType(const httplib::Headers &headers) {
auto iter = headers.find("Content-Type");
if (iter == headers.end()) {
return std::string();
}
return iter->second;
}
};
上述完整代码可详见github或者百度网盘