海康热成像SDK,透传修改测温规则,提高测温速度
最近使用一个海康热成像做测温,需要根据算法结果不断调整测温位置,测温速度不低于5Hz。
先尝试下测温速度情况,查看了SDK功能,有个实时测温功能,仔细看代码发现,这个需要提前设置好测温规则,也就是指定好测温区域、测温点之类的,然后它会把规则的测温结果不断上传。网页端设置好规则,代码一通猛如虎操作后,实测600ms才会回传一次测温结果,1.67Hz速度,也许是我的相机差吧,而且没有设置测温频率地方,SDK中说只能1Hz,这这这…和功能名称 实时测温相差甚远啊!
然后继续翻SDK,有个手动测温功能,想着能否手动设置规则后手动触发测温,尝试NET_DVR_GetSTDAbility函数看下是否支持,直接给我返回错误码23,压根不支持这功能…
就在要放弃时候,仔细回想下:
- 相机可以通过网页端设置规则,那肯定相机是支持规则设定的;
- 查看网页端视频上的测温数据变化,频率非常快,毫无卡顿,不像600ms才一次,所以,测温数据肯定有高频率的,只是我没找到
带着这两疑问,咨询了海康技术,果然,在SDK之外,还隐藏着一些关卡,主要两个步骤:第一,使用透传功能模拟网页端操作,进行规则设定;第二,使用NET_DVR_GetDVRConfig手动获取规则测温结果。详细操作步骤如下:
使用透传修改测温规则
验证透传改测温规则
先看下我网页上手动设置的4个规则:
截图没截全,哈,只能看到3个,注意第二个的名称是“你好,测试”。
浏览器按F12,打开控制台,回到海康界面,点击规则的保存按钮,下图:
这时候,回到控制台,看下
注意这时候多了几个name,其中“1”就是需要的内容,点击打开,Headers内容如下,复制下来URL先存着,待会用:
Payload内容是xml格式,全复制下来,可以规整下,我没弄了:
现在打开SDK包库文件下的demo:
测试下透传能不能修改规则,下图操作步骤:
操作4中内容就是上面的URL,记得去掉IP,输入参数就是上面的XML内容,修改“你好,测试”为“你好,你好”,点击操作,绿框内收到相机返回responce OK。好了,确定可以透传修改规则,去浏览器确认下:
没问题,确实修改好了。其他规则,比如点、区域、是否启动,修改xml内容实现,看下内容很好理解。
上代码
打开SDK的MFC工程,开始扣代码:
NET_DVR_XML_CONFIG_INPUT struInput = { 0 };
NET_DVR_XML_CONFIG_OUTPUT struOuput = { 0 };
struInput.dwSize = sizeof(struInput);
struOuput.dwSize = sizeof(struOuput);
/* 传输XML */
char* pBuf = "<ThermometryScene><id>1</id><normalizedScreenSize><normalizedScreenWidth>1000</normalizedScreenWidth><normalizedScreenHeight>1000</normalizedScreenHeight></normalizedScreenSize><ThermometryRegionList><ThermometryRegion><id>1</id><enabled>false</enabled><name/><type>region</type><Region><RegionCoordinatesList><RegionCoordinates><positionX>1</positionX><positionY>997</positionY></RegionCoordinates><RegionCoordinates><positionX>992</positionX><positionY>995</positionY></RegionCoordinates><RegionCoordinates><positionX>994</positionX><positionY>4</positionY></RegionCoordinates><RegionCoordinates><positionX>3</positionX><positionY>0</positionY></RegionCoordinates></RegionCoordinatesList></Region><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>2</id><enabled>true</enabled><name>你好,测试</name><type>point</type><Point><CalibratingCoordinates><positionX>288</positionX><positionY>665</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>3</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>4</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>5</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>6</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>7</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>8</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>9</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>10</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>11</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>12</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>13</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>14</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>15</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>16</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>17</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion><ThermometryRegion><id>18</id><enabled>false</enabled><name/><type>point</type><Point><CalibratingCoordinates><positionX>500</positionX><positionY>500</positionY></CalibratingCoordinates></Point><distanceUnit>meter</distanceUnit></ThermometryRegion></ThermometryRegionList></ThermometryScene>";
char szUrl[256] = { 0 };
sprintf(szUrl, "PUT /ISAPI/Thermal/channels/1/thermometry/1");
memset(&struInput, 0, sizeof(struInput));
memset(&struOuput, 0, sizeof(struOuput));
struInput.dwSize = sizeof(struInput);
struOuput.dwSize = sizeof(struOuput);
struInput.lpRequestUrl = szUrl;
struInput.dwRequestUrlLen = strlen(szUrl);
struInput.lpInBuffer = pBuf;
struInput.dwInBufferSize = strlen(pBuf);
if (!NET_DVR_STDXMLConfig(lUserID, &struInput, &struOuput))
printf("error\n");
else
printf("success\n");
简单吧,就这几句,需要改规则,就自己调整pBuf内容。也可以把字符串存文件里去,然后每次修改文件后读取,看着舒服点。
更快的获取温度数据
没什么说的,直接看代码吧:
DWORD dwChannel = 1; //热成像通道
DWORD dwReturned = 0;
/*int m_RuleID = 2;*/
NET_DVR_THERMOMETRYRULE_TEMPERATURE_INFO m_struTempInfo;
memset(&m_struTempInfo, 0, sizeof(NET_DVR_THERMOMETRYRULE_TEMPERATURE_INFO));
GetLocalTime(&sys);
cout << "min:" << sys.wMinute << " , sec: " << sys.wSecond << " milSec:" << sys.wMilliseconds << endl;
for (int m_RuleID = 1; m_RuleID < 5; m_RuleID++)
{
if (!NET_DVR_GetDVRConfig(lUserID, NET_DVR_GET_THERMOMETRYRULE_TEMPERATURE_INFO, m_RuleID, &m_struTempInfo, sizeof(m_struTempInfo), &dwReturned))
{
printf("error code: %d\n", NET_DVR_GetLastError());
}
else
{
printf("success, m_RuleID: %d\n", m_RuleID);
/* m_DataList.InsertItem(iItemCount, Temp);
Temp.Format("%.1f", m_struTempInfo->fMaxTemperature);
m_DataList.SetItemText(iItemCount, 1, Temp);
Temp.Format("%.1f", m_struTempInfo->fMinTemperature);
m_DataList.SetItemText(iItemCount, 2, Temp);
Temp.Format("%.1f", m_struTempInfo->fAverageTemperature);
m_DataList.SetItemText(iItemCount, 3, Temp);
Temp.Format("%.3f", m_struTempInfo->struHighestPoint.fX);
m_DataList.SetItemText(iItemCount, 4, Temp);
Temp.Format("%.3f", m_struTempInfo->struHighestPoint.fY);
m_DataList.SetItemText(iItemCount, 5, Temp);
Temp.Format("%.3f", m_struTempInfo->struLowestPoint.fX);
m_DataList.SetItemText(iItemCount, 6, Temp);
Temp.Format("%.3f", m_struTempInfo->struLowestPoint.fY);
m_DataList.SetItemText(iItemCount, 7, Temp);
Temp.Format("%d", m_struTempInfo->byIsFreezedata);
m_DataList.SetItemText(iItemCount, 8, Temp);*/
}
}
GetLocalTime(&sys);
cout << "min:" << sys.wMinute << " , sec: " << sys.wSecond << " milSec:" << sys.wMilliseconds << endl;
就这样循环读了4次规则测试,试了大概10次,平均单次规则读取,用时大概50ms,这样也能达到20Hz测温频率了,完全够用。
现在,每次算法告诉我要测温哪里,我立即修改测温规则,手动获取下测温数据,50ms左右就可以有结果,完美!当然,对于一些不需要调整测温区域场合,比如某个设备温度监控,可以直接网页上设定好规则后,直接用第二大步代码进行测温。