概述
另一篇比较好的博客:https://blog.csdn.net/weixin_42731241/article/details/81775571
一般进行图片传输时,先用openCV把图片转换为Mat,然后封装到json当中,然后再从json中解析出来。这次是客户端向服务端传输。
Ps:客户端第一次发送一张图片,第二次发送两张图片,后面依次循环,转成Mat封装到json中,服务端接收并解析,如果是一张图片生成名称和相似度,如果是两张只生成相似度,封装到json,并返回至客户端(用于人脸识别的,读者可以根据自己的需要改动)
客户端:图片转换为Mat用imread即可,然后Mat通过imencode函数转为uchar*,再转换为string类型,然后通过c_str()函数转换为const char*,最后Base64编码存到json里面(我找的Base64.h编码只能用这个数据类型,所以这个转换数据类型卡了我很长时间,关键还是对数据类型不熟悉)
服务端:json里面的数据进行Base64解码成string,然后转换为uchar*,再通过imdecode转换成Mat,最后imshow显示或者imwrite保存(相当于客户端的逆过程)
openCV的配置过程在之前的博客中
json.hpp 下载地址https://github.com/nlohmann/json/tree/develop/include/nlohmann
一.服务端
#include <iostream>
#include <stdio.h>
#include "Base64.h"
#include <winsock2.h>
#include "json1.hpp"
#include <opencv2/opencv.hpp>
#pragma comment(lib,"ws2_32.lib")
using namespace cv;
using json = nlohmann::json;
char revData[3888888];
int main(int argc, char* argv[])
{
//初始化WSA
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0)
{
return 0;
}
//创建套接字
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
printf("socket error !");
return 0;
}
//绑定IP和端口
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("bind error !");
}
//开始监听
if (listen(slisten, 5) == SOCKET_ERROR)
{
printf("listen error !");
return 0;
}
//循环接收数据
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
//revData = (char*)malloc(sizeof(char) * 1000000);
int i = 1;
while (true)
{
printf("等待连接...n");
sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
if (sClient == INVALID_SOCKET)
{
printf("accept error !");
continue;
}
printf("接受到一个连接:%s rn", inet_ntoa(remoteAddr.sin_addr));
int k = 1;
while (true)
{
//接收数据
int ret = recv(sClient, revData, 3888888, 0);
if (ret > 0)
{
revData[ret] = 0x00;
json o = json::parse(revData);
json j;
for (json::iterator it = o.begin(); it != o.end(); ++it)
{
if (it.key() == "mat1")
{
Mat img_decode;
std::string str_tmp = base64_decode(it.value());
std::vector<uchar> data(str_tmp.begin(), str_tmp.end());
img_decode = imdecode(data, CV_LOAD_IMAGE_COLOR);
imshow("pic", img_decode);
std::string num = std::to_string(k);
imwrite("D:\" + num + ".jpg", img_decode);
k++;
waitKey(10);
}
else if (it.key() == "mat2")
{
if (it.value() == "")
{
j["name"] = "";
j["similarity"] = "";
}
else
{
Mat img_decode;
std::string str_tmp = base64_decode(it.value());
std::vector<uchar> data(str_tmp.begin(), str_tmp.end());
img_decode = imdecode(data, CV_LOAD_IMAGE_COLOR);
imshow("pic", img_decode);
std::string num = std::to_string(k);
imwrite("D:\" + num + ".jpg", img_decode);
k++;
waitKey(10);
j["similarity"] = "";
}
}
}
//std::cout<< json::parse(revData)<< std::endl;
//printf(revData);
std::string s = j.dump();
const char * sendData;
sendData = s.c_str();
//const char * sendData = "你好,TCP客户端!n";
send(sClient, sendData, strlen(sendData), 0);
}
//发送数据
}
}
closesocket(sClient);
closesocket(slisten);
WSACleanup();
return 0;
}
Base64.h
#ifndef __BASE64_H__
#define __BASE64_H__
#include <iostream>
#include <string>
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(const char c)
{
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(const char * bytes_to_encode, unsigned int in_len)
{
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--)
{
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3)
{
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i <4); i++)
{
ret += base64_chars[char_array_4[i]];
}
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
{
char_array_3[j] = '