CSocket 传输 IplImage
近期开发一视频监控系统,需要进行网络数据下视频数据的传输。
在此之前,希望你有MFC基础的功底,具体详见《孙鑫深入了解VC++视频教程》第13、14、15章等有关网络和多线程的章节。
关于opencv的基本知识(怎么配置以及如何使用)请参见其他资料,这里需要补充下IplImage详解http://blog.csdn.net/google0802/article/details/8986791
最重要的是要搞明白IplImage里面的origin(弄错后传过去的图像是倒着的)和char *imageData; /* 指向排列的图像数据 */ 里面存储了char型的图像矩阵数据。
要先把图像的基本信息(width,height,depth,nchannels)传过去,然后传imageData,而另一端先接收图像的基本信息,用cvCreateImage来构造,然后接收imageData数据。
网络资料鱼龙混杂,具体分来以下几类:
最原始的方式实现;
CSocket实现;
多线程实现;
最原始的方式参见孙鑫的教程,从网络通信的原理一直讲到多线程再到异步IO,有关同步、异步、阻塞、非阻塞等概念详见文后链接。
套接字模式—阻塞模式开发http://blog.csdn.net/wangningyu/article/details/4571614给出了工程源代码
感觉孙老师不地道,虽然深入了解底层细节有助于我们对细节的把握,但实际开发还是要封装好的代码的,C语言面向过程的方式显然是不合适的。
套接字模式—非阻塞模式开发(1)总结了阻塞模式和非阻塞模式的优缺点
C++ Socket编程步骤http://www.cnblogs.com/Sniper-quay/archive/2011/06/22/2086636.html做了一小结
socket阻塞与非阻塞,同步与异步、I/O模型:http://284772894.iteye.com/blog/1852265
IO - 同步,异步,阻塞,非阻塞 (亡羊补牢篇)http://blog.csdn.net/historyasamirror/article/details/5778378
基于Socket的文件传输(使用CSocket类)http://blog.csdn.net/leixiaohua1020/article/details/12025731有源代码编译通过
基于UDP协议的简单基本视频传输程序的编写http://blog.csdn.net/jhh_move_on/article/details/9118075原始的UDP方式进行的传输,有源代码编译通过,因数据量小一次能传完,但数据量大了就有问题
揭开Socket编程的面纱http://www.cnblogs.com/goodcandle/archive/2005/12/10/socket.html
深入 CSocket 编程之阻塞和非阻塞模式http://blog.csdn.net/yjgx007/article/details/237955里面的两篇参考文献给出了源代码,非常不错
使用MFC类库进行socket编程的入门实例http://www.cppblog.com/changshoumeng/articles/112813.html这个总算接近实用水平了,我的代码就是在这基础上改的。
说下我新加的部分:为CServerDemoDlg 添加成员函数void SendImage(IplImage *img);负责发送图片
具体实现为:
void CServerDemoDlg::SendImage(IplImage *img) { try { if(!img->imageData) return; RecvSock->Send((char*)&img->width,4); RecvSock->Send((char*)&img->height,4); RecvSock->Send((char*)&img->depth,4); RecvSock->Send((char*)&img->nChannels,4); int buffersize=1024; RecvSock->Send((char*)&buffersize,4); int num=0,ret; while(num<=img->imageSize-buffersize) { ret=RecvSock->Send((char*)(img->imageData+num),buffersize); num+=ret; } ret=RecvSock->Send((CHAR*)img->imageData+num,img->imageSize-num); } catch (CException* e) { } }
void CServerDemoDlg::OnButton1() { img=cvLoadImage("bluerose.jpg"); SendImage(img); }
同理客户端接收主要代码:
void CClientDemoDlg::RecvImage(IplImage *img) { try { int width,height,depth,channels; ClientSock->Receive((char*)&width,4); ClientSock->Receive((char*)&height,4); ClientSock->Receive((char*)&depth,4); ClientSock->Receive((char*)&channels,4); img=cvCreateImage(cvSize(width,height),depth,channels); int imsize=img->imageSize; int buffersize; ClientSock->Receive((char*)&buffersize,4); int num=0,ret; while(num<img->imageSize-buffersize) { ret=ClientSock->Receive((char*)(img->imageData+num),buffersize); num+=ret; } ClientSock->Receive((char*)(img->imageData+num),img->imageSize-num); DrawPicToHDC(img,IDC_PIC); cvReleaseImage(&img); } catch (CException* e) { } }
看下最后的效果吧: