大家好,又见面了,我是你们的朋友全栈君。
上一篇介绍了在Windows上实现基于Socket和openCV的实时视频传输,这一篇将继续讲解在Linux上的实现。
环境:
Server: Ubuntu 14.04 LTS + OpenCV2.4.10
Client:: Ubuntu 14.04 LTS + OpenCV2.4.10
我采用的仍是TCP协议的通信,Linux上的实现和Windows大同小异。
Linux中OpenCV的编译安装可以参考 http://blog.csdn.net/pengz0807/article/details/49915573
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 <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>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_NUMstruct 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<uchar>(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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
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<uchar>(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;
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/129239.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...