1.问题和需求
需求是使用海康热成像相机实时获取温度矩阵。相机说明文档提供了全屏测温实时取流的方法和代码,其将字节流写入到本地文件,然后通过解析文件的方式获得温度矩阵。但在实际应用中必须要在内存中进行实时解析。
2. 方法和思路
将字节流缓存到内存中,当缓存中的数据量大于一帧数据的数据量时,将该帧数据拷贝出来解析为Mat矩阵
- 登录相机后,开启RealPlay,byVideoCodingType需要设置为1,并注册取流回调函数,所有温度原始数据会通过回调函数进行下发,同时需要通过协议透传配置相机全屏测温参数。
- 缓存回调函数给出的数据,并实时解析为OpenCV Mat:
- 回调函数每次给出的数据长度不一定都一样,因此,需要把数据先缓存起来,当满足一帧的数据量时,再进行解析
- 使用QBuffer进行缓存
- 数据解析:可以直接修改官方文档中给出的解析本地文件的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;
}
}