Opencv 实现简单UDP局域网实时摄像头传输 (一)

    做项目需要用到网络编程及摄像头捕捉,经过简单学习完成一个简单的视频发送。

发送端:

sender.cpp


#include "stdafx.h"
#include "WinSock2.h"
#include <opencv2\opencv.hpp>
#pragma comment(lib,"ws2_32.lib")

using namespace std;
using namespace cv;
int main()
{
	char ip[20];
	printf("输入目标IP\n");
	scanf("%s", &ip);
	printf("目标IP%s\n", ip);
	WSADATA wsaData;
	int port = 5099;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		cout << "加载套接字失败" << endl;
		return 1;
	}
	SOCKADDR_IN addrRec;
	addrRec.sin_family = AF_INET;
	addrRec.sin_port = htons(port);
	addrRec.sin_addr.s_addr = inet_addr(ip);
	SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockClient == SOCKET_ERROR)
	{
		cout << "创建套接字失败" << endl;
		return 1;
	}


	int nLen = sizeof(SOCKADDR_IN);


	VideoCapture capture(0);
	Mat capframe, frame;
	capture >> capframe;
	int framesize = sizeof(frame);
	_int64 datasize = capframe.dataend - capframe.datastart;
	_int64 shrinksize = datasize / 16;
	while (capture.isOpened())
	{
		capture >> capframe;
		imshow("video", capframe);
		int sendData;

		resize(capframe, frame, Size(), 0.25, 0.25);
		sendData = sendto(sockClient, (char*)frame.data, shrinksize, 0, (LPSOCKADDR)&addrRec, nLen);
		if (sendData>0)
		{
			printf("size:%d,send:%d\n", shrinksize, sendData);
		}
		else
		{
			printf("发送data错误!%d           %d\n", sendData, WSAGetLastError());
		}



		if (waitKey(20) == 27)//27是键盘摁下esc时,计算机接收到的ascii码值  
		{
			capture.release();
			break;
		}


	}
	waitKey();
	WSACleanup();
    return 0;
}

接收端:

receiver.cpp

#include "stdafx.h"
#include "thread"
#include "WinSock2.h"
#include<opencv2\opencv.hpp>
#pragma comment(lib,"ws2_32.lib")
using namespace cv;
int main()
{

	char ip[20];
	printf("输入本机ipIP\n");
	scanf("%s", ip);
	printf("本机IP:%s\n", ip);
	WSADATA wsaData;
	int port = 5099;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("加载套接字失败\n");
		return 1;
	}
	SOCKADDR_IN addrRec;
	addrRec.sin_family = AF_INET;
	addrRec.sin_port = htons(port);
	addrRec.sin_addr.s_addr = inet_addr(ip);
	SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockClient == SOCKET_ERROR)
	{
		printf("套接字创建失败\n");
		return 1;
	}
	if (bind(sockClient, (LPSOCKADDR)&addrRec, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
	{
		printf("套接字绑定失败:%d\n", WSAGetLastError);
		return 1;
	}
	SOCKADDR_IN addrSend;
	int nLen = sizeof(SOCKADDR);
	Mat frame, rsframe;
	VideoCapture capture(0);
	capture >> frame;
	capture.release();
	resize(frame, frame, Size(), 0.25, 0.25);
	_int64 datasize = frame.dataend - frame.datastart;
	while (1)
	{

		if (SOCKET_ERROR != recvfrom(sockClient, (char*)frame.data, datasize, 0, (LPSOCKADDR)&addrRec, &nLen))
		{
			printf("收到Data!\n");
			imshow("reciver", frame);
		}
		if (waitKey(20) == 27)//27是键盘摁下esc时,计算机接收到的ascii码值  
		{
			break;
		}
	}
	WSACleanup();
	return 0;
}

    使用的都是最基础的功能。

    视频帧没有经过压缩,而UDP一个包的大小最大为65536B,所以采集到的图像需要长宽缩小4倍才能发送,接收端接收到的也是缩小后的图像,可以在接受端中再加入一个resize放大,或者在两端加入视频数据压缩与解压,这也是之后的学习方向。

    对于Mat的应用还不熟练,且实现环境是两台笔记本电脑之间,因此是在接收端中执行一次capture>>frame来初始化接收端的Mat,这将导致在非笔记本的电脑上接收端初始化Mat失败,今后将尝试利用函数实现可变环境下的Mat初始化。

    原文作者:Embattle
    原文地址: https://blog.csdn.net/Embattle/article/details/79518443
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