海康相机 像素坐标(px,py)到sdk ptz 坐标转换最后到onvif ptz坐标

                                     基于当前相机PTZ位置的相对定位坐标计算

// ONVIF 坐标转为 SDK 坐标
    public Map<String, Double> ONvifFPtzToSdk(Map<String, Float> posOnvif) {
        Map<String, Double> posSdk = new HashMap<>();
        double panSdk = Math.min(180 * posOnvif.get("pan") + 180, 360);
        double tiltSdk = 45 * posOnvif.get("tilt") + 45;
        double zoomSdk = 3 * posOnvif.get("zoom") + 1;
        posSdk.put("pan", panSdk);
        posSdk.put("tilt", tiltSdk);
        posSdk.put("zoom", zoomSdk);
        return posSdk;
    }

    // SDK 坐标转为 ONVIF 坐标
    public Map<String, Float> SDKPtzToOnvif(Map<String, Double> posSdk) {
        Map<String, Float> posOnvif = new HashMap<>();
        float panOnvif = (float) ((posSdk.get("pan") - 180) / 180);
        float tiltOnvif = (float) ((posSdk.get("tilt") - 45) / 45);
        float zoomOnvif = (float) ((posSdk.get("zoom") - 1) / 3);
        posOnvif.put("pan", panOnvif);
        posOnvif.put("tilt", tiltOnvif);
        posOnvif.put("zoom", zoomOnvif);
        return posOnvif;
    }
    /****
     *
     * @param targetX 像素坐标
     * @param targetY 像素坐标
     * @param posOnvif
     * @return
     */
    public Map<String, Float> locate(int targetX, int targetY,  Map<String, Float>  posOnvif) {
        // 将 ONVIF 坐标转换为 SDK 坐标
        Map<String, Double> posSdk = ONvifFPtzToSdk(posOnvif);
        //Map<String, Double> posOnvif  onvif 获取当前状态下的 ptz 坐标
        // 直接使用 posOnvif 来计算 SDK 坐标
        // 水平视场角(参照《视场角相关计算》,通过相机标定,获取像素焦)
        double fovH = 37.75;

        double fovV = 21.80; // 垂直视场角
        int width = 2560;    // 图像宽度
        int height = 1440;   // 图像高度

        // 计算水平方向的偏移量 deltX
        double deltX = 0;
        if (targetX > (width / 2)) {
            deltX = Math.toDegrees(Math.atan((targetX - width / 2) / (width / 2) * Math.tan(Math.toRadians(fovH / 2))));
        } else {
            deltX = -Math.toDegrees(Math.atan((width / 2 - targetX) / (width / 2) * Math.tan(Math.toRadians(fovH / 2))));
        }

        // 计算垂直方向的偏移量 deltY
        double deltY = 0;
        if (targetY > (height / 2)) {
            deltY = Math.toDegrees(Math.atan((targetY - height / 2) / (height / 2) * Math.tan(Math.toRadians(fovV / 2))));
        } else {
            deltY = -Math.toDegrees(Math.atan((height / 2 - targetY) / (height / 2) * Math.tan(Math.toRadians(fovV / 2))));
        }

        // 更新 SDK 的 PTZ 坐标
        posSdk.put("pan", posSdk.get("pan") + deltX);
        posSdk.put("tilt", posSdk.get("tilt") - deltY); // 注意:SDK 是倒置的,所以需要减去 deltY
        
        // 将 SDK 坐标转换回 ONVIF 坐标
        return SDKPtzToOnvif(posSdk);
    }
  

  

posted @ 2024-11-08 05:50  Fitz  阅读(33)  评论(0编辑  收藏  举报