# pogucam - Poor Guy Camera

A Python package for camera streaming, capture, and image processing. Provides tools for publishing video streams via ZeroMQ, receiving and recording frames, and converting between FITS and common image formats.

## Overview

pogucam provides multiple interfaces for camera operations:

- **pogucam** - HTTP client for remote camera control and capture
- **zmqcam** - ZeroMQ-based streaming and file conversion tools
- **zmqcam-view** - Interactive FITS file viewer
- **zmqcam-napari** - FITS viewer using napari

## Installation

```bash
pip install pogucam
# or
uv pip install pogucam
```

## Requirements

- Python >= 3.12
- OpenCV with V4L2 support (for camera capture)
- ZeroMQ libraries
- astropy (for FITS file handling)

---

## pogucam (HTTP Client)

Run pogucam from the command line with the following syntax:

```bash
pogucam [URL] [-r RESOLUTION] [-f FOURCC]

Arguments:
  URL           IP address or device path (default: 127.0.0.1)

Options:
  -r, --resolution RESOLUTION   Set resolution (default: 640x480)
  -f, --fourcc FOURCC           Set pixel format: YUYV or MJPG (default: YUYV)

Examples:
  pogucam 192.168.1.10 -r 800x600 -f MJPG
  pogucam /dev/video0
  pogucam 0 -f YUYV -r 1920x1080
```

### Keypress Commands (pogucam)

- **S**: Save image
  - S: save one image
  - Shift+S: toggle saving all images
  - Ctrl+Shift+S: toggle saving JPG format
  - Alt+S: toggle saving FITS only
- **X**: Switch resolution / extend image
  - X: toggle local 2x image extend
  - Shift+X: send remote switch~reson~ command
  - Ctrl+X: send remote switch~resoff~ command
- **P**: Toggle print text overlays
- **E**: Adjust exposure (remote)
- **G**: Adjust gain (remote)
- **Y**: Adjust gamma (remote)
- **D**: Adjust local gamma
- **W**: Open web browser to URL (local)
- **Z**: Zoom (local)
- **H, J, K, L**: Move red cross (local) or send remote commands with Ctrl+Shift
- **V**: Toggle green cross (remote)
- **C**: Toggle red cross (local)
- **I**: Integrate accumulate (local/remote)
- **B**: Background image operations (local/remote)
- **F**: Foreground image operations (local)
- **R**: Rotate image (local)
- **1,2,3,4**: Load/save configurations
- **T**: Test commands and timelapse (local/remote)
- **A**: Timelapse control (local)
- **Esc or Q**: Quit application

---

## zmqcam Commands

### publish

Stream video from a camera or generate synthetic test pattern via ZeroMQ.

```bash
zmqcam publish [OPTIONS]
```

**Options:**
- `-c, --camera` - Camera device index (default: 0)
- `-a, --auto-video-source` - Auto-detect camera with YUYV support
- `-B, --blue-image` - Send synthetic 640x480 blue image at 1 fps
- `-b, --bind` - ZMQ bind address (default: tcp://*:5555)
- `-f, --fps` - Maximum FPS to publish, 0 for unlimited (default: 5)
- `-w, --width` - Capture width (default: 1920)
- `--height` - Capture height (default: 1080)
- `--format` - Pixel format: YUYV or MJPG (default: YUYV)
- `-z, --compression` - Zstd compression level 0-22 (default: 1)

**Examples:**
```bash
zmqcam publish --camera 0 --bind tcp://*:5555
zmqcam publish -a --bind tcp://*:5555
zmqcam publish --blue-image --bind tcp://*:5555
```

### subscribe

Connect to a ZMQ publisher and display or record video frames.

```bash
zmqcam subscribe [OPTIONS]
```

**Options:**
- `-c, --connect` - ZMQ connect address (default: tcp://localhost:5555)
- `--no-display` - Run without displaying frames
- `--display-width` - Display width (default: 640)
- `--display-height` - Display height (default: 480)
- `--fov` - Field of view for barrel correction (default: 150.0)
- `-t, --no-signal-timeout` - Seconds before showing no-signal image (default: 5.0)
- `--burst` - Number of frames to save in FITS burst (default: 10)
- `-d, --record-duration` - Duration for time-based recording (default: 10)
- `--burst-mode` - `individual` (separate files) or `sequence` (FITS cube)

**Interactive Controls:**
- `q` - Quit
- `v/h` - Show/hide window
- `s` - Save current frame as FITS
- `j/p` - Save as JPG/PNG
- `a/t` - Start frame/time-limited recording
- `0-9` - Display modes (scale, crop positions)
- `b` - Toggle barrel correction
- `+/-` - Adjust correction strength
- `x` - Toggle 2x scaling

**Examples:**
```bash
zmqcam subscribe --connect tcp://localhost:5555
zmqcam subscribe --burst-mode sequence --burst 100
```

### napari

View FITS files as a stack in napari.

```bash
zmqcam napari [OPTIONS] PATTERNS...
```

**Options:**
- `-k, --keep-temp` - Keep temporary TIFF file after viewing
- `-t, --temp-dir` - Directory for temporary files (default: /tmp)

**Examples:**
```bash
zmqcam napari *.fits
zmqcam napari --keep-temp image_*.fits
```

### tojpg

Convert FITS files to JPEG format.

```bash
zmqcam tojpg [OPTIONS] PATTERNS...
```

**Options:**
- `-q, --quality` - JPEG quality 1-100 (default: 95)
- `-o, --output-dir` - Output directory (default: current)
- `-f, --frame` - Frame index to extract from sequences (default: 0)

**Examples:**
```bash
zmqcam tojpg *.fits
zmqcam tojpg --quality 90 -o /tmp/output *.fits
zmqcam tojpg -f 5 sequence.fits  # Extract frame 5
```

### topng

Convert FITS files to PNG format.

```bash
zmqcam topng [OPTIONS] PATTERNS...
```

**Options:**
- `-o, --output-dir` - Output directory (default: current)
- `-f, --frame` - Frame index to extract from sequences (default: 0)

**Examples:**
```bash
zmqcam topng *.fits
zmqcam topng -o /tmp/output *.fits
```

### tomp4

Convert FITS sequence files to MP4 video.

```bash
zmqcam tomp4 [OPTIONS] PATTERNS...
```

**Options:**
- `-o, --output-dir` - Output directory (default: current)
- `-f, --fps` - Frames per second (default: 30)
- `-q, --quality` - Video quality 1-100 (default: 95)

**Examples:**
```bash
zmqcam tomp4 sequence.fits
zmqcam tomp4 -f 15 -q 90 *.fits
```

---

## zmqcam-view

Interactive terminal-based FITS file viewer. Displays Y, U, V channels and RGB preview with keyboard navigation.

```bash
zmqcam-view [DIRECTORY]
```

**Controls:**
- `↑/↓` or `j/k` - Navigate files
- `Enter` - View selected file
- `q` - Quit

---

## zmqcam-napari

Alternative entry point for viewing FITS files in napari.

```bash
zmqcam-napari [OPTIONS] PATTERNS...
```

---

## File Formats

### FITS

The primary storage format for captured frames. Supports:
- Single frames (2D arrays)
- Sequences/cubes (4D RGB arrays for burst recordings)
- Metadata headers with timing and hostname information

### YUYV

Raw capture format used for streaming. Provides uncompressed video with 4:2:2 chroma subsampling.

---

## Architecture

The package is organized into modules:

- `subscriber.py` - ZMQ subscriber with display and recording
- `subscriber_terminal.py` - Terminal input handling
- `subscriber_frame_utils.py` - Frame processing utilities
- `subscriber_recording.py` - Recording management
- `publisher.py` - ZMQ publisher for camera capture
- `image_saving.py` - FITS file I/O and conversions
- `image_processing_transformations.py` - Barrel distortion correction
- `image_processing_texts.py` - Text overlay utilities
- `fits_viewer.py` - Interactive FITS viewer
- `napari_viewer.py` - Napari integration

---

## MQTT

Experimental MQTT functionality is in development for raw image streaming.

Raw images are sent to `image/raw8000` topic with encoded header information including dimensions, timestamps, and camera parameters.

```python
header = struct.pack(
    '!HHQddIfff',
    width,
    height,
    int(framenumber),
    timestamp.timestamp(),
    recording_started.timestamp(),
    0,  # padding
    float(exposition),
    float(gain),
    float(gamma)
)
payload = header + image.tobytes()
```

---

## Notes

- Remote commands are sent via send~command~ with JSON data.
- Local commands affect display or saving behavior.
- Some commands print helpful info or ffmpeg usage hints.

## Appendix: External Tools Workflows

### A) Napari - Working with 4D FITS Cubes

For viewing and processing burst sequence files (4D RGB cubes) in napari:

**Install the crop plugin:**
```bash
uv run --with=napari-crop --with=napari-tabu zmqcam napari *.fits
```

**Axis rotation for 4D cubes:**
When opening sequence FITS files in napari, the dimensions may need reordering for proper display. Use napari's built-in axis reordering controls to navigate the (N, 3, H, W) format:
- The first axis (N) is the frame number
- The second axis (3) represents RGB channels
- The third and fourth axes are height and width

The napari-nd-cropper plugin provides shapes-based cropping functionality for extracting regions of interest from the image stack.

### B) Siril - Sequence Processing and Stacking

Siril can process FITS sequence files for astronomical image stacking:

**Convert single FITS cube to SER format:**
```bash
# Load the sequence FITS file in Siril
# Siril will recognize the 4D cube and treat it as a sequence
# Save as SER format for further processing
```

**Workflow for stacking:**
1. Open Siril and load your FITS sequence file
2. Siril will detect the multiple frames in the cube
3. Pre-process with bias/dark/flat frames if available
4. Register (align) the sequence frames
5. Stack using average or median combination
6. Export the final stacked result

**Command line example:**
```bash
# Siril script example for batch processing
siril -s stack_script.ssf
```

Where `stack_script.ssf` contains:
```
requires 0.99

# Convert FITS to internal sequence
cd /path/to/your/files
load sequence.fits

# Register sequence
register_sequence

# Stack with median
stack_sequence median

# Save result
save stacked_result.fits
```

---

## License

See project repository for license information.

## Author

jaromrax
