【视频传输】一、Opencv结合socket进行视频传输(TCP协议)

           简介:紧接着上一篇文章:【一】Opencv结合socket进行视频传输(TCP协议),我们趁热打铁,接下来在两台电脑之间进行视频的传输,化繁为简我们传输灰度视频。如确实还有问题,可以直接回复博客或图文并茂的将问题邮件给笔者(cuit_hjs@163.com),笔者知识有限,但尽量答复。

        那么我们现在就开始吧,找两台都能上网的计算机,然后相互ping一下;传输视频思路是:抓取摄像头的帧画面,传输,如此循环。

         跟上一文相同,在PC1上创建server工程,在PC2上创建client工程,代码分别如下:

客户端(client)源代码:

#include "stdafx.h"
#include <WINSOCK2.H>
#include <iostream>
#include <stdio.h>
#include <cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#pragma  comment(lib,"ws2_32.lib")

int main(int argc, char* argv[])
{
	WORD sockVersion = MAKEWORD(2,2);
	WSADATA data; 
	if(WSAStartup(sockVersion, &data) != 0)
	{
		return 0;
	}

	SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(sclient == INVALID_SOCKET)
	{
		printf("invalid socket !\n");
		return 0;
	}

	sockaddr_in serAddr;
	serAddr.sin_family = AF_INET;
	serAddr.sin_port = htons(8888);
	serAddr.sin_addr.S_un.S_addr = inet_addr("222.18.168.145"); //服务器的IP地址,可以是:①连接外网后分配的②手动设置的
	if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
	{
		printf("connect error !\n");
		closesocket(sclient);
		return 0;
	}
	//读取图像并发送
	IplImage *image_src = NULL;
	IplImage *image_dst = cvCreateImage(cvSize(640, 480), 8, 1);//我的摄像头是640x480的,如不同则自行修改

	CvCapture *capture = cvCreateCameraCapture(0);//打开摄像头
	if (!capture)
	{
		printf("摄像头打开失败,请检查设备!\n");
	}
	int i, j;
	char sendData[1000000] = "";
	cvNamedWindow("client", 1);
	while(1)
	{
		image_src = cvQueryFrame(capture);
		cvCvtColor(image_src, image_dst, CV_RGB2GRAY);
		for(i = 0; i < image_dst->height; i++)
		{
			for (j = 0; j < image_dst->width; j++)
			{
				sendData[image_dst->width * i + j] = ((char *)(image_dst->imageData + i * image_dst->widthStep))[j];
			}
		}
		cvShowImage("client", image_src);//显示原图
		cvWaitKey(30);//如果服务端收到的视频比较卡,此处延时适当改大一点
		send(sclient, sendData, 1000000, 0);
	}
	cvReleaseCapture(&capture);
	cvDestroyWindow("client");
	closesocket(sclient);
	WSACleanup();
	return 0;
}

服务器端(server)源代码:

#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#include <cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#pragma comment(lib,"ws2_32.lib")

int main(void)
{
	//初始化WSA
	WORD sockVersion = MAKEWORD(2,2);
	WSADATA wsaData;
	if(WSAStartup(sockVersion, &wsaData)!=0)
	{
		return 0;
	}
	//创建套接字
	SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(slisten == INVALID_SOCKET)
	{
		printf("socket error !");
		return 0;
	}
	//绑定IP和端口
	sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(8888);//端口8888
	sin.sin_addr.S_un.S_addr = INADDR_ANY; 
	if(bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		printf("bind error !");
	}

	//开始监听
	if(listen(slisten, 5) == SOCKET_ERROR)
	{
		printf("listen error !");
		return 0;
	}

	//循环接收数据
	SOCKET sClient;
	sockaddr_in remoteAddr;
	int nAddrlen = sizeof(remoteAddr);

	printf("等待连接...\n");
	do
	{
		sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
	}while(sClient == INVALID_SOCKET);
	printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
	
	char revData[1000000] = ""; 
	IplImage *image_src = cvCreateImage(cvSize(640, 480), 8, 1);//收到的图像是640x480的,如不同请自行修改
	int i, j;
	int ret;
	cvNamedWindow("server", 1);
	while(true)
	{
		//接收数据
		ret = recv(sClient, revData, 1000000, 0);		
		if(ret > 0)
		{
			revData[ret] = 0x00;
			for(i = 0; i < image_src->height; i++)
			{
				for (j = 0; j < image_src->width; j++)
				{
					((char *)(image_src->imageData + i * image_src->widthStep))[j] = revData[image_src->width * i + j];
				}
			}
			ret = 0;
		}
		cvShowImage("server", image_src);//收到的是灰度图像
		cvWaitKey(1);
	}
	cvDestroyWindow("server");	
	closesocket(slisten);
	WSACleanup();
	return 0;
}
          同样的,弄好了所有的准备工作后,先运行server,再运行client。可以看到效果,如果比较卡,可能是网络原因带宽不够,如果服务端有360加速球(绿色那个浮的圆条),就可以看到下载网速。

         到此,实验就算是结束了,但是对于上述效果我不是很满意,因为我在跑代码的时候确实是卡顿卡顿的。那么有一种改进的方法就是,将两台计算机直接用网线相连,一主一从。

         用网线连接后,用ipconfig查看,发现二者均没有分配到IP。那么就必须得手动分配IP地址了,在这里设置:网络连接—>本地连接—>属性—>常规—>Internet协议(TCP/IP)的属性中,下面我将server端设置为下图所示:


将client端设置为下图所示:


       分配好后,再二者相互ping一下,通了就可以,都没通可能就不得行(注意,请根据自己的网段来设置IP,可以上网搜一下电脑网线直连IP设置)。那么在可以注意到,需要将client中设置IP处的代码改为:

serAddr.sin_addr.S_un.S_addr = inet_addr("222.18.168.150"); 
       接下来运行server和client,可以看到顿卡瞬间就消失了,一下就变畅爽了。甚至试着client处的延时代码改变为:

cvWaitKey(1);
       即使这样也是毫无压力,你再看看上传下载网速。同样的道理,我们照猫画虎就可以无压力的传输彩色视频了。

       本次实验所需要的代码都已打包上传,下载地址:http://download.csdn.net/detail/hujingshuang/8400587

        特别注意:

                    1、本博客例程仅做学习交流用,切勿用于商业用途。

                    2、欢迎交流,转载请注明出处http://blog.csdn.net/hujingshuang/article/details/43193747



  • 9
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值