# Camera Model Helper

## Interface Definition

**Interface Name**: `ICameraModel`

### Interface Methods

```python
class ICameraModel(ABC):
    @abstractmethod
    def project(self, point_3d: np.ndarray, camera_params: CameraParameters) -> Tuple[float, float]:
        pass
    
    @abstractmethod
    def unproject(self, pixel: Tuple[float, float], depth: float, camera_params: CameraParameters) -> np.ndarray:
        pass
    
    @abstractmethod
    def get_focal_length(self, camera_params: CameraParameters) -> Tuple[float, float]:
        pass
    
    @abstractmethod
    def apply_distortion(self, pixel: Tuple[float, float], distortion_coeffs: List[float]) -> Tuple[float, float]:
        pass
    
    @abstractmethod
    def remove_distortion(self, pixel: Tuple[float, float], distortion_coeffs: List[float]) -> Tuple[float, float]:
        pass
```

## Component Description

Pinhole camera projection model with Brown-Conrady distortion handling.

## API Methods

### `project(point_3d: np.ndarray, camera_params: CameraParameters) -> Tuple[float, float]`

**Description**: Projects 3D point to 2D image pixel.

**Formula**:
```
x = fx * X/Z + cx
y = fy * Y/Z + cy
```

---

### `unproject(pixel: Tuple[float, float], depth: float, camera_params: CameraParameters) -> np.ndarray`

**Description**: Unprojects pixel to 3D ray at given depth.

**Formula**:
```
X = (x - cx) * depth / fx
Y = (y - cy) * depth / fy
Z = depth
```

---

### `get_focal_length(camera_params: CameraParameters) -> Tuple[float, float]`

**Description**: Returns (fx, fy) in pixels.

**Formula**:
```
fx = focal_length_mm * image_width / sensor_width_mm
fy = focal_length_mm * image_height / sensor_height_mm
```

---

### `apply_distortion(pixel: Tuple[float, float], distortion_coeffs: List[float]) -> Tuple[float, float]`

**Description**: Applies radial and tangential distortion (Brown-Conrady model).

---

### `remove_distortion(pixel: Tuple[float, float], distortion_coeffs: List[float]) -> Tuple[float, float]`

**Description**: Removes distortion from observed pixel.

## Dependencies

**External**: opencv-python, numpy

## Data Models

```python
class CameraParameters(BaseModel):
    focal_length: float  # mm
    sensor_width: float  # mm
    sensor_height: float  # mm
    resolution_width: int
    resolution_height: int
    principal_point: Tuple[float, float]  # (cx, cy) pixels
    distortion_coefficients: List[float]  # [k1, k2, p1, p2, k3]
```

