美文网首页
springboot 海康SDK抓图与车牌识别

springboot 海康SDK抓图与车牌识别

作者: 夜空最亮的9星 | 来源:发表于2023-11-21 17:22 被阅读0次

HkCameraParam

/**
 * 海康摄像头相关参数
 */
@Data
public class HkCameraParam {

//已登录设备的IP地址
    private String deviceIp;

//设备用户名
    private String username;

//设备密码
    private String password;

    private String nickname;
//端口号
    private Short port;
}

init 布防是为了自动抓图并识别车牌,

manualSnap 手动抓图是手动触发抓图并识别车牌。

take 简单抓图而已。



import com.slife.hikvision.config.HkCameraProperty;
import com.slife.hikvision.sdk.HCNetSDK;
import com.slife.hikvision.utils.*;
import com.slife.hikvision.domain.vo.HkCameraParam;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;

/**
 * 海康车牌摄像头初始化
 **/

@Slf4j
@Service
public class HkService {

    @Autowired
    private HkCameraProperty property;


    static HCNetSDK hCNetSDK = null;

    /**
     * 海康车牌摄像头初始化
     */
    @PostConstruct
    public void init() {
        List<HkCameraParam> cameraList = property.getCamera();

        for (HkCameraParam plateNumber :cameraList) {
            this.plateNumberInit(plateNumber.getDeviceIp(), plateNumber.getUsername(), plateNumber.getPassword(), plateNumber.getPort());

        }
    }

