wzh преди 1 седмица
родител
ревизия
abe79d206c
променени са 2 файла, в които са добавени 75 реда и са изтрити 6 реда
  1. 37 3
      pixel_to_lonlat.py
  2. 38 3
      video_location.py

+ 37 - 3
pixel_to_lonlat.py

@@ -10,6 +10,29 @@ from scipy.spatial.transform import Rotation as R
 
 # --- 核心函数 ---
 
+def compute_hfov_by_zoom(hfov_max, zoom, camera_type="dahua"):
+    """
+    将缩放等级(zoom)映射为水平视场角(hfov)。
+    规则:
+    - 最小zoom对应最大视场角(hfov_max)
+    - 最大zoom对应最小视场角(hfov_max * min_zoom / max_zoom)
+    """
+    if zoom is None:
+        return hfov_max
+    camera_type = (camera_type or "dahua").lower()
+    if camera_type in ("hik", "hikvision", "hk", "haikang", "海康"):
+        min_zoom, max_zoom = 1.0, 56.0
+    else:
+        min_zoom, max_zoom = 0.4375, 56.0
+
+    z = float(zoom)
+    if z < min_zoom:
+        z = min_zoom
+    elif z > max_zoom:
+        z = max_zoom
+
+    return hfov_max * (min_zoom / z)
+
 def pixel_to_lonlat(u, v, camera_params, ptz_params):
     """
     正向投影:将像素坐标(u, v)转换为经纬度。
@@ -26,7 +49,16 @@ def pixel_to_lonlat(u, v, camera_params, ptz_params):
     # --- 1. 解包所有已知参数 ---
     res_w, res_h = int(camera_params['resolution_w']), int(camera_params['resolution_h'])
     cam_lon, cam_lat = float(camera_params['cam_lon']), float(camera_params['cam_lat'])
-    cam_height, hfov =float( camera_params['height']), float(camera_params['hfov'])
+    cam_height = float(camera_params['height'])
+    hfov_max = float(camera_params['hfov'])
+    zoom_value = ptz_params.get('z')
+    if zoom_value is None:
+        zoom_value = ptz_params.get('zoom')
+    hfov = compute_hfov_by_zoom(
+        hfov_max=hfov_max,
+        zoom=zoom_value,
+        camera_type=camera_params.get('camera_type', 'dahua')
+    )
     north_p = float(camera_params['north_p_value'])
     p, t = float(ptz_params['pan']), float(ptz_params['tilt'])
 
@@ -88,14 +120,16 @@ if __name__ == '__main__':
         "resolution_h": 720,
         "cam_lon": 112.893799,
         "cam_lat": 28.221701,
-        "north_p_value": 39.0
+        "north_p_value": 39.0,
+        "camera_type": "dahua",
     }
 
     # --- 2. 定义摄像头当前的云台状态 ---
     # 在您的实际应用中,这些值应该是从摄像头API实时读取的
     CURRENT_PTZ_PARAMS = {
         "pan": 271.9,
-        "tilt": 26.2
+        "tilt": 26.2,
+        "z": 0.4375
     }
 
     # --- 3. 指定您想要查询的屏幕像素坐标 ---

+ 38 - 3
video_location.py

@@ -23,6 +23,31 @@ def lonlat_to_enu(lon, lat, center_lon, center_lat):
     y = EARTH_RADIUS * delta_lat
     return np.array([x, y, 0])
 
+def compute_hfov_by_zoom(hfov_max, zoom, camera_type="dahua"):
+    """
+    将缩放等级(zoom)映射为水平视场角(hfov)。
+    规则:
+    - 最小zoom对应最大视场角(hfov_max)
+    - 最大zoom对应最小视场角(hfov_max * min_zoom / max_zoom)
+    """
+    if zoom is None:
+        return hfov_max
+    camera_type = (camera_type or "dahua").lower()
+    if camera_type in ("hik", "hikvision", "hk", "haikang", "海康"):
+        min_zoom, max_zoom = 1.0, 56.0
+    else:
+        min_zoom, max_zoom = 0.4375, 56.0
+
+    # clamp zoom to valid range
+    z = float(zoom)
+    if z < min_zoom:
+        z = min_zoom
+    elif z > max_zoom:
+        z = max_zoom
+
+    # assume hfov scales inversely with zoom
+    return hfov_max * (min_zoom / z)
+
 def project_lonlat_to_pixel(target_lon, target_lat, resolution_w, resolution_h,
                             cam_lon, cam_lat, cam_height, p, t, hfov, north_p_value=0.0):
     """
@@ -137,8 +162,16 @@ def process_geojson_for_frontend(geojson_data, camera_params, calibrated_params)
     if len(geo_coords) > 1 and geo_coords[0] != geo_coords[-1]:
         geo_coords.append(geo_coords[0]) # 确保多边形闭合
 
-    full_params = {**camera_params, **calibrated_params}
     raw_pixel_points = []
+    hfov_max = float(calibrated_params['hfov'])
+    zoom_value = camera_params.get('z')
+    if zoom_value is None:
+        zoom_value = camera_params.get('zoom')
+    hfov = compute_hfov_by_zoom(
+        hfov_max=hfov_max,
+        zoom=zoom_value,
+        camera_type=camera_params.get('camera_type', 'dahua')
+    )
     # 1. Batch convert all geographic points to pixel points
     for lon, lat in geo_coords:
         u, v, is_visible = project_lonlat_to_pixel(
@@ -146,7 +179,7 @@ def process_geojson_for_frontend(geojson_data, camera_params, calibrated_params)
             resolution_w=int(camera_params['resolution_w']), resolution_h=int(camera_params['resolution_h']),
             cam_lon=float(camera_params['cam_lon']), cam_lat=float(camera_params['cam_lat']),
             cam_height=float(calibrated_params['cam_height']), p=float(camera_params['p']),
-            t=float(camera_params['t']), hfov=float(calibrated_params['hfov']),
+            t=float(camera_params['t']), hfov=hfov,
             north_p_value=float(camera_params['north_p_value'])
         )
         raw_pixel_points.append([int(u), int(v)])
@@ -238,7 +271,9 @@ if __name__ == '__main__':
     camera_params = {
         "resolution_w": 1280, "resolution_h": 720,
         "cam_lon": 112.893799, "cam_lat": 28.221701,
-        "north_p_value": 39.0, "p": 271.9, "t": 26.2
+        "north_p_value": 39.0, "p": 271.9, "t": 26.2,
+        "camera_type": "dahua",
+        "z": 0.4375
     }
 
     final_screen_segments = process_geojson_for_frontend(geojson_data, camera_params, calibrated_params)