OpenCV结合socket进行实时视频传输(TCP协议)
一、概述
内容:由Client客户端采集摄像头图像后经Socket传输到Server服务器端再显示出来。本实验在同一台电脑上实验,即运行服务器程序,又跑客户端程序,也就是说通过socket编程来实现数据的自发自收,这一步通过了接下来跑服务器和客户端分开的实验就简单了。
实验平台: VS2013 + opencv2.4.11(Windows 7)
说明:近期项目需要进行图像的采集传输任务,遂在网上寻找,并进行了些修改,记录在此。
二、实现
1、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、关闭监听;
2、Client 的实现(数据发送)
// Client.cpp 主函数
// 基于OpenCV和Winsock的图像传输(发送)#include "WinsockMatTransmissionClient.h" int main()
{WinsockMatTransmissionClient socketMat;if (socketMat.socketConnect("192.168.191.1", 6666) < 0) //地址自行设置{return 0;}cv::VideoCapture capture(0);cv::Mat frame;while (1){if (!capture.isOpened())return 0;capture >> frame;imshow("client", frame);cv::waitKey(30);if (frame.empty())return 0;socketMat.transmit(frame);}socketMat.socketDisconnect();return 0;
}
数据的发送——WinsockMatTransmissionClient.h
// WinsockMatTransmissionClient.h
// 基于OpenCV和Winsock的图像传输(发送)#ifndef __WINSOCKMATTRANSMISSIONCLIENT_H__
#define __WINSOCKMATTRANSMISSIONCLIENT_H__
#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include <stdio.h>
#include <Winsock2.h> #pragma comment(lib,"WS2_32.lib") //待传输图像默认大小为 640*480,可修改
#define IMG_WIDTH 640 // 需传输图像的宽
#define IMG_HEIGHT 480 // 需传输图像的高
//默认格式为CV_8UC3
#define BUFFER_SIZE IMG_WIDTH*IMG_HEIGHT*3/32 struct sentbuf
{char buf[BUFFER_SIZE];int flag;
};class WinsockMatTransmissionClient
{public:WinsockMatTransmissionClient(void);~WinsockMatTransmissionClient(void);private: SOCKET 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
数据的发送——WinsockMatTransmissionClient.cpp
// WinsockMatTransmissionClient.cpp
// 基于OpenCV和Winsock的图像传输(发送)#include "WinsockMatTransmissionClient.h" WinsockMatTransmissionClient::WinsockMatTransmissionClient(void)
{
}WinsockMatTransmissionClient::~WinsockMatTransmissionClient(void)
{
}int WinsockMatTransmissionClient::socketConnect(const char* IP, int PORT)
{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;}err = (sockClient = socket(AF_INET, SOCK_STREAM, 0));if (err < 0) {printf("create socket error: %s(errno: %d)\n\n", strerror(errno), errno);return -1;}else{printf("create socket successful!\nnow connect ...\n\n");}SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr = inet_addr(IP);addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(PORT);err = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));if (err < 0){printf("connect error: %s(errno: %d)\n\n", strerror(errno), errno);return -1;}else{printf("connect successful!\n\n");return 1;}
}void WinsockMatTransmissionClient::socketDisconnect(void)
{closesocket(sockClient);WSACleanup();
}int WinsockMatTransmissionClient::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 < 32; k++){int num1 = IMG_HEIGHT / 32 * k;for (int i = 0; i < IMG_HEIGHT / 32; 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 == 31)data.flag = 2;elsedata.flag = 1;if (send(sockClient, (char *)(&data), sizeof(data), 0) < 0){printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);return -1;}}
}
3、Server 的实现(数据接收)
// Server.cpp 主函数
// 基于OpenCV和Winsock的图像传输(接收)#include "WinsockMatTransmissionServer.h" int main()
{WinsockMatTransmissionServer socketMat;if (socketMat.socketConnect(6666) < 0){return 0;}cv::Mat image;while (1){if (socketMat.receive(image) > 0){cv::imshow("server", image);cv::waitKey(30);}}socketMat.socketDisconnect();return 0;
}
数据的接收——WinsockMatTransmissionServer.h
// WinsockMatTransmissionServer.h
// 基于OpenCV和Winsock的图像传输(接收)#ifndef __WINSOCKMATTRANSMISSIONSEVER_H__
#define __WINSOCKMATTRANSMISSIONSEVER_H__ #include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include <stdio.h>
#include <Winsock2.h> #pragma comment(lib,"WS2_32.lib") //待传输图像默认大小为 640*480,可修改
#define IMG_WIDTH 640 // 需传输图像的宽
#define IMG_HEIGHT 480 // 需传输图像的高
//默认格式为CV_8UC3
#define BUFFER_SIZE IMG_WIDTH*IMG_HEIGHT*3/32 struct recvbuf
{char buf[BUFFER_SIZE];int flag;
};class WinsockMatTransmissionServer
{public:WinsockMatTransmissionServer(void);~WinsockMatTransmissionServer(void);private: SOCKET sockConn;struct recvbuf data;public:// 打开socket连接 // params : PORT 传输端口 // return : -1 连接失败 // 1 连接成功 int socketConnect(int PORT);// 传输图像 // params : image 待接收图像 // return : -1 接收失败 // 1 接收成功 int receive(cv::Mat& image);// 断开socket连接 void socketDisconnect(void);
};#endif
数据的接收——WinsockMatTransmissionServer.cpp
// WinsockMatTransmissionServer.cpp
// 基于OpenCV和Winsock的图像传输(接收)// 基于OpenCV和Winsock的图像传输(接收)#include <iostream>
#include "WinsockMatTransmissionServer.h" WinsockMatTransmissionServer::WinsockMatTransmissionServer(void)
{
}WinsockMatTransmissionServer::~WinsockMatTransmissionServer(void)
{
}int WinsockMatTransmissionServer::socketConnect(int PORT)
{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;}SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(PORT);bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));listen(sockSrv, 5);SOCKADDR_IN addrClient;int len = sizeof(SOCKADDR);sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);int nRecvBuf = 1024 * 1024 * 10;setsockopt(sockConn, SOL_SOCKET, SO_RCVBUF, (const char*)&nRecvBuf, sizeof(int));
}void WinsockMatTransmissionServer::socketDisconnect(void)
{closesocket(sockConn);
}int WinsockMatTransmissionServer::receive(cv::Mat& image)
{cv::Mat img(IMG_HEIGHT, IMG_WIDTH, CV_8UC3, cv::Scalar(0));int needRecv = sizeof(recvbuf); //28804int count = 0;extern int errno;while (1){for (int i = 0; i < 32; 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");return -1;}pos += len0;}count = count + data.flag;int num1 = IMG_HEIGHT / 32 * i;for (int j = 0; j < IMG_HEIGHT / 32; 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 == 33){image = img;return 1;count = 0;}else{count = 0;i = 0;}}}}
}
三、结果
Client端:
Server端:
OpenCV结合socket进行实时视频传输(TCP协议)相关推荐
- socket 网络通信(基于tcp协议)以及粘包解决方案
socket 网络通信(基于tcp协议)以及粘包解决方案 参考文章: (1)socket 网络通信(基于tcp协议)以及粘包解决方案 (2)https://www.cnblogs.com/amiee- ...
- Socket 系统调用深入研究(TCP协议的整个通信过程)
说明 本文主要参考的原文:Know your TCP system call sequences socket api可以参考我的博客:socket API 介绍 TCP DEMO:tcp demo ...
- java socket 通信协议_java 基于TCP协议的Socket编程和通信
java 基于 TCP 协议的 Socket 编程和通信 在网络通讯中,第一次主动发起通讯的程序被称作客户 端 (Client) 程序, 简称客户端, 而在第一次通讯中等待连接的 程序被称作服务器端 ...
- 基于TCP协议的Socket网络通信
前言 一. 什么是网络(了解七层网络模型)? 二. 什么是TCP/UDP协议? 三.什么是socket? 定义 四.基于TCP协议的socket通信的实现步骤是怎样的? 客户端的实现 服务端的实现 测 ...
- 【计算机网络】传输层 : 总结 ( TCP / UDP 协议 | 寻址与端口 | UDP 协议 | TCP 协议特点 | TCP 连接释放 | TCP 流量控制 | TCP 拥塞控制 ) ★★★
文章目录 一.传输层 TCP / UDP 协议 ★ 二.寻址端口号 ★ 三.UDP 协议特点 四.UDP 协议首部格式 五.UDP 校验 六.TCP 协议 特点 ★ 七.TCP 报文段首部格式 八.T ...
- 【计算机网络】传输层 : TCP 协议 ( TCP 协议特点 | TCP 报文段首部格式 | TCP 报文段控制位 )
文章目录 一.TCP 协议 特点 二.TCP 报文段首部格式 三.TCP 报文段首部 666 控制位 一.TCP 协议 特点 TCP 协议 特点 : ① 面向连接 : TCP 协议的连接是 " ...
- 什么是SOCKET,什么是TCP,什么是HTTP?三者之间的关系和差异(面试常问)
该文章内容为作者结合多篇博文的总结,自行记录的理论笔记,方便查看. 一.SOCKET 套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本单元,它是网络通信过程中端点的抽象表示. ...
- 计算机视觉——利用openCV与Socket结合进行远程摄像头实时视频传输并保存图片数据
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.TCP协议通信步骤 二.代码实现 1.客户端 2.服务端 三.IP设置方法 四.效果演示 前言 本文的内容是利用o ...
- Socket编程(C语言实现)——TCP协议(网络间通信AF_INET)的流式(SOCK_STREAM)+报式(SOCK_DGRAM)传输【多线程+循环监听】
Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...
最新文章
- python16进制字节序_第 1 章 套接字、IPv4和简单的客户端/服务器编程
- Python原来这么厉害,我震惊了!
- php strpo函数,php strpos函数有什么用
- 安装Qemu-6.1.0
- linux服务器忘记ssh密码_【Linux】配置linux服务器之间ssh不用密码访问
- 华为路由交换常见配置
- 解决 el-autocomplete 不显示及没数据时闪一下的问题
- kubernetes存储系统介绍(Volume、PV、dynamic provisioning,阿里云服务器nfs创建pv,hostpath创建pv)
- 详解MySQL中EXPLAIN解释命令(转)
- windows tcp ping 端口工具及使用方法
- 《系统工程》--课程笔记二(系统工程方法论)
- 多窗直播 截屏录制——UC问鼎全球首款直播浏览器
- 如何学习硬件设计——理论篇
- Yolov5中使用Resnet18作为主干网络
- 前端实现Thing.js 3D模型展示Demo
- 3D视觉感知市场规模现状及行业发展前景分析
- 以前用C++实现的RMM分词类型
- 饮食男女,人之大欲--nbsp;《饮食…
- 【Leetcode】对 矩 阵 螺 旋 输 出 java/c++
- BZOJ4811: [Ynoi2017]由乃的OJ 重链剖分
热门文章
- JavaWeb 入门篇(2)Hello Servlet!!!
- 想学python怎么学习_新手如何自学python课程?
- python获取数组中大于某一阈值的那些索引值_使用Python+OpenCV进行实时车道检测...
- websocket 代理tcp_netty实现websocket请求实战
- 修改oracle日志大小,修改Oracle重做日志文件大小
- webpack引入iview.css,解决webpack+Vue引入iView找不到字体文件的问题
- t184卡西欧计算机玩游戏,中学回忆——卡西欧 FX-82ES 科学计算器 晒物
- python 笔试题 英方_经典算法题 :找字符串中的逆序对(百度笔试题)
- python引入jit_从numba导入jit
- 如何利用python进行数据分析统计服_利用Python进行数据分析