用Socket保存OpenCV的CvMat结构

接着上个月写的一篇发送IplImage结构的来说,因为Socket发送结构的部分上一篇写过了,所以不再多写了。

CvMat的结构如下:

typedef struct CvMat
{
    int type;
    int step;
    /* for internal use only */
    int* refcount;
    int hdr_refcount;
    union
    {
        uchar* ptr;
        short* s;
        int* i;
        float* fl;
        double* db;
    } data;
#ifdef __cplusplus
    union
    {
        int rows;
        int height;
    };
    union
    {
        int cols;
        int width;
    };
#else
    int rows;
    int cols;
#endif
}
CvMat;
这里其实和传送IpIlmage一样,需要先传送CvMat的header。需要特别说明的是,CvMat中的矩阵元素的类型和IplImage是不一样的,有可能是uchar,short,float或者double。所以在接受的过程中可能需要知道它的type。使用以下代码:

int a_type = CV_MAT_TYPE(mat->type);
CV_MAT_TYPE是core文件夹下的types_c.h里定义的一个宏。用这个宏可以将CvMat的type转换成诸如CV_8UC1之类的参数,并且以此确定CvMat的类型。

另外在利用cvCreateMatHeader这个函数中需要特别注意,它创建的CvMat的step和正常读一幅图片读出来的CvMat是不一样的。

以下是利用Socket传送一个CvMat的代码,这里指定CvMat为CV_32FC1,其中HDRLEN_CVMAT等于sizeof(CvMat)

BOOL SendCvMat(CvMat* source, SOCKET s)
{
	int ret, count, datalen, total;
	char *index;
	char buffer[BUFF_SIZE + 5];
	hdr_data datainfo;

	index = (char *)source->data.ptr;
	count = 0;
	ret = ::send(s, (char *)source, HDRLEN_CVMAT, 0);
	datalen = BUFF_SIZE;
	total = source->step * source->height;
	while (ret > 0)
	{
		datainfo.data_len = datalen;

		ret = ::send(s, (char *)&datainfo, HDRLEN_DATA, 0);
		memcpy(buffer, index, datalen);
		ret = ::send(s, (char *)&buffer, datalen, 0);
		if (datalen < BUFF_SIZE)
			break;

		count += datalen;
		index += datalen;
		if (count > total - BUFF_SIZE)
			datalen = total - count;
	}
	datainfo.data_len = -1;
	ret = ::send(s, (char *)&datainfo, HDRLEN_DATA, 0);
	return TRUE;
}

以下是接受一个CvMat的代码

CvMat* RcvCvMat(SOCKET s)//just for 32-bit float
{
	CvMat header;
	CvMat *mat;
	float *databuf;//so each element of databuf consists of two chars
	char *index;
	int ret;
	hdr_data datainfo;
	char buffer[BUFF_SIZE + 5];

	ret = ::recv(s, (char *)&header, HDRLEN_CVMAT, 0);
	mat = cvCreateMatHeader(header.rows, header.cols, header.type);
	mat->step = header.step;

	databuf = new float[mat->height * mat->step];
	mat->data.fl = databuf;
	index = (char *)databuf;

	ret = ::recv(s, (char *)&datainfo, HDRLEN_DATA, 0);
	while(ret > 0 && datainfo.data_len != -1){
		receivedata(buffer, datainfo.data_len, s);
		memcpy(index, buffer, datainfo.data_len);
		index += datainfo.data_len;
		receivedata((char *)&datainfo, HDRLEN_DATA, s);
	}
	return mat;
}



你可能感兴趣的:(用Socket保存OpenCV的CvMat结构)