海康相机 像素坐标(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); }