Java調(diào)用海康sdk操作熱成像設(shè)備獲取對(duì)應(yīng)點(diǎn)溫度轴捎, 汉缀校康官方提供有Java版的sdk蚕脏,遺憾的是里面提供的api比較舊了新版的api需要根據(jù)c++版的開(kāi)發(fā)文檔自己寫(xiě)對(duì)應(yīng)的java接口和類。這對(duì)于不熟悉c++的開(kāi)發(fā)人員比較吃力侦锯。下面的代碼示例了通過(guò)和毡蓿康的SDK獲取熱成像畫(huà)面上某一點(diǎn)的具體溫度。目前已經(jīng)使用Python實(shí)現(xiàn)了相應(yīng)的效果尺碰,有需要Python版本的可以留言挣棕。
maven依賴
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>3.0.9</version>
</dependency>
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import lombok.extern.slf4j.Slf4j;
import java.nio.ByteBuffer;
/**
* 調(diào)用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;//設(shè)備信息
static HCNetSDK hCNetSDK = null;//sdk
public 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點(diǎn)的溫度是,{}", temperature);
}
hkNetApp.logout();
hCNetSDK.NET_DVR_Cleanup();
}
/**
* SDK初始化
* @return
*/
public Boolean init() {
if (!hCNetSDK.NET_DVR_Init()) {
log.error("初始化失敗");
return false;
}
return true;
}
/*************************************************
函數(shù): "注冊(cè)" 按鈕單擊響應(yīng)函數(shù)
函數(shù)描述: 注冊(cè)登錄設(shè)備
*************************************************/
public Boolean login() {//GEN-FIRST:event_jButtonLoginActionPerformed
//注冊(cè)之前先注銷已注冊(cè)的用戶,預(yù)覽情況下不可注銷
if (lUserID.longValue() > -1) {
//先注銷
hCNetSDK.NET_DVR_Logout_V30(lUserID);
}
//注冊(cè)
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) {
//測(cè)溫?cái)?shù)據(jù)
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接口類亲桥,因?yàn)楣俜絛emo代碼較多這里只提取了需要使用的部分洛心。
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調(diào)用接口
*/
public interface HCNetSDK extends StdCallLibrary {
/**
* 常量
*/
int SERIALNO_LEN = 48; //序列號(hào)長(zhǎng)度
int NAME_LEN = 32; //用戶名長(zhǎng)度
//method
boolean 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();
//啟用日志文件寫(xiě)入接口
boolean NET_DVR_SetLogToFile(int bLogEnable, String strLogDir, boolean bAutoDel);
//NET_DVR_Login_V30()參數(shù)結(jié)構(gòu)
class NET_DVR_DEVICEINFO_V30 extends Structure {
public byte[] sSerialNumber = new byte[SERIALNO_LEN]; //序列號(hào)
public byte byAlarmInPortNum; //報(bào)警輸入個(gè)數(shù)
public byte byAlarmOutPortNum; //報(bào)警輸出個(gè)數(shù)
public byte byDiskNum; //硬盤(pán)個(gè)數(shù)
public byte byDVRType; //設(shè)備類型, 1:DVR 2:ATM DVR 3:DVS ......
public byte byChanNum; //模擬通道個(gè)數(shù)
public byte byStartChan; //起始通道號(hào),例如DVS-1,DVR - 1
public byte byAudioChanNum; //語(yǔ)音通道數(shù)
public byte byIPChanNum; //最大數(shù)字通道個(gè)數(shù)
public byte[] byRes1 = new byte[24]; //保留
}
class NET_DVR_THERMOMETRY_PRESETINFO extends Structure {
public int dwSize;//結(jié)構(gòu)體大小
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;//規(guī)則ID 0-表示無(wú)效词身,從1開(kāi)始 (list內(nèi)部判斷數(shù)據(jù)有效性)
public short wDistance;//距離(m)[0, 10000]
public float fEmissivity;//發(fā)射率(發(fā)射率 精確到小數(shù)點(diǎn)后兩位)[0.01, 1.00](即:物體向外輻射能量的本領(lǐng))
public byte byDistanceUnit;//距離單位: 0-米(m),1-英尺(feet),2-厘米(centimeter)
public byte[] byRes = new byte[2];
public byte byReflectiveEnabled;//反射溫度使能:0- 否番枚,1- 是
public float fReflectiveTemperature;//反射溫度 精確到小數(shù)后2位
public byte[] szRuleName = new byte[NAME_LEN/*32*/];//規(guī)則名稱
public byte[] byRes1 = new byte[63];
public byte byRuleCalibType;//規(guī)則標(biāo)定類型 0-點(diǎn)法严,1-框,2-線
public NET_VCA_POINT struPoint;//點(diǎn)測(cè)溫坐標(biāo)(當(dāng)規(guī)則標(biāo)定類型為"點(diǎn)"的時(shí)候生效)
public NET_VCA_POLYGON struRegion;//區(qū)域户辫、線(當(dāng)規(guī)則標(biāo)定類型為"框"或者"線"的時(shí)候生效)
}
class NET_VCA_POINT extends Structure {
public float fX; // X軸坐標(biāo), 0.001~1
public float fY; //Y軸坐標(biāo), 0.001~1
}
class NET_VCA_POLYGON extends Structure {
public int dwPointNum; //有效點(diǎn) 大于等于3渐夸,若是3點(diǎn)在一條線上認(rèn)為是無(wú)效區(qū)域,線交叉認(rèn)為是無(wú)效區(qū)域
public NET_VCA_POINT[] struPos = new NET_VCA_POINT[10]; //多邊形邊界點(diǎn),最多十個(gè)
}
class NET_DVR_THERMOMETRY_COND extends Structure {
public int dwSize;//結(jié)構(gòu)體大小
public int dwChannel;
public short wPresetNo;//0-保留
public byte[] byRes = new byte[62];
}
class NET_DVR_STD_CONFIG extends Structure {
public Pointer lpCondBuffer; //[in]條件參數(shù)(結(jié)構(gòu)體格式),例如通道號(hào)等.可以為NULL
public int dwCondSize; //[in] lpCondBuffer指向的內(nèi)存大小
public Pointer lpInBuffer; //[in]輸入?yún)?shù)(結(jié)構(gòu)體格式),設(shè)置時(shí)不為NULL渔欢,獲取時(shí)為NULL
public int dwInSize; //[in] lpInBuffer指向的內(nèi)存大小
public Pointer lpOutBuffer; //[out]輸出參數(shù)(結(jié)構(gòu)體格式),獲取時(shí)不為NULL,設(shè)置時(shí)為NULL
public int dwOutSize; //[in] lpOutBuffer指向的內(nèi)存大小
public Pointer lpStatusBuffer; //[out]返回的狀態(tài)參數(shù)(XML格式),獲取成功時(shí)不會(huì)賦值,如果不需要,可以置NULL
public int dwStatusSize; //[in] lpStatusBuffer指向的內(nèi)存大小
public Pointer lpXmlBuffer; //[in/out]byDataType = 1時(shí)有效,xml格式數(shù)據(jù)
public int dwXmlSize; //[in/out]lpXmlBuffer指向的內(nèi)存大小,獲取時(shí)同時(shí)作為輸入和輸出參數(shù)墓塌,獲取成功后會(huì)修改會(huì)實(shí)際長(zhǎng)度,設(shè)置時(shí)表示實(shí)際長(zhǎng)度奥额,而不是整個(gè)內(nèi)存大小
public byte byDataType; //[in]輸入/輸出參數(shù)類型,0-使用結(jié)構(gòu)體類型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];
}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("byValue");
}
}
//設(shè)備抓圖附加全屏測(cè)溫?cái)?shù)據(jù)結(jié)構(gòu)體
class NET_DVR_JPEGPICTURE_WITH_APPENDDATA extends Structure {
public int dwSize;
public int dwChannel;//通道號(hào)
public int dwJpegPicLen;//Jpeg圖片長(zhǎng)度
public Pointer pJpegPicBuff;//Jpeg圖片指針
public int dwJpegPicWidth; // 圖像寬度
public int dwJpegPicHeight; //圖像高度
public int dwP2PDataLen;//全屏測(cè)溫?cái)?shù)據(jù)長(zhǎng)度
public Pointer pP2PDataBuff; //全屏測(cè)溫?cái)?shù)據(jù)指針
public byte byIsFreezedata;//是否數(shù)據(jù)凍結(jié) 0-否 1-是
public byte[] byRes = new byte[255];
}
}
下面是運(yùn)行結(jié)果: