用SOCKET发送OpenCV的IplImage结构
来源:互联网 发布:js 骰子的转动效果 编辑:程序博客网 时间:2024/05/01 10:44
做一个C/S架构的Image Processing的程序,其中读写图片和图像处理的部分都是用OpenCV来实现的。本人原先没有怎么接触过SOCKET编程,网上也没有找到怎么发送一个类似IplImage结构这样文章,之后自己解决了,所以把CSDN的博客开了写一篇这个,自己记录一下,也方便像我一样的初学者。
对于一般的结构例如CvPoint,我们首先来看一下CvPoint的结构
typedef struct CvPoint{ int x; int y;}CvPoint;
如果要发送一个CvPoint的话可以使用以下语句
CvPoint point(1, 1);send(s, (char*)&point, sizeof(CvPoint), 0);
CvPoint p;recv(s, (char*)&p, sizeof(CvPoint), 0);实际上这种发送接受的结构类似于memcpy,发送的过程就是将内存中指向point所占空间的开始地址接连的sizeof(CvPoint)个字节的内容(实际上就是point的内容)拷贝到发送缓冲区中等待发送。
而接受则是将当前接收缓冲区中的内容连续拷贝sizeof(CvPoint)个字符到以&p为起点的内存空间中。比较简略的示意图如下所示
这时候实际上采用什么类型的指针来作为index都是无所谓的。例如&p为0x00cd4360,这时候声明一个int类型的指针指向p的话同样也是指向0x00cd4360.唯一不同的是如果你把它指向的地址元素以int形式取出来可能结果会很怪,另外int类型指针增加的话是跨越2个字节而不是1个。所以这里即使是用BYTE*代替char*都是可以的。
所以可能像我一样的初学者就觉得这样就可以如法炮制传送IplImage结构了,其实不是这样的。首先来分析一下IplImage的结构:
typedef struct _IplImage{ int nSize; /* sizeof(IplImage) */ int ID; /* version (=0)*/ int nChannels; /* Most of OpenCV functions support 1,2,3 or 4 channels */ int alphaChannel; /* Ignored by OpenCV */ int depth; /* Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported. */ char colorModel[4]; /* Ignored by OpenCV */ char channelSeq[4]; /* ditto */ int dataOrder; /* 0 - interleaved color channels, 1 - separate color channels. cvCreateImage can only create interleaved images */ int origin; /* 0 - top-left origin, 1 - bottom-left origin (Windows bitmaps style). */ int align; /* Alignment of image rows (4 or 8). OpenCV ignores it and uses widthStep instead. */ int width; /* Image width in pixels. */ int height; /* Image height in pixels. */ struct _IplROI *roi; /* Image ROI. If NULL, the whole image is selected. */ struct _IplImage *maskROI; /* Must be NULL. */ void *imageId; /* " " */ struct _IplTileInfo *tileInfo; /* " " */ int imageSize; /* Image data size in bytes (==image->height*image->widthStep in case of interleaved data)*/ char *imageData; /* Pointer to aligned image data. */ int widthStep; /* Size of aligned image row in bytes. */ int BorderMode[4]; /* Ignored by OpenCV. */ int BorderConst[4]; /* Ditto. */ char *imageDataOrigin; /* Pointer to very origin of image data (not necessarily aligned) - needed for correct deallocation */}IplImage;其中我们通过分析IplImage的结构可以看出,实际上其中成员除了int,char数组之外还有char指针。所以我们可以看出来,IplImage是一个Header+Data式的结构。它的data项实际上是存在另外的地方,用一个imageData指示数据的首地址而已。所以分析到这里已经很明白了,只需要将IplImage的header和data分开传输过去就可以了。以下是简单实现的代码,其中hdr_data以及HDRLEN_DATA分别是数据包头和数据包头的长度,用来指示接下去要收多少个字节的data:
#define BUFF_SIZE 1024 * 4//any number you wants according to your OS#define HDRLEN_IPLIMAGE (sizeof(IplImage))IplImage* RcvIplImage(SOCKET s)//returns a pointer to the iplimage{IplImage header;IplImage* source;char *databuf;char *index;int ret;hdr_data datainfo;char buf[BUFF_SIZE+5];ret = ::recv(s, (char *)&header, HDRLEN_IPLIMAGE, 0);source = cvCreateImageHeader(cvSize(header.width, header.height), header.depth, header.nChannels);if (ret != HDRLEN_IPLIMAGE){return NULL;}databuf = new char[source->imageSize];source->imageData = databuf;source->imageDataOrigin = databuf;index = databuf;ret = ::recv(s, (char *)&datainfo, HDRLEN_DATA, 0);if (ret != HDRLEN_DATA){return NULL;}while(ret > 0 && datainfo.data_len != -1){receivedata(buf, datainfo.data_len, s);memcpy(index, buf, datainfo.data_len);index += datainfo.data_len;receivedata((char *)&datainfo, HDRLEN_DATA, s);}return source;}BOOL SendIplImage(IplImage* source, SOCKET s){int ret, count, datalen;char *index;hdr_data datainfo;index = source->imageData;count = 0;ret = ::send(s, (char *)source, HDRLEN_IPLIMAGE, 0);datalen = BUFF_SIZE;while (ret > 0){datainfo.data_len = datalen;ret = ::send(s, (char *)&datainfo, HDRLEN_DATA, 0);ret = ::send(s, (char *)index, datalen, 0);if (datalen < BUFF_SIZE)break;count += datalen;index += datalen;if (count > source->imageSize - BUFF_SIZE)datalen = source->imageSize - count;}datainfo.data_len = -1;ret = ::send(s, (char *)&datainfo, HDRLEN_DATA, 0);return TRUE;}BOOL receivedata(char* buf, int length, SOCKET s)//用来从接受缓冲区中接受length个字节{int ret, lefti;lefti = length;while (lefti > 0){ret = ::recv(s, (char *)buf, lefti, 0);buf += ret;lefti = lefti - ret;}return TRUE;}
以上就是发送和接受IplImage结构的代码。但是需要指出的是,对于RcvIplImage返回的IplImage *结构最好不要用CvReleaseImage来释放。因为这个函数是对应于使用CvCreateImage函数创建的图像的,直接使用可能因为CvFree的一些设计导致冲突。推荐使用以下代码来解决这个问题:
IplImage *oriImage = RcvIplImage(m_socket);delete[] (oriImage->imageData);cvReleaseImageHeader(&oriImage);与此同时我也研究了一下怎么发送CvMat,这个比起IplImage来说有点麻烦,鉴于我已经很困了,所以下次再写
PS:给个最简单的hdr_data的定义
其实就是把Iplimage分成header和data,在接收端得到了包头之后把ipliamge的imageData指针指向接收到的data的的位置。
hdr_data是数据包头的内容,这个可以根据需要定义。比如说最简单地就用
struct hdr_data{
long length;
}
- 用SOCKET发送OpenCV的IplImage结构
- opencv iplimage socket 传输
- opencv iplimage socket 传输
- opencv学习_5 (IplImage的结构)
- opencv学习_5 (IplImage的结构)
- OpenCV---IplImage结构
- openCV IplImage结构体
- opencv IplImage结构
- OpenCV IplImage结构体
- 用Socket保存OpenCV的CvMat结构
- OpenCV 中Iplimage结构详解
- opencv——IplImage结构
- 利用OpenCv读取视频时释放IplImage结构的问题
- OpenCV的IplImage图像格式
- IplImage结构的使用
- IplImage的结构分析
- [zz]OpenCV 学习笔记之IplImage 结构
- opencv-IplImage结构图像画到HDC上
- 新加坡行前——上海一日游 13/09/2012
- C标准I/O缓冲区:全缓冲和行缓冲
- ajax
- Keil C51编程工具
- Linux curl使用简单介绍
- 用SOCKET发送OpenCV的IplImage结构
- hdu 1040 As Easy As A+B
- javascript 基础总结1
- 三款免费的PHP加速器:APC、eAccelerator、XCache比较
- Fluent Interface-感知
- 安装boost的regex模块
- PING用一生诠释了TCP/IP
- DES加密代码
- 在C#中使用Panel控件实现在一个窗体中嵌套另一个窗体