背景
做到项目涉及到c++与python进行混合编程,c++向python传递图像进行处理,python处理结束后在返回结果。对于这两种语言的通信问题,一直让我头疼。试了试socket通信,进行图像传输。废话不多说。
环境
win10+vs2015+opencv3.4+python3.5
代码
以下只是关键代码,读者根据实际情况,自行裁剪哈
C++端(客户端)
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <iostream>
#include <opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
#define BuffSize 1024
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
return -1;
}
if (LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1) {
WSACleanup();
return -1;
}
Mat imgSrc = imread("K:/home.jpg", IMREAD_UNCHANGED);
if (imgSrc.empty())
{
return -1;
}
Mat img;
img.create(imgSrc.size(), imgSrc.type());
img = imgSrc.clone();
int totalNum = img.rows*img.cols*img.elemSize();
while (true)
{
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//本机
//addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.107");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(8888);
int sec = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
if (SOCKET_ERROR == sec)
{
continue;
}
char* pos = (char*)img.data;
int colByte = img.cols*img.channels() * sizeof(uchar);
for (int i = 0; i<img.rows; i++)
{
char* data = (char*)img.ptr<uchar>(i); //第i行首地址
int sedNum = 0;
char buf[BuffSize] = { 0 };
//按行拆分,发送数据
while (sedNum < colByte)
{
int sed = (BuffSize < colByte - sedNum) ? BuffSize : (colByte - sedNum);
memcpy(buf, &data[sedNum], sed);
int SendSize = send(sockClient, buf, sed, 0);
if (SOCKET_ERROR == SendSize)
return -1;
/*else
cout << SendSize << endl;*/
sedNum += SendSize;
}
}
char recvBuf[50];
int ns = recv(sockClient, recvBuf, 50, 0);
recvBuf[ns] = '\0';
printf("severRecv %s\n", recvBuf);
Sleep(5);
char t[2];
std::cin >> t;
}
WSACleanup();
getchar();
return 0;
}
Python端(服务端)
import numpy as np
import socket
import time
from PIL import Image
import cv2
# 图像尺寸
wid = 512
hig = 384
channels = 3
def recvall(sock, count):
buf = b''
while count:
newbuf = sock.recv(count)
if not newbuf: return None
buf += newbuf
count -= len(newbuf)
return buf
if __name__ == '__main__':
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 8888))
server.listen(0)
totleNum = wid * hig * channels; # 总共多少数据
while True:
connection, address = server.accept()
print(connection, address)
stringData = recvall(connection, int(totleNum))
data = np.fromstring(stringData, dtype='uint8')
print(len(data))
# 解析数据
#方法一
Array = data.reshape(hig, wid, channels)
im = Image.fromarray(Array)
im.save("out.jpeg")
im.show("test")
# 方法二
# decimg = np.zeros((hig, wid, channels), np.uint8)
# for i in range(0, hig):
# for j in range(0, wid):
# for k in range(0, channels):
# decimg[i][j][k] = data[(i * wid + j) * channels + k]
#
# # cv2.imwrite('.\SERVER.jpg', decimg)
# cv2.namedWindow("test", 0)
# cv2.imshow("test", decimg)
# cv2.waitKey(0)
connection.send(bytes("clientRecv: ok", encoding="ascii"))
time.sleep(10)
connection.close()
input("enter end")
先运行服务端,再运行客户端。
图像传输给python后,再进行相应的处理。本例需要预设图像尺寸,当然读者可以先通过socket发送图像的头信息,比如尺寸什么的,再传递图像的数据。
传输速度比较慢,我是在本机上做的,3M图像差不多300ms。