1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
| """ 传感器数字孪生模型框架 模拟真实传感器的光学/电气特性 """
import numpy as np from dataclasses import dataclass, field from typing import Optional, Tuple
@dataclass class SensorSpec: """传感器规格参数""" name: str resolution: Tuple[int, int] pixel_size_um: float quantum_efficiency: float dark_noise_e: float full_well_e: int read_noise_e: float bit_depth: int fps: float dynamic_range_db: float
class SensorDigitalTwin: """ 传感器数字孪生 输入:理想场景图像 + 光照条件 输出:模拟传感器输出的真实图像(含噪声/畸变) """ def __init__(self, spec: SensorSpec): self.spec = spec def simulate(self, ideal_image: np.ndarray, exposure_ms: float = 10, illumination_lux: float = 500) -> np.ndarray: """ 模拟传感器成像 Args: ideal_image: 理想图像 (H, W, C), float 0-1 exposure_ms: 曝光时间 illumination_lux: 照度 Returns: sensor_output: 传感器输出 (H, W, C), uint8/uint16 """ H, W, C = ideal_image.shape pixel_area_m2 = (self.spec.pixel_size_um * 1e-6) ** 2 photons_per_pixel = (illumination_lux * pixel_area_m2 * exposure_ms * 1e-3 * self.spec.quantum_efficiency) signal_electrons = ideal_image * photons_per_pixel shot_noise = np.random.poisson(signal_electrons).astype(float) dark_current = self.spec.dark_noise_e * exposure_ms / 1000 dark_noise = np.random.normal(dark_current, np.sqrt(dark_current), (H, W, C)) read_noise = np.random.normal(0, self.spec.read_noise_e, (H, W, C)) total_electrons = shot_noise + dark_noise + read_noise total_electrons = np.clip(total_electrons, 0, self.spec.full_well_e) max_val = 2 ** self.spec.bit_depth - 1 output = (total_electrons / self.spec.full_well_e * max_val) return output.astype(np.uint16 if self.spec.bit_depth > 8 else np.uint8) def simulate_hdr(self, ideal_image: np.ndarray, exposures: list = [1, 10, 50]) -> np.ndarray: """模拟 HDR 成像""" exposures_imgs = [self.simulate(ideal_image, exp) for exp in exposures] return np.mean(exposures_imgs, axis=0).astype(np.uint16)
SENSORS = { 'OX05C1S': SensorSpec( name='OmniVision OX05C1S', resolution=(2592, 1944), pixel_size_um=2.2, quantum_efficiency=0.65, dark_noise_e=15.0, full_well_e=6000, read_noise_e=1.5, bit_depth=12, fps=60, dynamic_range_db=120 ), 'SC860AT': SensorSpec( name='SmartSens SC860AT', resolution=(3840, 2160), pixel_size_um=1.8, quantum_efficiency=0.70, dark_noise_e=10.0, full_well_e=8000, read_noise_e=1.2, bit_depth=14, fps=30, dynamic_range_db=140 ) }
if __name__ == "__main__": spec = SENSORS['OX05C1S'] twin = SensorDigitalTwin(spec) ideal = np.random.rand(480, 640, 3) * 0.5 + 0.3 for lux in [10, 100, 500, 1000]: output = twin.simulate(ideal, exposure_ms=10, illumination_lux=lux) snr = 20 * np.log10(np.mean(output) / (np.std(output) + 1e-10)) print(f"照度 {lux:4d} lux: 输出均值={np.mean(output):.1f}, " f"SNR={snr:.1f}dB, dtype={output.dtype}") print(f"\n传感器: {spec.name}") print(f"分辨率: {spec.resolution}") print(f"动态范围: {spec.dynamic_range_db}dB")
|