    /**
     * 海康车牌摄像头初始化
     */
    public void plateNumberInit(String deviceIp, String username, String password, Short port) {
        if (hCNetSDK == null) {
            if (!this.createSDKInstance()) {
                log.info("【海康车牌摄像头初始化】加载SDK失败");
                return;
            }
        }
        // 初始化
        if (!hCNetSDK.NET_DVR_Init()) {
            log.info("【海康车牌摄像头初始化】初始化失败");
            return;
        }
        log.info("【海康车牌摄像头初始化】初始化成功");
        // 设置连接时间与重连时间
        this.connect();
        // 设备信息
        int lUserID = this.login(deviceIp, username, password, port);
        if (lUserID < 0) {
            return;
        }
        // 启用布防
        this.setupAlarm(lUserID);
        // 设置报警回调函数
        new Thread(() -> {
            try {
                for (; ; ) {
                    this.setMessageCallBack();
                    Thread.sleep(2000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    /**
     * 动态库加载
     */
    private boolean createSDKInstance() {
        if (hCNetSDK == null) {
            synchronized (HCNetSDK.class) {
                String path;
                if (OsSelect.isWindows()) {
                    path = "\\HCNetSDK.dll";
                } else {
                    path = "/libhcnetsdk.so";
                }
                log.info("【海康初始化】LOAD_PATH: {}", property.getSdkPath() + path);
                hCNetSDK = (HCNetSDK) Native.loadLibrary(property.getSdkPath() + path, HCNetSDK.class);
                // linux系统建议调用以下接口加载组件库
                this.loadLinuxLib();
            }
        }
        return true;
    }

    /**
     * linux系统建议调用以下接口加载组件库
     */
    private void loadLinuxLib() {
        if (OsSelect.isWindows()) {
            return;
        }
        // linux系统建议调用以下接口加载组件库
        log.info("【海康初始化】linux系统加载组件库");
        HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
        HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
        //这里是库的绝对路径,请根据实际情况修改,注意改路径必须有访问权限
        String strPathCom = property.getSdkPath();
        String strPath1 = strPathCom + "/libcrypto.so.1.1";
        String strPath2 = strPathCom + "/libssl.so.1.1";

        System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
        ptrByteArray1.write();
        hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());

        System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
        ptrByteArray2.write();
        hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());

        HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
        System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
        struComPath.write();
        hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());
    }

    /**
     * 设置链接事件与重连时间
     */
    private void connect() {
        // 设置连接时间与重连时间
        hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
        hCNetSDK.NET_DVR_SetReconnect(10000, true);
    }

    /**
     * 注册设备
     */
    private int login(String deviceIp, String username, String password, Short port) {
        // 设备信息, 输出参数
        HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
        HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
        // 注册设备-登录参数,包括设备地址、登录用户、密码等
        m_strLoginInfo.sDeviceAddress = new byte[hCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        System.arraycopy(deviceIp.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, deviceIp.length());
        m_strLoginInfo.sUserName = new byte[hCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(username.getBytes(), 0, m_strLoginInfo.sUserName, 0, username.length());
        m_strLoginInfo.sPassword = new byte[hCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(password.getBytes(), 0, m_strLoginInfo.sPassword, 0, password.length());
        m_strLoginInfo.wPort = port;
        // 是否异步登录:0- 否,1- 是
        m_strLoginInfo.bUseAsynLogin = false;
        m_strLoginInfo.write();
        // 设备信息, 输出参数
        int lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (lUserID < 0) {
            log.info("【海康车牌摄像头初始化】注册登录失败: {}", hCNetSDK.NET_DVR_GetErrorMsg(null));
            hCNetSDK.NET_DVR_Cleanup();
            return -1;
        }

        return lUserID;
    }

    /**
     * 设置回调
     */
    private void setMessageCallBack() {
        // 设置报警回调函数
        hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(this::callback, null);
    }

    /**
     * 启用布防
     */
    private void setupAlarm(int lUserID) {
        // 启用布防
        HCNetSDK.NET_DVR_SETUPALARM_PARAM lpSetupParam = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
        lpSetupParam.dwSize = 0;
        // 布防优先级:0- 一等级(高),1- 二等级(中)
        lpSetupParam.byLevel = 1;
        // 上传报警信息类型: 0- 老报警信息(NET_DVR_PLATE_RESULT), 1- 新报警信息(NET_ITS_PLATE_RESULT)
        lpSetupParam.byAlarmInfoType = 1;
        int lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(lUserID, lpSetupParam);
        if (lAlarmHandle < 0) {
            log.info("【海康车牌摄像头初始化】启用布防失败: {}", hCNetSDK.NET_DVR_GetLastError());
            hCNetSDK.NET_DVR_Logout(lUserID);
            hCNetSDK.NET_DVR_Cleanup();
            return;
        }
        log.info("【海康车牌摄像头初始化】布防成功,开始监测车辆");
    }


    /**
     * 回调
     */
    public boolean callback(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
        log.info("【海康车牌摄像头回调】进入回调 开始识别车牌 lCommand: 0x{}", Integer.toHexString(lCommand));
        switch (lCommand) {
            case HCNetSDK.COMM_ITS_PLATE_RESULT:
                log.info("【海康车牌摄像头回调】交通抓拍的终端图片上传");
                HCNetSDK.NET_ITS_PLATE_RESULT strItsPlateResult = new HCNetSDK.NET_ITS_PLATE_RESULT();
                strItsPlateResult.write();
                Pointer pItsPlateInfo = strItsPlateResult.getPointer();
                pItsPlateInfo.write(0, pAlarmInfo.getByteArray(0, strItsPlateResult.size()), 0, strItsPlateResult.size());
                strItsPlateResult.read();
                try {

                    String license = new String(strItsPlateResult.struPlateInfo.sLicense, "GBK");
                    // 车型识别:0- 未知,1- 客车(大型),2- 货车(大型),3- 轿车(小型),4- 非机动车
                    String host = new String(pAlarmer.sDeviceIP).trim();//ip地址
                    String type = strItsPlateResult.byVehicleType + "".trim();
                    String plateNumber = license.substring(1).trim();
                    String byCountry = license.substring(1, 2).trim();
                    String byColor = license.substring(0, 1).trim();

                    log.info("【海康车牌摄像头回调】ip地址: {}", host);
                    log.info("【海康车牌摄像头回调】车辆类型: {}", type);
                    log.info("【海康车牌摄像头回调】车牌号: {}", plateNumber);
                    log.info("【海康车牌摄像头回调】车牌省份: {}", byCountry);
                    log.info("【海康车牌摄像头回调】车牌颜色: {}", byColor);

                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                break;
        }
        return true;
    }


    /**
     * 写到本地
     */
    private String writeFile(byte[] bs, String suffix) {
        String path = property.getImgPath()+File.separator+DateUtils.getDate().replace("-","");
        FileUtils.checkDirExists(path);
        String filename =path +File.separator + DateUtils.getDateTimeString() + "_" + suffix + ".jpg";//, path = property.getImgPath() + filename;

        File file = new File(filename);

        try (FileOutputStream fos = new FileOutputStream(file);
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            bos.write(bs);
        } catch (Exception e) {
            log.error("【海康摄像头写入图片失败】", e);
            return null;
        }
        return filename;
    }



    /**
     * 海康SDK手动抓拍并获取车牌
     */
    public void manualSnap(HkCameraParam camera) {
        // 设备信息
        int lUserID = this.cameraInit(camera.getDeviceIp(), camera.getUsername(), camera.getPassword(), camera.getPort());
        HCNetSDK.NET_DVR_PLATE_RESULT struPlateResultInfo = new HCNetSDK.NET_DVR_PLATE_RESULT();
        struPlateResultInfo.pBuffer1 =  new Memory(2 * 1024 * 1024);
        struPlateResultInfo.pBuffer2 =  new Memory( 1024 * 1024);
        HCNetSDK.NET_DVR_MANUALSNAP struInter = new HCNetSDK.NET_DVR_MANUALSNAP();
        struInter.byLaneNo = 1;

        boolean flag = hCNetSDK.NET_DVR_ManualSnap(lUserID, struInter, struPlateResultInfo);

        if (flag){
            String license = null;
            try {

                byte[] byteArray = struPlateResultInfo.pBuffer1.getByteArray(0, struPlateResultInfo.dwPicLen);

                // img1 车辆场景图片(大图)
                String img1 = writeFile(byteArray, camera.getDeviceIp().substring(camera.getDeviceIp().lastIndexOf(".") + 1) + "_s");
                byte[] byteArray1 = struPlateResultInfo.pBuffer2.getByteArray(0, struPlateResultInfo.dwPicLen);

                // img2 车牌图片(小图)
                String img2 = writeFile(byteArray1, camera.getDeviceIp().substring(camera.getDeviceIp().lastIndexOf(".") + 1) + "_p");
                license = new String(struPlateResultInfo.struPlateInfo.sLicense, "GBK");
                String plateNumber = license.substring(1).trim();
                String byCountry = license.substring(1, 2).trim();
                String byColor = license.substring(0, 1).trim();
                String byType = struPlateResultInfo.byVehicleType + "".trim();
                String carType = CarType.getCarType(byType);
                log.info("【海康车牌摄像头回调】车牌号: {}", plateNumber);
                log.info("【海康车牌摄像头回调】车牌省份: {}", byCountry);
                log.info("【海康车牌摄像头回调】车牌颜色: {}", byColor);
                log.info("【海康车牌摄像头回调】车牌类型: {}", carType);
                log.info("【海康车牌摄像头回调】场景图片: {}", img1);
                log.info("【海康车牌摄像头回调】车牌图片: {}", img2);
                hCNetSDK.NET_DVR_Logout(lUserID);
                hCNetSDK.NET_DVR_Cleanup();



            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }




    }

    /**
     * 海康全彩摄像头初始化
     */
    private int cameraInit(String deviceIp, String username, String password, Short port) {
        if (hCNetSDK == null) {
            if (!this.createSDKInstance()) {
                log.info("【海康全彩摄像头】加载SDK失败");
                return -1;
            }
        }
        // 初始化
        if (!hCNetSDK.NET_DVR_Init()) {
            log.info("【海康全彩摄像头】初始化失败");
            return -1;
        }
        log.info("【海康全彩摄像头】初始化成功");
        // 设备信息
        return this.login(deviceIp, username, password, port);
    }

    /**
     * 手动抓图
     * @param camera
     */
    public void take(HkCameraParam camera){
        int lUserID = this.cameraInit(camera.getDeviceIp(), camera.getUsername(), camera.getPassword(), camera.getPort());
        String img = this.writeFile(this.takePhoto(lUserID), camera.getDeviceIp().substring(camera.getDeviceIp().lastIndexOf(".") + 1));
        hCNetSDK.NET_DVR_Logout(lUserID);
        hCNetSDK.NET_DVR_Cleanup();
        log.info("文件保存路径:"+img);
    }

    /**
     * 海康全彩摄像头拍照
     */
    private byte[] takePhoto(int lUserID) {
        // JPEG图像参数
        HCNetSDK.NET_DVR_JPEGPARA lpJpegPara = new HCNetSDK.NET_DVR_JPEGPARA();
        // 设置图片的分辨率
        lpJpegPara.wPicSize = 2;
        // 设置图片质量
        lpJpegPara.wPicQuality = 0;
        // 通道号、输入缓冲区大小
        int channel = 1, dwPicSize = 1024 * 1024;
        // 保存JPEG数据的缓冲区
        Pointer sJpegPicBuffer = new Memory(dwPicSize);
        // 返回图片数据的大小
        IntByReference reference = new IntByReference();
        // 抓拍
        hCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(lUserID, channel, lpJpegPara, sJpegPicBuffer, dwPicSize, reference);
        // 图片大小
        int value = reference.getValue();
        log.info("【海康全彩摄像头】图片大小: {}", value);
        // 图片byte
        return sJpegPicBuffer.getByteArray(0, value);
    }
}

相关文章

网友评论

      本文标题:springboot 海康SDK抓图与车牌识别

      本文链接:https://www.haomeiwen.com/subject/tjzbwdtx.html