from:
c++ 解析从浏览器端传过来的图像base64编码,并转换成opencv识别的格式
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "opencv2/core/core.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include <b64/encode.h>
#include <b64/decode.h>
#include "face_detection.h"
using namespace cv;
using namespace std;
cv::Mat img_gray;
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static inline bool is_base64(unsigned char c)
{
return (isalnum(c) || (c == '+') || (c == '/'));
}
Mat deserialize(std::stringstream& input)
{ // The data we need to deserialize int width = 0;
int height = 0;
int type = 0;
size_t size = 0; // Read the width, height, type and size of the buffer
input.read((char*)(&width), sizeof(int));
input.read((char*)(&height), sizeof(int));
input.read((char*)(&type), sizeof(int));
input.read((char*)(&size), sizeof(size_t)); // Allocate a buffer for the pixels
char* data = new char[size]; // Read the pixels from the stringstream
input.read(data, size); // Construct the image (clone it so that it won't need our buffer anymore)
Mat m = Mat(height, width, type, data).clone(); // Delete our buffer
delete[]data; // Return the matrix
return m;
}
Mat getFaceRec(Mat img, seeta::FaceDetection *detector)
{
if (img.channels() != 1)
cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
else
img_gray = img;
seeta::ImageData img_data;
img_data.data = img_gray.data;
img_data.width = img_gray.cols;
img_data.height = img_gray.rows;
img_data.num_channels = 1;
std::vector<seeta::FaceInfo> faces = detector->Detect(img_data);
cv::Rect face_rect;
int32_t num_face = static_cast<int32_t>(faces.size());
for (int32_t i = 0; i < num_face; i++)
{
face_rect.x = faces[i].bbox.x;
face_rect.y = faces[i].bbox.y;
face_rect.width = faces[i].bbox.width;
face_rect.height = faces[i].bbox.height;
cv::rectangle(img, face_rect, CV_RGB(0, 0, 255), 4, 8, 0);
}
return img;
}
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;
}
void getBBoxOfFace(string path,char* modelPath)
{
seeta::FaceDetection *detector = new seeta::FaceDetection(modelPath);
detector->SetMinFaceSize(40); detector->SetScoreThresh(2.f);
detector->SetImagePyramidScaleFactor(0.8f); detector->SetWindowStep(4, 4);
Mat img = cv::imread(path);
if (img.channels() != 1)
cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
else
img_gray = img;
seeta::ImageData img_data;
img_data.data = img_gray.data;
img_data.width = img_gray.cols;
img_data.height = img_gray.rows;
img_data.num_channels = 1;
std::vector<seeta::FaceInfo> faces = detector->Detect(img_data);
cv::Rect face_rect;
int32_t num_face = static_cast<int32_t>(faces.size());
for (int32_t i = 0; i < num_face; i++)
{
face_rect.x = faces[i].bbox.x;
face_rect.y = faces[i].bbox.y;
face_rect.width = faces[i].bbox.width;
face_rect.height = faces[i].bbox.height;
cout<<face_rect.x<<","<<face_rect.y<<","<<face_rect.width<<","<<face_rect.height<<endl; //cv::rectangle(img, face_rect, CV_RGB(0, 0, 255), 4, 8, 0);
}
}
void seetaFaceDetectorByBase64Path(string path,char* modelPath)
{
seeta::FaceDetection *detector = new seeta::FaceDetection(modelPath);
detector->SetMinFaceSize(40); detector->SetScoreThresh(2.f);
detector->SetImagePyramidScaleFactor(0.8f);
detector->SetWindowStep(4, 4);
base64::decoder D;
std::ifstream fin(path);
std::string strRs;
std::string str;
while (fin)
{
fin >> str;
strRs += str;
}
/* std::stringstream decoded;
std::stringstream ss(strRs);
D.decode(ss, decoded); //base64解密
Mat img = deserialize(decoded); //反序列化
*/
std::string decoded_string = base64_decode(strRs);
std::vector<uchar> data(decoded_string.begin(), decoded_string.end());
Mat img = imdecode(data, IMREAD_UNCHANGED);
//cv::imshow("img",img);
//cv::waitKey(0);
//检测人脸
if (img.channels() != 1)
cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
else
img_gray = img;
seeta::ImageData img_data;
img_data.data = img_gray.data;
img_data.width = img_gray.cols;
img_data.height = img_gray.rows;
img_data.num_channels = 1;
std::vector<seeta::FaceInfo> faces = detector->Detect(img_data);
cv::Rect face_rect;
int32_t num_face = static_cast<int32_t>(faces.size());
for (int32_t i = 0; i < num_face; i++)
{
face_rect.x = faces[i].bbox.x;
face_rect.y = faces[i].bbox.y;
face_rect.width = faces[i].bbox.width;
face_rect.height = faces[i].bbox.height;
cout<<face_rect.x<<","<<face_rect.y<<","<<face_rect.width<<","<<face_rect.height<<endl;
//cv::rectangle(img, face_rect, CV_RGB(0, 0, 255), 4, 8, 0);
}
}
void seetaFaceDetectorByBase64Str(string encoded_string,char* modelPath)
{
seeta::FaceDetection *detector = new seeta::FaceDetection(modelPath);
detector->SetMinFaceSize(40);
detector->SetScoreThresh(2.f);
detector->SetImagePyramidScaleFactor(0.8f);
detector->SetWindowStep(4, 4);
base64::decoder D;
std::string decoded_string = base64_decode(encoded_string);
std::vector<uchar> data(decoded_string.begin(), decoded_string.end());
Mat img = imdecode(data, IMREAD_UNCHANGED);
//cv::imshow("img",img);
//cv::waitKey(0);
//检测人脸
if (img.channels() != 1)
cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
else
img_gray = img;
seeta::ImageData img_data;
img_data.data = img_gray.data;
img_data.width = img_gray.cols;
img_data.height = img_gray.rows;
img_data.num_channels = 1;
std::vector<seeta::FaceInfo> faces = detector->Detect(img_data);
cv::Rect face_rect;
int32_t num_face = static_cast<int32_t>(faces.size());
for (int32_t i = 0; i < num_face; i++)
{
face_rect.x = faces[i].bbox.x;
face_rect.y = faces[i].bbox.y;
face_rect.width = faces[i].bbox.width;
face_rect.height = faces[i].bbox.height;
cout<<face_rect.x<<","<<face_rect.y<<","<<face_rect.width<<","<<face_rect.height<<endl;
//cv::rectangle(img, face_rect, CV_RGB(0, 0, 255), 4, 8, 0);
}
}
int main(int argc, char** argv)
{
//视频路径 模型路径
if(argc != 3)
{
std::cout<<"argument fault"<<std::endl;
return 0;
}
//getBBoxOfFace(argv[1],argv[2]);
seetaFaceDetectorByBase64Str(argv[1],argv[2]);
/* Mat frame;
char path[100];
int count = 0;
seeta::FaceDetection *detector = new seeta::FaceDetection(argv[2]);
detector->SetMinFaceSize(40);
detector->SetScoreThresh(2.f);
detector->SetImagePyramidScaleFactor(0.8f);
detector->SetWindowStep(4, 4);
getBBoxOfFace(string path,string modelPath);
VideoCapture capture(argv[1]);
while(true)
{
capture >> frame;
//获得了最后一帧
if(frame.empty()) { break; }
frame = getFaceRec(frame,detector);
sprintf(path,"/home/lgf/ext_data/videoFace/%d.jpg",count++);
cv2.imwrite(path,) cv::namedWindow("SeetaFaceDetect", cv::WINDOW_AUTOSIZE);
cv::imshow("Test", frame);
cv::waitKey(1);
}
cv::destroyAllWindows();
*/
}