linux c++ 与python之间使用tcp传输图片并返回结果
客户端为 c++,服务端为python客户端可参考:https://blog.csdn.net/qq_31511955/article/details/94580915json库地址:https://github.com/nlohmann/json/tree/develop/include/nlohmann需要一个第三方的json库,主要流程为:图片用imread转换为Mat,然后Ma...
客户端为 c++,服务端为python
客户端可参考:https://blog.csdn.net/qq_31511955/article/details/94580915
json库地址:https://github.com/nlohmann/json/tree/develop/include/nlohmann
需要一个第三方的json库,主要流程为:图片用imread转换为Mat,然后Mat通过imencode函数转为uchar*,再转换为string类型,然后通过c_str()函数转换为const char*,最后Base64编码存到json里面
客户端代码:
#include "myTcp.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "base64.h"
#include "json.hpp"
using namespace std;
using namespace cv;
using json = nlohmann::json;
int main()
{
json j;
const char* c;
Mat image = imread("./1.jpg", IMREAD_UNCHANGED);
if (image.empty())
{
cout<<"read image failed \n";
return -1;
}
else
cout<<"read successful!\n";
vector<unsigned char> data_encode;
int res = imencode(".jpg", image, data_encode);
string str_encode(data_encode.begin(), data_encode.end());
c = str_encode.c_str();
j["mat"] = base64_encode(c, str_encode.size());
string s = j["mat"].dump();
const char * sendData;
sendData = s.c_str();
TCPclient tcp;
if(tcp.connect_Server("127.0.0.1", 6789))
cout<<"connect successful!\n";
else
cout<<"connect failed\n";
int length = strlen(sendData);
cout << tcp.Send((char*)&length, sizeof(int)) << endl;
cout << tcp.Send((char*)sendData, length) << endl;
char strbuffer[10240] = {0};
int ret = tcp.Recv(strbuffer, sizeof(strbuffer));
if(ret <= 0)
{
return -1;
}
string result = string(strbuffer);
cout<<"recv: " << ret << " " << result << endl;
return 0;
}
服务端:
#识别服务
import socketserver
import threading
from queue import Queue
import cv2
import json
import base64
import numpy as np
HOST = '127.0.0.1'
PORT = 6789
ADDR = (HOST, PORT)
class msgRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
print ('connected from.....', self.client_address)
while True:
head = self.request.recv(4)
data = bytearray(head)
#获取图片大小
msgLen = int.from_bytes(data, byteorder='little')
print('msg len is %d' %(msgLen))
#获取图片
curSize = 0
allData = b''
while curSize < msgLen:
data = self.request.recv(1024)
allData += data
curSize += len(data)
print("recv data len is ", len(allData))
img = json.loads(allData)
#解码保存
imgDecode = base64.b64decode(img)
#保存图片
fImg = open('2.jpg', 'wb')
fImg.write(imgDecode)
fImg.close()
print("save img...\n")
#mmdetection 识别,返回识别结果
result = [[1,2,3,4], [5,6,7,8], [6,6,6,6], [1,2,3,4]];
jsonResult = json.dumps(result)
print(jsonResult)
socket = self.request
print(socket)
#发送回去
arrResult = bytearray(jsonResult.encode('utf-8'))
socket.sendall(arrResult)
print('send done.')
socket.close()
print('\n')
break;
if __name__ == "__main__":
tcpServ = socketserver.ThreadingTCPServer(ADDR, msgRequestHandler)
print ('waiting for connection...')
tcpServ.serve_forever()
others:
封装的tcp类:可参考:https://blog.csdn.net/PPprogrammer/article/details/103018358
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <iostream>
using namespace std;
class TCPclient
{
public:
TCPclient()
{
sock_clientfp=0;
}
~TCPclient()
{
if(sock_clientfp > 0 )
{
close(sock_clientfp);
}
}
public:
bool connect_Server(const char *serverIP,int port);
ssize_t Send(const void *buf, size_t len);
ssize_t Recv(void *buf, size_t len);
private:
int sock_clientfp;
};
bool TCPclient::connect_Server(const char *serverIP,int port)
{
sock_clientfp = socket(AF_INET,SOCK_STREAM,0);
struct hostent *h;
if((h = gethostbyname(serverIP)) == 0)
{
close(sock_clientfp);
sock_clientfp = 0;
return false;
}
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
memcpy(&servaddr.sin_addr,h->h_addr,h->h_length);
if(connect(sock_clientfp,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0)
{
close(sock_clientfp);
sock_clientfp = 0;
return false;
}
return true;
}
ssize_t TCPclient::Send(const void *buf, size_t len)
{
return send(sock_clientfp, buf,len,0);
}
ssize_t TCPclient::Recv(void *buf, size_t len)
{
memset(buf,0,len);
return recv(sock_clientfp, buf,len,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] = '\0';
}
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 (j = 0; (j < i + 1); j++)
{
ret += base64_chars[char_array_4[j]];
}
while ((i++ < 3))
{
ret += '=';
}
}
return ret;
}
std::string base64_decode(std::string const & encoded_string)
{
int in_len = (int)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;
}
#endif
另外客户端在linux下用g++编译时,json库要用 c++11标准编译,别忘了指定opencv库和头文件目录、json头文件目录
g++ -std=c++11 client.cpp `pkg-config --cflags --libs opencv` -I/mnt/data/myTest/ -o client
在测试时,我是在docker里测的,在同一个bash里测试比较麻烦,需要将服务器切到后台操作。这里建议复制一份bash,然后在新bash里进入到同一个docker里
sudo docker exec -it ceb4147fafda /bin/bash
一个问题:这里将接收到的图片保存到本地时图片大小变大了,但是肉眼看不出来变化,中间出现的问题待解决...
更多推荐
所有评论(0)