Java调用海康sdk操作热成像设备获取对应点温度
Java调用海康sdk操作热成像设备获取对应点温度, 海康官方提供有Java版的sdk,提供的ap根据c++版的开发文档自己写对应的java接口和类。下面的代码示例了通过海康的SDK获取热成像画面上某一点的具体温度。获取温度需要登陆摄像头web管理页面开启测温(在同一网段或者网络可通的pc浏览器上输入摄像头ip即可),不然SDK将无法获取温度。
代码地址点击获取最新代码
maven依赖
com.sun.jna jna 3.0.9
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import lombok.extern.slf4j.Slf4j;import java.nio.ByteBuffer;/*** 调用demo** @author JW* @version 1.0* @date 2021/3/25 14:47*/
@Slf4j
public class HKNetApp {private NativeLong lUserID = new NativeLong(-1);//用户句柄private HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo;//设备信息static HCNetSDK hCNetSDK = null;//sdkpublic static synchronized void loadLibrary(String libraryPath){if(null == hCNetSDK){hCNetSDK = (HCNetSDK) Native.loadLibrary(libraryPath, HCNetSDK.class);}}public static void main(String[] args) {loadLibrary("你的sdk地址");HKNetApp hkNetApp = new HKNetApp();if (hkNetApp.init() && hkNetApp.login()) {Float temperature = hkNetApp.getTemperature(new HKPoint(1,1), 126, 100);log.info("1,1点的温度是,{}", temperature);}hkNetApp.logout();hCNetSDK.NET_DVR_Cleanup();}/*** SDK初始化* @return*/public Boolean init() {if (!hCNetSDK.NET_DVR_Init()) {log.error("初始化失败");return false;}return true;}/*************************************************函数: "注册" 按钮单击响应函数函数描述: 注册登录设备*************************************************/public Boolean login() {//GEN-FIRST:event_jButtonLoginActionPerformed//注册之前先注销已注册的用户,预览情况下不可注销if (lUserID.longValue() > -1) {//先注销hCNetSDK.NET_DVR_Logout_V30(lUserID);}//注册m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();lUserID = hCNetSDK.NET_DVR_Login_V30("192.168.8.14", (short) 8000, "admin", "a1234567", m_strDeviceInfo);long userID = lUserID.longValue();boolean initSuc = hCNetSDK.NET_DVR_SetLogToFile(3, "f:\\sdklog\\", false);if (userID == -1) {log.error("登录失败,{}", userID);return false;}return true;}public void logout() {hCNetSDK.NET_DVR_Logout_V30(lUserID);}public Float getTemperature(HKPoint hkPoint, int sourceWidth, int sourceHeight) {boolean bRet = false;int nErr = 0;int erro;HCNetSDK.NET_DVR_THERMOMETRY_PRESETINFO m_struThermometryInfo = new HCNetSDK.NET_DVR_THERMOMETRY_PRESETINFO();m_struThermometryInfo.dwSize = m_struThermometryInfo.size();HCNetSDK.NET_DVR_THERMOMETRY_COND m_struThermometryCond = new HCNetSDK.NET_DVR_THERMOMETRY_COND();m_struThermometryCond.dwSize = m_struThermometryCond.size();m_struThermometryCond.dwChannel = 1;m_struThermometryCond.wPresetNo = 1;m_struThermometryCond.write();HCNetSDK.NET_DVR_STD_CONFIG struCfg = new HCNetSDK.NET_DVR_STD_CONFIG();struCfg.lpCondBuffer = m_struThermometryCond.getPointer();struCfg.dwCondSize = m_struThermometryCond.size();struCfg.lpOutBuffer = m_struThermometryInfo.getPointer();struCfg.dwOutSize = m_struThermometryInfo.size();HCNetSDK.BYTE_ARRAY m_szStatusBuf = new HCNetSDK.BYTE_ARRAY(4096 * 4);struCfg.lpStatusBuffer = m_szStatusBuf.getPointer();struCfg.dwStatusSize = 4096 * 4;struCfg.byDataType = 0;bRet = hCNetSDK.NET_DVR_GetSTDConfig(lUserID, 3624, struCfg);if (!bRet) {nErr = hCNetSDK.NET_DVR_GetLastError();log.error("NET_DVR_GetSTDConfig失败,{}", nErr);return 0f;}m_struThermometryInfo.dwSize = m_struThermometryInfo.size();m_struThermometryInfo.wPresetNo = 1;m_struThermometryInfo.struPresetInfo[0] = new HCNetSDK.NET_DVR_THERMOMETRY_PRESETINFO_PARAM();m_struThermometryInfo.struPresetInfo[0].byEnabled = 1;m_struThermometryInfo.struPresetInfo[0].byRuleID = 1;m_struThermometryInfo.struPresetInfo[0].wDistance = 10;m_struThermometryInfo.struPresetInfo[0].fEmissivity = (float) 0.9599;m_struThermometryInfo.struPresetInfo[0].byReflectiveEnabled = 0;m_struThermometryInfo.struPresetInfo[0].fReflectiveTemperature = 20;m_struThermometryInfo.struPresetInfo[0].byRuleCalibType = 2;//m_struThermometryInfo.struPresetInfo[0].szRuleName ="1";m_struThermometryInfo.struPresetInfo[0].byDistanceUnit = 0;//m_struThermometryInfo.struPresetInfo[0].byemissivityMode = 0;m_struThermometryInfo.struPresetInfo[0].struPoint = new HCNetSDK.NET_VCA_POINT();m_struThermometryInfo.struPresetInfo[0].struPoint.fX = 0;m_struThermometryInfo.struPresetInfo[0].struPoint.fY = 0;m_struThermometryInfo.struPresetInfo[0].struPoint.write();m_struThermometryInfo.struPresetInfo[0].struRegion = new HCNetSDK.NET_VCA_POLYGON();m_struThermometryInfo.struPresetInfo[0].struRegion.dwPointNum = 2;m_struThermometryInfo.struPresetInfo[0].struRegion.struPos[0] = new HCNetSDK.NET_VCA_POINT();m_struThermometryInfo.struPresetInfo[0].struRegion.struPos[0].fX = (float) 0.187;m_struThermometryInfo.struPresetInfo[0].struRegion.struPos[0].fY = (float) 0.6119;m_struThermometryInfo.struPresetInfo[0].struRegion.struPos[0].write();m_struThermometryInfo.struPresetInfo[0].struRegion.struPos[1] = new HCNetSDK.NET_VCA_POINT();m_struThermometryInfo.struPresetInfo[0].struRegion.struPos[1].fX = (float) 0.876;m_struThermometryInfo.struPresetInfo[0].struRegion.struPos[1].fY = (float) 0.569;m_struThermometryInfo.struPresetInfo[0].struRegion.struPos[1].write();m_struThermometryInfo.struPresetInfo[0].struRegion.write();m_struThermometryInfo.write();struCfg.lpInBuffer = m_struThermometryInfo.getPointer();struCfg.dwInSize = m_struThermometryInfo.size();boolean setSTDConfig = hCNetSDK.NET_DVR_SetSTDConfig(lUserID, 3625, struCfg);log.info("NET_DVR_SetSTDConfig,{}", setSTDConfig);HCNetSDK.NET_DVR_JPEGPICTURE_WITH_APPENDDATA m_strJpegWithAppenData = new HCNetSDK.NET_DVR_JPEGPICTURE_WITH_APPENDDATA();m_strJpegWithAppenData.dwSize = m_strJpegWithAppenData.size();m_strJpegWithAppenData.dwChannel = 1;HCNetSDK.BYTE_ARRAY ptrJpegByte = new HCNetSDK.BYTE_ARRAY(2 * 1024 * 1024);HCNetSDK.BYTE_ARRAY ptrP2PDataByte = new HCNetSDK.BYTE_ARRAY(2 * 1024 * 1024);m_strJpegWithAppenData.pJpegPicBuff = ptrJpegByte.getPointer();m_strJpegWithAppenData.pP2PDataBuff = ptrP2PDataByte.getPointer();bRet = hCNetSDK.NET_DVR_CaptureJPEGPicture_WithAppendData(lUserID, 2, m_strJpegWithAppenData);if (bRet) {//测温数据if (m_strJpegWithAppenData.dwP2PDataLen > 0) {HKPoint point = point2point(hkPoint, sourceWidth, sourceHeight, m_strJpegWithAppenData.dwJpegPicWidth, m_strJpegWithAppenData.dwJpegPicHeight);return getTemperature0(m_strJpegWithAppenData.pP2PDataBuff.getByteBuffer( (m_strJpegWithAppenData.dwJpegPicWidth * point.y + point.x) * 4, 4));}}return 0f;}private Float getTemperature0(ByteBuffer byteBuffer) {byte[] byTempData = new byte[4];byteBuffer.get(byTempData);int l = byTempData[0];l &= 0xff;l |= ((long) byTempData[1] << 8);l &= 0xffff;l |= ((long) byTempData[2] << 16);l &= 0xffffff;l |= ((long) byTempData[3] << 24);return Float.intBitsToFloat(l);}private HKPoint point2point(HKPoint points, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight) {points.x = points.x * sourceWidth / targetWidth;points.y = points.y * sourceHeight / targetHeight;points.x = points.x >= targetWidth ? targetWidth : points.x;points.x = points.x < 0 ? 0 : points.x;points.y = points.y >= targetHeight ? targetHeight : points.y;points.y = points.y < 0 ? 0 : points.y;return points;}
}
sdk接口类,因为官方demo代码较多这里只提取了需要使用的部分。
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;import java.util.Arrays;
import java.util.List;/*** 海康sdk调用接口*/
public interface HCNetSDK extends StdCallLibrary {/*** 常量*/int SERIALNO_LEN = 48; //序列号长度int NAME_LEN = 32; //用户名长度//methodboolean NET_DVR_Init();boolean NET_DVR_Cleanup();NativeLong NET_DVR_Login_V30(String sDVRIP, short wDVRPort, String sUserName, String sPassword, NET_DVR_DEVICEINFO_V30 lpDeviceInfo);boolean NET_DVR_Logout_V30(NativeLong lUserID);boolean NET_DVR_SetSTDConfig(NativeLong lUserID, int dwCommand, NET_DVR_STD_CONFIG lpInConfigParam);boolean NET_DVR_GetSTDConfig(NativeLong lUserID, int dwCommand, NET_DVR_STD_CONFIG lpOutConfigParam);boolean NET_DVR_CaptureJPEGPicture_WithAppendData(NativeLong lUserID, int lChannel, NET_DVR_JPEGPICTURE_WITH_APPENDDATA lpJpegWithAppend);int NET_DVR_GetLastError();//启用日志文件写入接口boolean NET_DVR_SetLogToFile(int bLogEnable, String strLogDir, boolean bAutoDel);//NET_DVR_Login_V30()参数结构class NET_DVR_DEVICEINFO_V30 extends Structure {public byte[] sSerialNumber = new byte[SERIALNO_LEN]; //序列号public byte byAlarmInPortNum; //报警输入个数public byte byAlarmOutPortNum; //报警输出个数public byte byDiskNum; //硬盘个数public byte byDVRType; //设备类型, 1:DVR 2:ATM DVR 3:DVS ......public byte byChanNum; //模拟通道个数public byte byStartChan; //起始通道号,例如DVS-1,DVR - 1public byte byAudioChanNum; //语音通道数public byte byIPChanNum; //最大数字通道个数public byte[] byRes1 = new byte[24]; //保留}class NET_DVR_THERMOMETRY_PRESETINFO extends Structure {public int dwSize;//结构体大小public short wPresetNo;//0-保留public byte[] byRes = new byte[2];public NET_DVR_THERMOMETRY_PRESETINFO_PARAM[] struPresetInfo = new NET_DVR_THERMOMETRY_PRESETINFO_PARAM[40];}class NET_DVR_THERMOMETRY_PRESETINFO_PARAM extends Structure {public byte byEnabled; //是否使能:0- 否,1- 是public byte byRuleID;//规则ID 0-表示无效,从1开始 (list内部判断数据有效性)public short wDistance;//距离(m)[0, 10000]public float fEmissivity;//发射率(发射率 精确到小数点后两位)[0.01, 1.00](即:物体向外辐射能量的本领)public byte byDistanceUnit;//距离单位: 0-米(m),1-英尺(feet),2-厘米(centimeter)public byte[] byRes = new byte[2];public byte byReflectiveEnabled;//反射温度使能:0- 否,1- 是public float fReflectiveTemperature;//反射温度 精确到小数后2位public byte[] szRuleName = new byte[NAME_LEN/*32*/];//规则名称public byte[] byRes1 = new byte[63];public byte byRuleCalibType;//规则标定类型 0-点,1-框,2-线public NET_VCA_POINT struPoint;//点测温坐标(当规则标定类型为"点"的时候生效)public NET_VCA_POLYGON struRegion;//区域、线(当规则标定类型为"框"或者"线"的时候生效)}class NET_VCA_POINT extends Structure {public float fX; // X轴坐标, 0.001~1public float fY; //Y轴坐标, 0.001~1}class NET_VCA_POLYGON extends Structure {public int dwPointNum; //有效点 大于等于3,若是3点在一条线上认为是无效区域,线交叉认为是无效区域public NET_VCA_POINT[] struPos = new NET_VCA_POINT[10]; //多边形边界点,最多十个}class NET_DVR_THERMOMETRY_COND extends Structure {public int dwSize;//结构体大小public int dwChannel;public short wPresetNo;//0-保留public byte[] byRes = new byte[62];}class NET_DVR_STD_CONFIG extends Structure {public Pointer lpCondBuffer; //[in]条件参数(结构体格式),例如通道号等.可以为NULLpublic int dwCondSize; //[in] lpCondBuffer指向的内存大小public Pointer lpInBuffer; //[in]输入参数(结构体格式),设置时不为NULL,获取时为NULLpublic int dwInSize; //[in] lpInBuffer指向的内存大小public Pointer lpOutBuffer; //[out]输出参数(结构体格式),获取时不为NULL,设置时为NULLpublic int dwOutSize; //[in] lpOutBuffer指向的内存大小public Pointer lpStatusBuffer; //[out]返回的状态参数(XML格式),获取成功时不会赋值,如果不需要,可以置NULLpublic int dwStatusSize; //[in] lpStatusBuffer指向的内存大小public Pointer lpXmlBuffer; //[in/out]byDataType = 1时有效,xml格式数据public int dwXmlSize; //[in/out]lpXmlBuffer指向的内存大小,获取时同时作为输入和输出参数,获取成功后会修改会实际长度,设置时表示实际长度,而不是整个内存大小public byte byDataType; //[in]输入/输出参数类型,0-使用结构体类型lpInBuffer/lpOutBuffer有效,1-使用XML类型lpXmlBuffer有效public byte[] byRes = new byte[23];}class BYTE_ARRAY extends Structure {public byte[] byValue;public BYTE_ARRAY(int iLen) {byValue = new byte[iLen];}@Overrideprotected List<String> getFieldOrder() {return Arrays.asList("byValue");}}//设备抓图附加全屏测温数据结构体class NET_DVR_JPEGPICTURE_WITH_APPENDDATA extends Structure {public int dwSize;public int dwChannel;//通道号public int dwJpegPicLen;//Jpeg图片长度public Pointer pJpegPicBuff;//Jpeg图片指针public int dwJpegPicWidth; // 图像宽度public int dwJpegPicHeight; //图像高度public int dwP2PDataLen;//全屏测温数据长度public Pointer pP2PDataBuff; //全屏测温数据指针public byte byIsFreezedata;//是否数据冻结 0-否 1-是public byte[] byRes = new byte[255];}
}
下面是运行结果:
