1.问题和需求

需求是使用海康热成像相机实时获取温度矩阵。相机说明文档提供了全屏测温实时取流的方法和代码,其将字节流写入到本地文件,然后通过解析文件的方式获得温度矩阵。但在实际应用中必须要在内存中进行实时解析。

2. 方法和思路

将字节流缓存到内存中,当缓存中的数据量大于一帧数据的数据量时,将该帧数据拷贝出来解析为Mat矩阵

  1. 登录相机后,开启RealPlay,byVideoCodingType需要设置为1,并注册取流回调函数,所有温度原始数据会通过回调函数进行下发,同时需要通过协议透传配置相机全屏测温参数。
  2. 缓存回调函数给出的数据,并实时解析为OpenCV Mat:
  1. 回调函数每次给出的数据长度不一定都一样,因此,需要把数据先缓存起来,当满足一帧的数据量时,再进行解析
  2. 使用QBuffer进行缓存
  3. 数据解析:可以直接修改官方文档中给出的解析本地文件的demo

3. 参考代码

在回调函数中进行缓存和解析

void CALLBACK g_RealDataCallBack_V30(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize,void* dwUser)
{
    Camera* camera = (Camera*)dwUser;

    switch (dwDataType)
    {
	    case NET_DVR_STREAMDATA:
	    {
	        //接收到的数据写入缓存
	        //BUFFER为QBuffer类型的对象
	        camera->BUFFER->write((char*)pBuffer, dwBufSize);
	        pos = camera->BUFFER->pos(); //缓存中指针指向的位置,表示当前已经缓存的字节个数
	        sumSize += dwBufSize;        //一共接收到的缓存

			//bufferSize为一帧数据的大小
	        if(pos >= camera->bufferSize)
	        {	
				//超过一帧数据量,将一帧数据从BUFFER中读出来
				camera->BUFFER->seek(0);    //读取的时候指针需要回到开头
				
				//将数据读取到QByteArray中
				QByteArray frameByte(camera->bufferSize, '0');
				camera->BUFFER->read(frameByte.data(), camera->bufferSize);
				
				//判断缓存中是否剩余有其他数据
				int stopPos = camera->BUFFER->pos(); 
				int remanentNum = sumSize - stopPos;
	
	            if(remanentNum > 0)
	            {
			        //有多余的数据
	                //读取出多余的数据	
	                camera->BUFFER->seek(stopPos);
	                QByteArray dataSpanByte(remanentNum, '0');
	                camera->BUFFER->read(dataSpanByte.data(), remanentNum);
	
	                //再将多余的数据写入缓存的头部
	                camera->BUFFER->seek(0);
	                camera->BUFFER->write(dataSpanByte.data(), remanentNum);	
	            }
	            else
	            {
	                //没有多余的数据,则将指针移动会缓存开始处
	                camera->BUFFER->seek(0);	
	            }
	
	  	
	            //将完整的一帧数据拷贝到另一个Qbuffer对象中	
	            QBuffer *oneFrameBuffer = new QBuffer();	
	            buffer->open(QBuffer::WriteOnly);	
	            buffer->seek(0);	
	            buffer->write(frameByte.data(), camera->bufferSize);	
	            buffer->close();
		
	            //解析为温度矩阵
	            cv::Mat tempMat = camera->PaserQBufferToImg(oneFrameBuffer);
		        
		        // ----- 处理 -----
			    //
			    //
			    //
	            delete oneFrameBuffer;
	            	
	            //当前BUFFER中的数据量
	            sumSize = camera->BUFFER->pos();	
	        }
	        break;
	    }
	    default:
	        break;
    }
}