linux opencv视频通信,基于Socket和OpenCV的实时视频传输(On Linux)

上一篇介绍了在Windows上实现基于Socket和openCV的实时视频传输,这一篇将继续讲解在Linux上的实现。

环境:

Server: Ubuntu 14.04 LTS + OpenCV2.4.10

Client:: Ubuntu 14.04 LTS + OpenCV2.4.10

我采用的仍是TCP协议的通信,Linux上的实现和Windows大同小异。

TCP协议通信的一般步骤我再重新说一下:

客户端:

1、创建一个socket,用函数socket();

2、设置socket属性,用函数setsockopt();* 可选

3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选

4、设置要连接的对方的IP地址和端口等属性;

5、连接服务器,用函数connect();

6、收发数据,用函数send()和recv(),或者read()和write();

7、关闭网络连接;

服务器端:

1、创建一个socket,用函数socket();

2、设置socket属性,用函数setsockopt(); * 可选

3、绑定IP地址、端口等信息到socket上,用函数bind();

4、开启监听,用函数listen();

5、接收客户端上来的连接,用函数accept();

6、收发数据,用函数send()和recv(),或者read()和write();

7、关闭网络连接;

8、关闭监听;

我把图像的发送和接收分别封装在了两个类中:

采集与发送:

SocketMatTransmissionClient.h

/*M///

//

// 基于OpenCV和Socket的图像传输(发送)

//

//By 彭曾 , at CUST, 2016.08.07

//

//website: www.pengz0807.com email: pengz0807@163.com

//

//M*/

#ifndef __SOCKETMATTRANSMISSIONCLIENT_H__

#define __SOCKETMATTRANSMISSIONCLIENT_H__

#include "opencv2/opencv.hpp"

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace cv;

//待传输图像默认大小为 640*480,可修改

#define IMG_WIDTH 640// 需传输图像的宽

#define IMG_HEIGHT 480// 需传输图像的高

#define PACKAGE_NUM 2

//默认格式为CV_8UC3

#define BUFFER_SIZE IMG_WIDTH*IMG_HEIGHT*3/PACKAGE_NUM

struct sentbuf

{

char buf[BUFFER_SIZE];

int flag;

};

class SocketMatTransmissionClient

{

public:

SocketMatTransmissionClient(void);

~SocketMatTransmissionClient(void);

private:

int sockClient;

struct sentbuf data;

public:

// 打开socket连接

// params :IP服务器的ip地址

//PORT传输端口

// return : -1连接失败

//1连接成功

int socketConnect(const char* IP, int PORT);

// 传输图像

// params : image 待传输图像

// return : -1传输失败

//1传输成功

int transmit(cv::Mat image);

// 断开socket连接

void socketDisconnect(void);

};

#endif

SocketMatTransmissionClient.cpp

/*M///

//

// 基于OpenCV和Socket的图像传输(发送)

//

//By 彭曾 , at CUST, 2016.08.07

//

//website: www.pengz0807.com email: pengz0807@163.com

//

//M*/

#include "SocketMatTransmissionClient.h"

SocketMatTransmissionClient::SocketMatTransmissionClient(void)

{

}

SocketMatTransmissionClient::~SocketMatTransmissionClient(void)

{

}

int SocketMatTransmissionClient::socketConnect(const char* IP, int PORT)

{

struct sockaddr_in servaddr;

if ((sockClient = socket(AF_INET, SOCK_STREAM, 0)) < 0)

{

printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);

return -1;

}

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(PORT);

if (inet_pton(AF_INET, IP, &servaddr.sin_addr) <= 0)

{

printf("inet_pton error for %s\n", IP);

return -1;

}

if (connect(sockClient, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

{

printf("connect error: %s(errno: %d)\n", strerror(errno), errno);

return -1;

}

else

{

printf("connect successful!\n");

}

}

void SocketMatTransmissionClient::socketDisconnect(void)

{

close(sockClient);

}

int SocketMatTransmissionClient::transmit(cv::Mat image)

{

if (image.empty())

{

printf("empty image\n\n");

return -1;

}

if(image.cols != IMG_WIDTH || image.rows != IMG_HEIGHT || image.type() != CV_8UC3)

{

printf("the image must satisfy : cols == IMG_WIDTH(%d) rows == IMG_HEIGHT(%d) type == CV_8UC3\n\n", IMG_WIDTH, IMG_HEIGHT);

return -1;

}

for(int k = 0; k < PACKAGE_NUM; k++)

{

int num1 = IMG_HEIGHT / PACKAGE_NUM * k;

for (int i = 0; i < IMG_HEIGHT / PACKAGE_NUM; i++)

{

int num2 = i * IMG_WIDTH * 3;

uchar* ucdata = image.ptr(i + num1);

for (int j = 0; j < IMG_WIDTH * 3; j++)

{

data.buf[num2 + j] = ucdata[j];

}

}

if(k == PACKAGE_NUM - 1)

data.flag = 2;

else

data.flag = 1;

if (send(sockClient, (char *)(&data), sizeof(data), 0) < 0)

{

printf("send image error: %s(errno: %d)\n", strerror(errno), errno);

return -1;

}

}

}

接收与显示:

SocketMatTransmissionServer.h

/*M///

//

// 基于OpenCV和Socket的图像传输(接收)

//

//By 彭曾 , at CUST, 2016.08.07

//

//website: www.pengz0807.com email: pengz0807@163.com

//

//M*/

#ifndef __SOCKETMATTRANSMISSIONSEVER_H__

#define __SOCKETMATTRANSMISSIONSEVER_H__

#include "opencv2/opencv.hpp"

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace cv;

#define PACKAGE_NUM 2

#define IMG_WIDTH 640

#define IMG_HEIGHT 480

#define BLOCKSIZE IMG_WIDTH*IMG_HEIGHT*3/PACKAGE_NUM

struct recvBuf

{

char buf[BLOCKSIZE];

int flag;

};

class SocketMatTransmissionServer

{

public:

SocketMatTransmissionServer(void);

~SocketMatTransmissionServer(void);

int sockConn;

private:

struct recvBuf data;

int needRecv;

int count;

public:

// 打开socket连接

// params :PORT传输端口

// return : -1连接失败

//1连接成功

int socketConnect(int PORT);

// 传输图像

// params : image待接收图像

//image待接收图像

// return : -1接收失败

//1接收成功

int receive(cv::Mat& image);

// 断开socket连接

void socketDisconnect(void);

};

#endif

SocketMatTransmissionServer.cpp

/*M///

//

// 基于OpenCV和Socket的图像传输(接收)

//

//By 彭曾 , at CUST, 2016.08.07

//

//website: www.pengz0807.com email: pengz0807@163.com

//

//M*/

#include "SocketMatTransmissionServer.h"

SocketMatTransmissionServer::SocketMatTransmissionServer(void)

{

}

SocketMatTransmissionServer::~SocketMatTransmissionServer(void)

{

}

int SocketMatTransmissionServer::socketConnect(int PORT)

{

int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);

struct sockaddr_in server_sockaddr;

server_sockaddr.sin_family = AF_INET;

server_sockaddr.sin_port = htons(PORT);

server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)

{

perror("bind");

return -1;

}

if(listen(server_sockfd,5) == -1)

{

perror("listen");

return -1;

}

struct sockaddr_in client_addr;

socklen_t length = sizeof(client_addr);

sockConn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length);

if(sockConn<0)

{

perror("connect");

return -1;

}

else

{

printf("connect successful!\n");

return 1;

}

close(server_sockfd);

}

void SocketMatTransmissionServer::socketDisconnect(void)

{

close(sockConn);

}

int SocketMatTransmissionServer::receive(cv::Mat& image)

{

int returnflag = 0;

cv::Mat img(IMG_HEIGHT, IMG_WIDTH, CV_8UC3, cv::Scalar(0));

needRecv = sizeof(recvBuf);

count = 0;

memset(&data,0,sizeof(data));

for (int i = 0; i < PACKAGE_NUM; i++)

{

int pos = 0;

int len0 = 0;

while (pos < needRecv)

{

len0 = recv(sockConn, (char*)(&data) + pos, needRecv - pos, 0);

if (len0 < 0)

{

printf("Server Recieve Data Failed!\n");

break;

}

pos += len0;

}

count = count + data.flag;

int num1 = IMG_HEIGHT / PACKAGE_NUM * i;

for (int j = 0; j < IMG_HEIGHT / PACKAGE_NUM; j++)

{

int num2 = j * IMG_WIDTH * 3;

uchar* ucdata = img.ptr(j + num1);

for (int k = 0; k < IMG_WIDTH * 3; k++)

{

ucdata[k] = data.buf[num2 + k];

}

}

if (data.flag == 2)

{

if (count == PACKAGE_NUM + 1)

{

image = img;

returnflag = 1;

count = 0;

}

else

{

count = 0;

i = 0;

}

}

}

if(returnflag == 1)

return 1;

else

return -1;

}

示例代码:

图像的采集与发送:

SocketClientMat.cpp

#include "SocketMatTransmissionClient.h"

int main()

{

SocketMatTransmissionClient socketMat;

if (socketMat.socketConnect("127.0.0.1", 6666) < 0)

{

return 0;

}

cv::VideoCapture capture(0);

cv::Mat image;

while (1)

{

if (!capture.isOpened())

return 0;

capture >> image;

if (image.empty())

return 0;

socketMat.transmit(image);

}

socketMat.socketDisconnect();

return 0;

}

接收与显示:

SocketServerMat.cpp

#include "SocketMatTransmissionServer.h"

int main()

{

SocketMatTransmissionServer socketMat;

if (socketMat.socketConnect(6666) < 0)

{

return 0;

}

cv::Mat image;

while (1)

{

if(socketMat.receive(image) > 0)

{

cv::imshow("",image);

cv::waitKey(30);

}

}

socketMat.socketDisconnect();

return 0;

}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值