python与C++利用socket通信进行Mat图像传输

背景

​​​​​做到项目涉及到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。

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值