基于当前相机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);
}