You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
5.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import numpy as np
import json
from typing import Dict, Any
class CameraModel:
def __init__(self, config_path: str = None):
"""
初始化相机模型,支持从配置文件加载参数。
:param config_path: 配置文件的路径JSON/YAML。如果为 None则使用默认参数。
"""
# 默认参数
self._default_params = {
'camera_width': 1280,
'camera_height': 960,
"origin_K": np.array([[1086.58411235010, 0.00000000e+00, 656.379279306796],
[0.00000000e+00, 1086.65442545872, 960-489.101890262552],
[0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]),
"undistor_K": np.array([[838.19297892, 0, 658.51580973],
[0, 836.93529706, 960-484.42225009],
[0, 0, 1]]),
"dist_coeffs": np.array([-0.450688803, 0.260760637, 0.000210619624, -0.000669674309, -0.0447846385]),
"focal_length": 3.6,
"height": 1007.0633042608584, # 1.007e+03 - 9
"rotation_alpha": 0.8892272342384955,
"rotation_beta": 0.6786627929104145,
"position_offset_x": 507,
"position_offset_y": 32,
"rotation_camera": 0.03985022053087201,
"filter": True,
"filt_percent": 0.05,
"outlier_num": 10,
"ransac_residual_threshold": 2.5,
"grid_downsample": True,
"cell_size": 10,
"zoom":1.1,
}
# 如果提供了配置文件,则从文件加载参数
if config_path:
self.load_config(config_path)
else:
self._set_parameters(self._default_params)
def _set_parameters(self, params: Dict[str, Any]) -> None:
"""根据参数字典设置成员变量"""
self.camera_width = params["camera_width"]
self.camera_height = params["camera_height"]
self.origin_K = np.array(params["origin_K"])
self.undistor_K = np.array(params["undistor_K"])
self.dist_coeffs = np.array(params["dist_coeffs"])
self.focal_length = params["focal_length"]
self.height = params["height"]
self.rotation_alpha = params["rotation_alpha"]
self.rotation_beta = params["rotation_beta"]
self.position_offset_x = params["position_offset_x"]
self.position_offset_y = params["position_offset_y"]
self.rotation_camera = params["rotation_camera"]
self.filter = params["filter"]
self.filt_percent = params["filt_percent"]
self.outlier_num = params["outlier_num"]
self.ransac_residual_threshold = params["ransac_residual_threshold"]
self.grid_downsample = params["grid_downsample"]
self.cell_size = params["cell_size"]
self.zoom = params["zoom"]
# 计算派生属性
self.pixel_size_x = self.focal_length / self.undistor_K[0, 0]
self.pixel_size_y = self.focal_length / self.undistor_K[1, 1]
self.principal_point = (self.undistor_K[0, 2], self.undistor_K[1, 2])
def load_config(self, file_path: str) -> None:
"""从 JSON 文件加载参数"""
with open(file_path, 'r') as f:
params = json.load(f)
self._set_parameters(params)
def save_config(self, file_path: str) -> None:
"""将当前参数保存到 JSON 文件"""
params = {
"camera_width": self.camera_width,
"camera_height": self.camera_height,
"origin_K": self.origin_K.tolist(),
"undistor_K": self.undistor_K.tolist(),
"dist_coeffs": self.dist_coeffs.tolist(),
"focal_length": self.focal_length,
"height": self.height,
"rotation_alpha": self.rotation_alpha,
"rotation_beta": self.rotation_beta,
"position_offset_x": self.position_offset_x,
"position_offset_y": self.position_offset_y,
"rotation_camera": self.rotation_camera,
"filter": self.filter,
"filt_percent": self.filt_percent,
"outlier_num": self.outlier_num,
"grid_downsample": self.grid_downsample,
"cell_size": self.cell_size,
"ransac_residual_threshold": self.ransac_residual_threshold,
"zoom": self.zoom
}
with open(file_path, 'w') as f:
json.dump(params, f, indent=4)
def update_parameter(self, key: str, value: Any) -> None:
"""动态更新单个参数"""
if hasattr(self, key):
setattr(self, key, value)
# 如果修改了 K 或焦距,需要重新计算派生属性
if key in ["undistor_K", "focal_length"]:
self.pixel_size_x = self.focal_length / self.undistor_K[0, 0]
self.pixel_size_y = self.focal_length / self.undistor_K[1, 1]
self.principal_point = (self.undistor_K[0, 2], self.undistor_K[1, 2])
else:
raise AttributeError(f"参数 {key} 不存在")
# model = CameraModel(None)
# model.save_config("updated_config.json")