diff --git a/odm_preprocess.py b/odm_preprocess.py index cc07a99..3c4a5ce 100644 --- a/odm_preprocess.py +++ b/odm_preprocess.py @@ -298,8 +298,8 @@ class ImagePreprocessor: self.cluster() self.filter_isolated_points() self.filter_time_group_overlap() - center_lat, center_lon = self.calculate_center_coordinates() # self.filter_alternate_images() + center_lat, center_lon = self.calculate_center_coordinates() grid_points, translations = self.divide_grids() self.copy_images(grid_points) self.logger.info("预处理任务完成") diff --git a/odm_preprocess_fast.py b/odm_preprocess_fast.py index d97a795..805dc88 100644 --- a/odm_preprocess_fast.py +++ b/odm_preprocess_fast.py @@ -4,10 +4,7 @@ from datetime import timedelta from dataclasses import dataclass from typing import Dict, Tuple import psutil - -import matplotlib.pyplot as plt import pandas as pd -from tqdm import tqdm from filter.cluster_filter import GPSCluster from filter.time_group_overlap_filter import TimeGroupOverlapFilter @@ -20,6 +17,7 @@ from utils.visualizer import FilterVisualizer from post_pro.merge_tif import MergeTif from post_pro.merge_obj import MergeObj from post_pro.merge_laz import MergePly +from post_pro.conv_obj import ConvertOBJ @dataclass @@ -187,6 +185,28 @@ class ImagePreprocessor: self.visualizer.visualize_filter_step( self.gps_points, previous_points, "3-Time Group Overlap") + def calculate_center_coordinates(self): + """计算剩余点的中心经纬度坐标""" + mean_lat = self.gps_points['lat'].mean() + mean_lon = self.gps_points['lon'].mean() + self.logger.info(f"区域中心坐标:纬度 {mean_lat:.6f}, 经度 {mean_lon:.6f}") + return mean_lat, mean_lon + + def filter_alternate_images(self): + """按时间顺序隔一个删一个图像来降低密度""" + previous_points = self.gps_points.copy() + + # 按时间戳排序 + self.gps_points = self.gps_points.sort_values('date') + + # 保留索引为偶数的行(即隔一个保留一个) + self.gps_points = self.gps_points.iloc[::2].reset_index(drop=True) + + self.visualizer.visualize_filter_step( + self.gps_points, previous_points, "4-Alternate Images") + + self.logger.info(f"交替过滤后剩余 {len(self.gps_points)} 个点") + def divide_grids(self) -> Tuple[Dict[tuple, pd.DataFrame], Dict[tuple, tuple]]: """划分网格 Returns: @@ -220,7 +240,7 @@ class ImagePreprocessor: os.makedirs(output_dir, exist_ok=True) - for point in tqdm(points, desc=f"复制网格 ({grid_id[0]},{grid_id[1]}) 的图像"): + for point in points: src = os.path.join(self.config.image_dir, point["file"]) dst = os.path.join(output_dir, point["file"]) shutil.copy(src, dst) @@ -245,7 +265,13 @@ class ImagePreprocessor: merger = MergeObj(self.config.output_dir) merger.merge_grid_obj(grid_points, translations) - def post_process(self, successful_grid_points: Dict[tuple, pd.DataFrame], grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple]): + def convert_obj(self, grid_points: Dict[tuple, pd.DataFrame], center_lat: float, center_lon: float): + """转换OBJ模型""" + self.logger.info("开始转换OBJ模型") + converter = ConvertOBJ(self.config.output_dir, center_lat, center_lon) + converter.convert_grid_obj(grid_points) + + def post_process(self, successful_grid_points: Dict[tuple, pd.DataFrame], grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple], center_lat: float, center_lon: float): """后处理:合并或复制处理结果""" if len(successful_grid_points) < len(grid_points): self.logger.warning( @@ -256,12 +282,14 @@ class ImagePreprocessor: if self.config.mode == "快拼模式": self.merge_tif(successful_grid_points, self.config.produce_dem) elif self.config.mode == "三维模式": - self.merge_ply(successful_grid_points) - self.merge_obj(successful_grid_points, translations) + # self.merge_ply(successful_grid_points) + # self.merge_obj(successful_grid_points, translations) + self.convert_obj(successful_grid_points, center_lat, center_lon) else: self.merge_tif(successful_grid_points, self.config.produce_dem) - self.merge_ply(successful_grid_points) - self.merge_obj(successful_grid_points, translations) + # self.merge_ply(successful_grid_points) + # self.merge_obj(successful_grid_points, translations) + self.convert_obj(successful_grid_points, center_lat, center_lon) def process(self): """执行完整的预处理流程""" @@ -270,15 +298,17 @@ class ImagePreprocessor: self.cluster() self.filter_isolated_points() self.filter_time_group_overlap() + center_lat, center_lon = self.calculate_center_coordinates() + # self.filter_alternate_images() grid_points, translations = self.divide_grids() # self.copy_images(grid_points) - self.logger.info("预处理任务完成") + # self.logger.info("预处理任务完成") # successful_grid_points = self.odm_monitor.process_all_grids( # grid_points, self.config.produce_dem) successful_grid_points = grid_points self.post_process(successful_grid_points, - grid_points, translations) + grid_points, translations, center_lat, center_lon) except Exception as e: self.logger.error(f"处理过程中发生错误: {str(e)}", exc_info=True) diff --git a/post_pro/conv_obj.py b/post_pro/conv_obj.py index 5f495fa..589597c 100644 --- a/post_pro/conv_obj.py +++ b/post_pro/conv_obj.py @@ -13,17 +13,19 @@ class ConvertOBJ: def convert_grid_obj(self, grid_points): """转换每个网格的OBJ文件为OSGB格式""" - os.makedirs(os.path.join(self.output_dir, "osgb"), exist_ok=True) + os.makedirs(os.path.join(self.output_dir, "osgb", "Data"), exist_ok=True) + tile_infos = [] + for grid_id in grid_points.keys(): try: - self._convert_single_grid(grid_id) + tile_info = self._convert_single_grid(grid_id, grid_points) + tile_infos.append(tile_info) except Exception as e: self.logger.error(f"网格 {grid_id} 转换失败: {str(e)}") - - # 在所有网格处理完成后创建总的metadata.xml - self._create_merged_metadata() - def _convert_single_grid(self, grid_id): + self._create_merged_metadata(tile_infos) + + def _convert_single_grid(self, grid_id, grid_points): """转换单个网格的OBJ文件""" # 1. 构建相关路径 grid_name = f"grid_{grid_id[0]}_{grid_id[1]}" @@ -40,9 +42,24 @@ class ConvertOBJ: self.logger.info(f"开始转换网格 {grid_id} 的OBJ文件") output_osgb = os.path.join(texturing_dir, "Tile.osgb") + # 计算当前网格相对于中心点的偏移 + grid_data = grid_points[grid_id] + lats = [point['lat'] for point in grid_data] + lons = [point['lon'] for point in grid_data] + + min_lat = min(lats) + min_lon = min(lons) + + # 计算偏移量(米) + offset_x = self._calculate_distance(self.center_lat, self.center_lon, self.center_lat, min_lon) + offset_y = self._calculate_distance(self.center_lat, self.center_lon, min_lat, self.center_lon) + + # 修改转换命令,使用正确的参数格式 cmd = ( - f"osgconv --compressed --smooth --fix-transparency -o 0,1,0-0,0,-1 " - f"{obj_file} {output_osgb}" + f"osgconv {obj_file} {output_osgb} " + f"--compressed --smooth --fix-transparency " + f"-t {offset_x},{offset_y},0 " # 使用 -t 参数进行平移 + f"-o 0,1,0-0,0,-1" ) try: @@ -65,20 +82,82 @@ class ConvertOBJ: target_osgb = os.path.join(tile_dir, f"Tile_{grid_id[0]}_{grid_id[1]}.osgb") shutil.copy2(output_osgb, target_osgb) - self.logger.info(f"网格 {grid_id} 转换完成") + # 计算当前网格的边界框 + grid_data = grid_points[grid_id] + # 假设grid_data是一个列表,每个元素都是包含lat和lon的字典 + lats = [point['lat'] for point in grid_data] + lons = [point['lon'] for point in grid_data] + + min_lat = min(lats) + max_lat = max(lats) + min_lon = min(lons) + max_lon = max(lons) + + # 计算相对于中心点的偏移 + offset_x = self._calculate_distance(self.center_lat, self.center_lon, self.center_lat, min_lon) + offset_y = self._calculate_distance(self.center_lat, self.center_lon, min_lat, self.center_lon) + + tile_info = { + 'id': f"{grid_id[0]}_{grid_id[1]}", + 'bounds': { + 'min_lat': min_lat, + 'max_lat': max_lat, + 'min_lon': min_lon, + 'max_lon': max_lon + }, + 'offset': (offset_x, offset_y) + } + return tile_info - def _create_merged_metadata(self): + def _calculate_distance(self, lat1, lon1, lat2, lon2): + """计算两点间的距离(米)""" + from math import sin, cos, sqrt, atan2, radians + R = 6371000 # 地球半径(米) + + lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2]) + 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 _create_merged_metadata(self, tile_infos): """创建合并后的metadata.xml文件""" metadata_content = f""" - EPSG:4326 - {self.center_lon},{self.center_lat},0.000000 - - Visible - -""" + + + + {min([t['bounds']['min_lat'] for t in tile_infos])} + {max([t['bounds']['max_lat'] for t in tile_infos])} + {min([t['bounds']['min_lon'] for t in tile_infos])} + {max([t['bounds']['max_lon'] for t in tile_infos])} + + """ + + for tile in tile_infos: + metadata_content += f""" + + {tile['offset'][0]},{tile['offset'][1]},0 + + {tile['bounds']['min_lat']} + {tile['bounds']['max_lat']} + {tile['bounds']['min_lon']} + {tile['bounds']['max_lon']} + + """ + + metadata_content += """ + + + + + Visible + + """ metadata_file = os.path.join(self.output_dir, "osgb", "metadata.xml") with open(metadata_file, 'w', encoding='utf-8') as f: