Merge branch 'develop' of http://222.212.85.86:8222/bdzl2/ai_project_v1 into develop
This commit is contained in:
commit
ee8733a0ce
File diff suppressed because it is too large
Load Diff
@ -3,10 +3,10 @@ from sanic import Blueprint, Request, json
|
|||||||
from sanic.response import text
|
from sanic.response import text
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
import logging
|
import logging
|
||||||
from earthwork_calculator_point_cloud import EarthworkCalculatorPointCloud
|
from b3dm.earthwork_calculator_point_cloud import EarthworkCalculatorPointCloud
|
||||||
# 导入计算模块
|
# 导入计算模块
|
||||||
from earthwork_calculator_3d_tiles import EarthworkCalculator3dTiles, AlgorithmType, EarthworkResult3dTiles
|
from b3dm.earthwork_calculator_3d_tiles import EarthworkCalculator3dTiles, AlgorithmType, EarthworkResult3dTiles
|
||||||
from tileset_data_source import TilesetDataSource
|
from b3dm.tileset_data_source import TilesetDataSource
|
||||||
|
|
||||||
earthwork_bp = Blueprint("earthwork", url_prefix="")
|
earthwork_bp = Blueprint("earthwork", url_prefix="")
|
||||||
|
|
||||||
|
|||||||
@ -70,9 +70,9 @@ class DracoGLBParser:
|
|||||||
extensions_required = self.json_data.get('extensionsRequired', [])
|
extensions_required = self.json_data.get('extensionsRequired', [])
|
||||||
|
|
||||||
if 'KHR_draco_mesh_compression' in extensions_used:
|
if 'KHR_draco_mesh_compression' in extensions_used:
|
||||||
print("✓ 使用 Draco 压缩")
|
print("使用 Draco 压缩")
|
||||||
if 'KHR_draco_mesh_compression' in extensions_required:
|
if 'KHR_draco_mesh_compression' in extensions_required:
|
||||||
print("⚠ Draco 压缩是必需的")
|
print("Draco 压缩是必需的")
|
||||||
|
|
||||||
# 网格信息
|
# 网格信息
|
||||||
meshes = self.json_data.get('meshes', [])
|
meshes = self.json_data.get('meshes', [])
|
||||||
@ -88,7 +88,7 @@ class DracoGLBParser:
|
|||||||
if 'extensions' in primitive:
|
if 'extensions' in primitive:
|
||||||
draco_info = primitive['extensions'].get('KHR_draco_mesh_compression')
|
draco_info = primitive['extensions'].get('KHR_draco_mesh_compression')
|
||||||
if draco_info:
|
if draco_info:
|
||||||
print(f" ✓ 使用 Draco 压缩")
|
print(f" 使用 Draco 压缩")
|
||||||
print(f" 属性: {draco_info.get('attributes', {})}")
|
print(f" 属性: {draco_info.get('attributes', {})}")
|
||||||
|
|
||||||
# 缓冲区信息
|
# 缓冲区信息
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# terrain3d_analyzer_color13
|
# slope_aspect_img13
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from scipy.ndimage import sobel
|
from scipy.ndimage import sobel
|
||||||
@ -376,5 +376,5 @@ def setup_chinese_font():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
dem_path = r'D:\devForBdzlWork\ai_project_v1\b3dm\test\o_dem_df67f1cc.tif'
|
dem_path = r'D:/devForBdzlWork/ai_project_v1/b3dm/o_dem_f1cb6f69_slopeAspect.tif'
|
||||||
read_slope_aspect_by_dem(dem_path)
|
read_slope_aspect_by_dem(dem_path)
|
||||||
@ -7,7 +7,8 @@ import time
|
|||||||
import uuid
|
import uuid
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import threading
|
import threading
|
||||||
from terrain_calculator import TerrainCalculator
|
import os
|
||||||
|
from b3dm.terrain_calculator import TerrainCalculator
|
||||||
|
|
||||||
terrain_bp = Blueprint("terrain", url_prefix="")
|
terrain_bp = Blueprint("terrain", url_prefix="")
|
||||||
MINIO_SUB_PATH = "slopeAspectPng"
|
MINIO_SUB_PATH = "slopeAspectPng"
|
||||||
@ -54,7 +55,6 @@ class PointItem(BaseModel):
|
|||||||
z: float = Field(..., description="z坐标")
|
z: float = Field(..., description="z坐标")
|
||||||
|
|
||||||
class PointRequest(BaseModel):
|
class PointRequest(BaseModel):
|
||||||
"""使用Pydantic HttpUrl类型的严格点批量请求模型"""
|
|
||||||
points: List[PointItem] = Field(..., description="点列表")
|
points: List[PointItem] = Field(..., description="点列表")
|
||||||
url: str = Field(..., description="URL地址")
|
url: str = Field(..., description="URL地址")
|
||||||
|
|
||||||
@ -64,6 +64,9 @@ class PointRequest(BaseModel):
|
|||||||
raise ValueError("批量处理最多支持10个点")
|
raise ValueError("批量处理最多支持10个点")
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
class PreloadRequest(BaseModel):
|
||||||
|
url: str = Field(..., description="URL地址")
|
||||||
|
|
||||||
class AnalysisConfig(BaseModel):
|
class AnalysisConfig(BaseModel):
|
||||||
"""分析配置"""
|
"""分析配置"""
|
||||||
classify: bool = Field(default=True, description="是否进行分类")
|
classify: bool = Field(default=True, description="是否进行分类")
|
||||||
@ -155,6 +158,42 @@ async def calculate_aspect1(request: Request):
|
|||||||
"success": False
|
"success": False
|
||||||
}, status=500)
|
}, status=500)
|
||||||
|
|
||||||
|
@terrain_bp.post("/api/v1/calculate/preload3dTiles")
|
||||||
|
async def preload_3dtiles(request: Request):
|
||||||
|
"""预加载3dtiles地图数据"""
|
||||||
|
try:
|
||||||
|
data = request.json
|
||||||
|
if not data:
|
||||||
|
return json({"error": "请求体不能为空"}, status=400)
|
||||||
|
|
||||||
|
# 验证输入
|
||||||
|
try:
|
||||||
|
vector = PreloadRequest(**data)
|
||||||
|
except Exception as e:
|
||||||
|
return json({"error": f"输入验证失败: {str(e)}"}, status=400)
|
||||||
|
|
||||||
|
# 创建并启动线程
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
thread1 = threading.Thread(target=TerrainCalculator.preload_3dtiles, args=(vector.url))
|
||||||
|
# 启动线程
|
||||||
|
thread1.start()
|
||||||
|
url_prefix = extract_and_rebuild_url(vector.url)
|
||||||
|
return json({
|
||||||
|
"success": True,
|
||||||
|
"data": f"{script_dir}/data_3dtiles",
|
||||||
|
"request": {
|
||||||
|
"input_vector": vector.model_dump(),
|
||||||
|
"timestamp": time.time()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"坡向计算API错误: {e}")
|
||||||
|
return json({
|
||||||
|
"error": f"服务器内部错误: {str(e)}",
|
||||||
|
"success": False
|
||||||
|
}, status=500)
|
||||||
|
|
||||||
@terrain_bp.post("/api/v1/calculate/slopeAspect")
|
@terrain_bp.post("/api/v1/calculate/slopeAspect")
|
||||||
async def calculate_slopeAspect(request: Request):
|
async def calculate_slopeAspect(request: Request):
|
||||||
"""生成坡向坡度俯视图"""
|
"""生成坡向坡度俯视图"""
|
||||||
@ -193,6 +232,44 @@ async def calculate_slopeAspect(request: Request):
|
|||||||
"success": False
|
"success": False
|
||||||
}, status=500)
|
}, status=500)
|
||||||
|
|
||||||
|
@terrain_bp.post("/api/v1/calculate/slopeAspectTif")
|
||||||
|
async def calculate_slopeAspect_tif(request: Request):
|
||||||
|
"""生成坡向坡度tif文件"""
|
||||||
|
try:
|
||||||
|
data = request.json
|
||||||
|
if not data:
|
||||||
|
return json({"error": "请求体不能为空"}, status=400)
|
||||||
|
|
||||||
|
# 验证输入
|
||||||
|
try:
|
||||||
|
vector = PointRequest(**data)
|
||||||
|
except Exception as e:
|
||||||
|
return json({"error": f"输入验证失败: {str(e)}"}, status=400)
|
||||||
|
|
||||||
|
# 生成坡向坡度俯视图
|
||||||
|
region_coords = [(point.x, point.y, point.z) for point in vector.points]
|
||||||
|
slope_aspect_tif_name = f"o_dem_{uuid.uuid4().hex[:8]}_slopeAspect.tif"
|
||||||
|
# 创建并启动线程
|
||||||
|
thread1 = threading.Thread(target=TerrainCalculator.generate_slopeAspect_tif, args=(region_coords, vector.url, slope_aspect_tif_name, MINIO_SUB_PATH))
|
||||||
|
# 启动线程
|
||||||
|
thread1.start()
|
||||||
|
url_prefix = extract_and_rebuild_url(vector.url)
|
||||||
|
return json({
|
||||||
|
"success": True,
|
||||||
|
"data": f"{url_prefix}/{MINIO_SUB_PATH}/{slope_aspect_tif_name}",
|
||||||
|
"request": {
|
||||||
|
"input_vector": vector.model_dump(),
|
||||||
|
"timestamp": time.time()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"坡向计算API错误: {e}")
|
||||||
|
return json({
|
||||||
|
"error": f"服务器内部错误: {str(e)}",
|
||||||
|
"success": False
|
||||||
|
}, status=500)
|
||||||
|
|
||||||
@terrain_bp.post("/api/v1/calculate/both")
|
@terrain_bp.post("/api/v1/calculate/both")
|
||||||
async def calculate_both(request: Request):
|
async def calculate_both(request: Request):
|
||||||
"""同时计算坡度和坡向"""
|
"""同时计算坡度和坡向"""
|
||||||
|
|||||||
@ -3,20 +3,23 @@ from typing import List, Tuple, Dict, Any
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
from data_3dtiles_manager import MinIO3DTilesManager
|
from b3dm.data_3dtiles_manager import MinIO3DTilesManager
|
||||||
import data_3dtiles_to_dem
|
import b3dm.data_3dtiles_to_dem as data_3dtiles_to_dem
|
||||||
import terrain3d_analyzer_color
|
import b3dm.slope_aspect_img as slope_aspect_img
|
||||||
|
import b3dm.slope_aspect_tif as slope_aspect_tif
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
ENDPOINT_URL = "222.212.85.86:9000"
|
||||||
|
ACCESS_KEY = "WuRenJi"
|
||||||
|
SECRET_KEY = "WRJ@2024"
|
||||||
|
|
||||||
|
|
||||||
class TerrainCalculator:
|
class TerrainCalculator:
|
||||||
"""地形坡度和坡向计算器"""
|
"""地形坡度和坡向计算器"""
|
||||||
|
|
||||||
def generate_slopeAspect_3d_overlook(region_coords, url, overall_3d_png_name, minio_sub_path) :
|
def preload_3dtiles(url) :
|
||||||
# 下载3dtiles地图数据
|
# 下载3dtiles地图数据
|
||||||
ENDPOINT_URL = "222.212.85.86:9000"
|
|
||||||
ACCESS_KEY = "WuRenJi"
|
|
||||||
SECRET_KEY = "WRJ@2024"
|
|
||||||
manager = MinIO3DTilesManager(
|
manager = MinIO3DTilesManager(
|
||||||
endpoint_url=ENDPOINT_URL,
|
endpoint_url=ENDPOINT_URL,
|
||||||
access_key=ACCESS_KEY,
|
access_key=ACCESS_KEY,
|
||||||
@ -26,7 +29,25 @@ class TerrainCalculator:
|
|||||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
success, entry_local_path = manager.download_full_tileset(
|
success, entry_local_path = manager.download_full_tileset(
|
||||||
tileset_url=url,
|
tileset_url=url,
|
||||||
save_dir=f"{script_dir}/data_3dtiles",
|
save_dir=f"data_3dtiles",
|
||||||
|
region_filter=None
|
||||||
|
)
|
||||||
|
if not success :
|
||||||
|
logger.info(f"下载地图数据失败: {url}")
|
||||||
|
return "下载地图数据失败", None
|
||||||
|
|
||||||
|
def generate_slopeAspect_3d_overlook(region_coords, url, overall_3d_png_name, minio_sub_path) :
|
||||||
|
# 下载3dtiles地图数据
|
||||||
|
manager = MinIO3DTilesManager(
|
||||||
|
endpoint_url=ENDPOINT_URL,
|
||||||
|
access_key=ACCESS_KEY,
|
||||||
|
secret_key=SECRET_KEY,
|
||||||
|
secure=False
|
||||||
|
)
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
success, entry_local_path = manager.download_full_tileset(
|
||||||
|
tileset_url=url,
|
||||||
|
save_dir=f"data_3dtiles",
|
||||||
region_filter=None
|
region_filter=None
|
||||||
)
|
)
|
||||||
if not success :
|
if not success :
|
||||||
@ -35,14 +56,14 @@ class TerrainCalculator:
|
|||||||
|
|
||||||
tileset_path = entry_local_path
|
tileset_path = entry_local_path
|
||||||
dem_path = os.path.join(script_dir, f"o_dem_{uuid.uuid4().hex[:8]}.tif")
|
dem_path = os.path.join(script_dir, f"o_dem_{uuid.uuid4().hex[:8]}.tif")
|
||||||
data_3dtiles_to_dem.generate_dem(region_coords, tileset_path, dem_path)
|
data_3dtiles_to_dem.generate_dem(tileset_path, dem_path, region_coords)
|
||||||
|
|
||||||
if not os.path.exists(dem_path) :
|
if not os.path.exists(dem_path) :
|
||||||
logger.info(f"生成坡度坡向俯视图失败: {url},{region_coords}")
|
logger.info(f"生成坡度坡向俯视图失败: {url},{region_coords}")
|
||||||
return "生成坡度坡向俯视图失败", None
|
return "生成坡度坡向俯视图失败", None
|
||||||
|
|
||||||
overall_3d_png_path = os.path.join(script_dir, overall_3d_png_name)
|
overall_3d_png_path = os.path.join(script_dir, overall_3d_png_name)
|
||||||
terrain3d_analyzer_color.read_slope_aspect_by_dem(dem_path, overall_3d_png_path)
|
slope_aspect_img.read_slope_aspect_by_dem(dem_path, overall_3d_png_path)
|
||||||
logger.info(f"生成成功: {url},{region_coords},{overall_3d_png_path}")
|
logger.info(f"生成成功: {url},{region_coords},{overall_3d_png_path}")
|
||||||
|
|
||||||
entry_bucket, _ = manager.parse_minio_url(url);
|
entry_bucket, _ = manager.parse_minio_url(url);
|
||||||
@ -52,6 +73,43 @@ class TerrainCalculator:
|
|||||||
else :
|
else :
|
||||||
return "生成失败", None
|
return "生成失败", None
|
||||||
|
|
||||||
|
def generate_slopeAspect_tif(region_coords, url, slope_aspect_tif_name, minio_sub_path) :
|
||||||
|
# 下载3dtiles地图数据
|
||||||
|
manager = MinIO3DTilesManager(
|
||||||
|
endpoint_url=ENDPOINT_URL,
|
||||||
|
access_key=ACCESS_KEY,
|
||||||
|
secret_key=SECRET_KEY,
|
||||||
|
secure=False
|
||||||
|
)
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
success, entry_local_path = manager.download_full_tileset(
|
||||||
|
tileset_url=url,
|
||||||
|
save_dir=f"data_3dtiles",
|
||||||
|
region_filter=None
|
||||||
|
)
|
||||||
|
if not success :
|
||||||
|
logger.info(f"下载地图数据失败: {url},{region_coords}")
|
||||||
|
return "下载地图数据失败", None
|
||||||
|
|
||||||
|
tileset_path = entry_local_path
|
||||||
|
dem_path = os.path.join(script_dir, f"o_dem_{uuid.uuid4().hex[:8]}.tif")
|
||||||
|
data_3dtiles_to_dem.generate_dem(tileset_path, dem_path, region_coords)
|
||||||
|
|
||||||
|
if not os.path.exists(dem_path) :
|
||||||
|
logger.info(f"生成坡度坡向俯视图失败: {url},{region_coords}")
|
||||||
|
return "生成坡度坡向俯视图失败", None
|
||||||
|
|
||||||
|
slope_aspect_tif_path = os.path.join(script_dir, slope_aspect_tif_name)
|
||||||
|
slope_aspect_tif.create_slope_aspect(dem_path, 'combined', slope_aspect_tif_path)
|
||||||
|
logger.info(f"生成成功: {url},{region_coords},{slope_aspect_tif_path}")
|
||||||
|
|
||||||
|
entry_bucket, _ = manager.parse_minio_url(url);
|
||||||
|
success, minio_path = manager.upload_file(entry_bucket, f"{minio_sub_path}/{slope_aspect_tif_name}", slope_aspect_tif_path)
|
||||||
|
if success :
|
||||||
|
return "生成成功", minio_path
|
||||||
|
else :
|
||||||
|
return "生成失败", None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate_vector(vector: List[float]) -> bool:
|
def validate_vector(vector: List[float]) -> bool:
|
||||||
"""验证输入向量是否有效"""
|
"""验证输入向量是否有效"""
|
||||||
|
|||||||
@ -38,6 +38,9 @@ from cv_back_video import startBackAIVideo
|
|||||||
from sanic_cors import CORS
|
from sanic_cors import CORS
|
||||||
|
|
||||||
from sanic import Sanic, Request
|
from sanic import Sanic, Request
|
||||||
|
# 引入其他模块
|
||||||
|
from b3dm.earthwork_api import earthwork_bp
|
||||||
|
from b3dm.terrain_api import terrain_bp
|
||||||
|
|
||||||
# 配置日志
|
# 配置日志
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
@ -313,6 +316,9 @@ async def heartbeat_monitor(task_manager: TaskManager):
|
|||||||
|
|
||||||
app = Sanic("YoloStreamService1")
|
app = Sanic("YoloStreamService1")
|
||||||
CORS(app)
|
CORS(app)
|
||||||
|
# 显式注册蓝图
|
||||||
|
app.blueprint(earthwork_bp)
|
||||||
|
app.blueprint(terrain_bp)
|
||||||
|
|
||||||
|
|
||||||
# 启动心跳监测
|
# 启动心跳监测
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user