Parcourir la source

250320-1代码。

baoyubo il y a 2 mois
Parent
commit
8629b4d283

+ 2 - 2
models/video_base.py

@@ -175,8 +175,8 @@ class TPVideoInfo(Base):
     cameraIndexCode = Column(String(100), primary_key=True, comment="摄像头索引码")
     gbIndexCode = Column(String(100), comment="国标索引码")
     name = Column(String(255), comment="摄像头名称")
-    longitude = Column(String(255), comment="经度")
-    latitude = Column(String(255), comment="纬度")
+    longitude = Column(Float, comment="经度")
+    latitude = Column(Float, comment="纬度")
     altitude = Column(String(255), comment="海拔")
     pixel = Column(String(50), comment="像素")
     cameraType = Column(String(50), comment="摄像头类型代码")

+ 3 - 1
routers/api/videoResource/__init__.py

@@ -6,6 +6,7 @@ from .videoinfo import router as videoinfo_router
 from .avcon import router as avcon_router
 from .wrjvideo import router as wrjvideo_router
 from .tag import router as tag_router
+from .location import router as location_router
 
 router = APIRouter()
 
@@ -13,4 +14,5 @@ router.include_router(hkvideo_router, prefix="/hkvideo")
 router.include_router(videoinfo_router, prefix="/videoinfo")
 router.include_router(tag_router, prefix="/tag")
 router.include_router(avcon_router, prefix="/avcon")
-router.include_router(wrjvideo_router, prefix="/wrjvideo")
+router.include_router(wrjvideo_router, prefix="/wrjvideo")
+router.include_router(location_router, prefix="/location")

+ 161 - 0
routers/api/videoResource/location/__init__.py

@@ -0,0 +1,161 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from fastapi import APIRouter, Request, Depends, Query, HTTPException, status
+from common.security import valid_access_token
+from fastapi.responses import JSONResponse
+from sqlalchemy.orm import Session
+from sqlalchemy import and_, or_
+from sqlalchemy.sql import func
+from sqlalchemy.future import select
+from common.auth_user import *
+from pydantic import BaseModel
+from database import get_db
+from typing import List
+from models import *
+from utils import *
+from utils.ry_system_util import *
+from utils.video_util import *
+from collections import defaultdict
+import traceback
+
+import json
+import time
+import math
+
+router = APIRouter()
+
+
+@router.get("/videos")
+async def get_videos(
+        zoom_level: int = Query(..., description="Zoom level for clustering"),
+        latitude_min: float = Query(..., description="Minimum latitude"),
+        latitude_max: float = Query(..., description="Maximum latitude"),
+        longitude_min: float = Query(..., description="Minimum longitude"),
+        longitude_max: float = Query(..., description="Maximum longitude"),
+        dict_value: str = Query(None),
+        db:  Session = Depends(get_db)
+):
+    try:
+        # 根据缩放级别动态调整分组粒度
+        distance_threshold = 1000 / (2 ** zoom_level)  # 例如:每缩放一级,距离阈值减半
+        que = True
+        print(time.time())
+        if dict_value:
+            tag_info = get_dict_data_info(db, 'video_type', dict_value)
+            if tag_info:
+                if tag_info.dict_label!='全量视频':
+                    videolist = [i.video_code for i in tag_get_video_tag_list(db,dict_value)]
+                    que =TPVideoInfo.gbIndexCode.in_(videolist)
+        # 查询分组
+        print("1",time.time())
+        query = (
+            select(
+                TPVideoInfo.cameraIndexCode,
+                TPVideoInfo.gbIndexCode,
+                TPVideoInfo.pixel,
+                TPVideoInfo.cameraType,
+                TPVideoInfo.cameraTypeName,
+                TPVideoInfo.installPlace,
+                TPVideoInfo.status,
+                TPVideoInfo.statusName,
+                TPVideoInfo.latitude,
+                TPVideoInfo.longitude,
+                TPVideoInfo.name,
+                func.ST_AsText(TPVideoInfo.location).label("location")
+            )
+            .select_from(TPVideoInfo).where(
+                and_(
+                    TPVideoInfo.latitude >= latitude_min,
+                    TPVideoInfo.latitude <= latitude_max,
+                    TPVideoInfo.longitude >= longitude_min,
+                    TPVideoInfo.longitude <= longitude_max,
+                    TPVideoInfo.longitude>0,
+                    TPVideoInfo.latitude>0,que
+                )
+            )
+            .order_by(TPVideoInfo.cameraIndexCode)
+        )
+
+        result = db.execute(query)
+        print("2",time.time())
+        videos = result.fetchall()
+        print("3",time.time())
+
+        # 动态分组逻辑
+        # groups = {}
+        groups = group_videos(videos, distance_threshold)
+        # for video in videos:
+        #     grouped = False
+        #     for group_id, group in list(groups.items()):
+        #         for v in group["videos"]:
+        #             distance = calculate_distance(video, v)
+        #             if distance < distance_threshold:
+        #                 groups[group_id]["videos"].append(video)
+        #                 groups[group_id]["count"] += 1
+        #                 grouped = True
+        #                 break
+        #         if grouped:
+        #             break
+        #     if not grouped:
+        #         group_id = video.cameraIndexCode
+        #         groups[group_id] = {"count": 1, "videos": [video]}
+
+        print("4",time.time())
+
+        return {"code": 200,
+                "msg": "操作成功",
+                "data": groups}
+    except Exception as e:
+        # 处理异常
+        traceback.print_exc()
+        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
+def calculate_grid_size(distance_threshold):
+    # 假设地球半径为6371公里,将距离阈值转换为经纬度的差值
+    # 这里假设纬度变化对距离的影响较小,仅根据经度计算网格大小
+    earth_radius = 6371  # 地球半径,单位为公里
+    grid_size = distance_threshold / earth_radius
+    return grid_size
+
+def get_grid_key(latitude, longitude, grid_size):
+    # 根据经纬度和网格大小计算网格键
+    return (math.floor(latitude / grid_size), math.floor(longitude / grid_size))
+
+def calculate_distance(video1, video2):
+    # 使用 Haversine 公式计算两点之间的距离
+    from math import radians, sin, cos, sqrt, atan2
+    R = 6371  # 地球半径(公里)
+    lat1, lon1 = radians(video1.latitude), radians(video1.longitude)
+    lat2, lon2 = radians(video2.latitude), radians(video2.longitude)
+    dlat = lat2 - lat1
+    dlon = lon2 - lon1
+    a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
+    c = 2 * atan2(sqrt(a), sqrt(1 - a))
+    return R * c
+
+def group_videos(videos, distance_threshold):
+    grid_size = calculate_grid_size(distance_threshold)
+    grid = defaultdict(list)
+    groups = {}
+
+    for video in videos:
+        grid_key = get_grid_key(video.latitude, video.longitude, grid_size)
+        grid[grid_key].append(video)
+
+    for grid_key, grid_videos in grid.items():
+        for video in grid_videos:
+            grouped = False
+            for group_id, group in list(groups.items()):
+                for v in group["videos"]:
+                    if calculate_distance(video, v) < distance_threshold:
+                        groups[group_id]["videos"].append(video)
+                        groups[group_id]["count"] += 1
+                        grouped = True
+                        break
+                if grouped:
+                    break
+            if not grouped:
+                group_id = video.cameraIndexCode
+                groups[group_id] = {"count": 1, "videos": [video]}
+
+    return groups