Files

324 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# **Stereo Disparity Map and Point Cloud Generation**
This project implements a dense stereo disparity map and point cloud generation pipeline using spatio-temporal Zero-Normalized Cross-Correlation (ZNCC) with subpixel interpolation methods and other advanced features.
## **Features**
- **Dense Disparity Map Calculation**: Generates Disparity and vertical shift maps.
- **Subpixel Interpolation**: Supports parabolic, Gaussian, and equiangular interpolation methods for subpixel accuracy.
- **Correlation Map**: Computes ZNCC correlation for each pixel.
- **Point Cloud Generation**: Reprojects disparity maps into 3D space using a Q matrix.
- **Color Mapping**: Normalizes depth values and applies a colormap for visualization.
- **Optional Median Filtering**: Smoothens the disparity map.
- **Visualization**: Saves disparity maps, vertical shift maps, and correlation maps with colorbars.
## **Requirements**
- Python 3.9 or later
```bash
# This step only
pip install -r ~/Speckle-Scanner/05_disparity/zncc/requirements.txt
# Or install everything for the full pipeline
pip install -r ~/Speckle-Scanner/requirements.txt
# Optional GPU acceleration (pick one matching your CUDA version)
pip install cupy-cuda12x # CUDA 12.x
pip install cupy-cuda11x # CUDA 11.211.8
```
Packages: `numpy`, `opencv-python`, `matplotlib`, `scipy`, `numba`, `open3d`. Without `cupy`, the pipeline falls back to CPU (`numba`).
## **Input Requirements**
- **Stereo Rectified Images**:
- Images must be stored in `.png` or `.bmp` format.
- **Pipeline pairing** (in `02_rect_images/`): `lc_ts1634840093_ck….png` is matched with `rc_ts1634840093_ck….png` on the shared `ts` token; the `ck…` suffix is ignored.
- Pairs are sorted by timestamp; `--num_images` defaults to **all** pairs; if limited, the **last N** (highest timestamps) are used.
- Standalone runs may still use separate `left/` and `right/` folders with any naming; pipeline mode uses one folder with `lc_` / `rc_` prefixes.
- PNG is preferred when both PNG and BMP pairs exist.
- **Q Matrix File**:
- A `.cvstore` file containing the Q matrix for 3D reprojection.
## **Outputs**
- **Disparity Map**: Saved as `Disparity.npy`.
- **Vertical Shift Map**: Saved as `vertical_shift_map.npy`.
- **Correlation Map**: Saved as `correlation_map.npy`.
- **Disparity and Shift Maps with Colorbars**:
- `Disparity_map_colorbar.png`
- `vertical_shift_map_colorbar.png`
- `correlation_map_colorbar.png`
- **Point Cloud**:
- Saved as `Point_cloud.ply` in PLY format with depth-based color information.
## **Usage**
1. Clone the repository and navigate to the project directory.
2. Prepare your stereo images and paste them in data folder
Example directory structure:
```
project_directory/
.data/
├── left/
│ ├── 0.png
│ ├── 1.png
│ └── ...
└── right/
├── 0.png
├── 1.png
└── ...
Or
.data/
├── left/
│ ├── lc00000.bmp
│ └── lc00001.bmp
└── right/
├── rc00000.bmp
└── rc00001.bmp
```
3. The Q matrix must be provided in a YAML file (e.g., `Q.cvstore`).
Format example:
```
%YAML:1.0
---
Q: !!opencv-matrix
rows: 4
cols: 4
dt: f
data: [ 1.0, 0.0, 0.0, -5.5863211059570312e+02,
0.0, 1.0, 0.0, -7.3320780181884766e+02,
0.0, 0.0, 0.0, 3.3665836719173171e+03,
0.0, 0.0, 1.4262549294100269e+00, 1.0682440279589944e+03 ]
```
This matrix is essential for converting disparity maps into a 3D point cloud.
3. Run the script with desired parameters (see below).
### **Basic Command**
```bash
# stereo_disparity_main.py auto-selects GPU (CUDA) or CPU.
cd ~/Speckle-Scanner/05_disparity/zncc
# Default parameters (saves disparity map only)
python stereo_disparity_main.py \
--left_dir <path_to_rect_images> \
--right_dir <path_to_rect_images> \
--left_prefix lc_ \
--right_prefix rc_ \
--q_file <path_to_lc-rc_Q.cvstore> \
--disp_output_dir <path_to_04_zncc_disp_map> \
--pcl_output_dir <path_to_06_zncc_pcl>
# Troubleshooting mode — saves all outputs (vertical shift, correlation, point cloud)
python stereo_disparity_main.py \
--left_dir <path_to_rect_images> \
--right_dir <path_to_rect_images> \
--left_prefix lc_ \
--right_prefix rc_ \
--q_file <path_to_lc-rc_Q.cvstore> \
--disp_output_dir <path_to_04_zncc_disp_map> \
--pcl_output_dir <path_to_06_zncc_pcl> \
--troubleshooting
```
This runs the program with default parameters.
Same commands for stereo_disparity_cpu.py and stereo_disparity_gpu.py
### **Custom Parameters**
You can override any parameter through command-line arguments. Below is an example with some customized parameters:
```bash
python stereo_disparity_main.py \
--window_size 5 \
--H_neg_range -165 \
--H_pos_range 65 \
--v_neg_range -4 \
--v_pos_range 0 \
--zncc_threshold 0.4 \
--num_images 10 \ # optional: last 10 pairs by timestamp; omit for all pairs
--noise_filter "open3d" \
--interpolation True \
--noise_remove False \
--method "gaussian" \
--q_file "./data/Q_matrix.cvstore" \
--left_dir "./data/left" \
--right_dir "./data/right" \
--disp_output_dir "./output/disp" \
--pcl_output_dir "./output/pcl" \
--troubleshooting
```
## **Available Parameters**
| Parameter | Default Value | Description |
| ------------------ | ------------------- | --------------------------------------------------------------------------------------|
| `--window_size` | `5` | Size of the window for block matching. |
| `--H_neg_range` | `0` | Horizontal negative disparity range. |
| `--H_pos_range` | `65` | Horizontal positive disparity range. |
| `--v_neg_range` | `-4` | Vertical negative disparity range. |
| `--v_pos_range` | `2` | Vertical positive disparity range. |
| `--zncc_threshold` | `0.4` | ZNCC threshold for valid matches. |
| `--num_images` | all pairs | Stereo pairs to use per scan. Default: all `lc_ts*`/`rc_ts*` pairs matched on `ts`. If fewer than available, the **last N** pairs (highest timestamps) are used; `ck*` suffix is ignored. |
| `--noise_filter` | `open3d` | Post-processing noise filter method (`median`[Disparity Map] or `open3d`[Pointcloud]).|
| `--interpolation` | `True` | Enable subpixel interpolation (`True` or `False`). |
| `--noise_remove` | `True` | noise removal using bidirectional disparity estimation (`True` or `False`). |
| `--method` | `parabolic` | Subpixel interpolation method (`parabolic`, `gaussian`, or `equiangular`). |
| `--q_file` | `./data1/Q.cvstore` | Path to the Q matrix file. |
| `--left_dir` | `./data1/left` | Path to the directory containing left images. |
| `--right_dir` | `./data1/right` | Path to the directory containing right images. |
| `--left_prefix` | `""` | Filename prefix to filter left images (e.g. `lc_`) when both cameras share a folder. |
| `--right_prefix` | `""` | Filename prefix to filter right images (e.g. `rc_`) when both cameras share a folder. |
| `--output_dir` | `./results` | Fallback output directory (used when `--disp_output_dir`/`--pcl_output_dir` are not set). |
| `--disp_output_dir` | same as `--output_dir` | Directory for disparity map outputs (npy + png). |
| `--pcl_output_dir` | same as `--output_dir` | Directory for point cloud outputs (PLY + TXT). |
| `--troubleshooting` | `False` | When set, saves all outputs (vertical shift map, correlation map, point cloud); otherwise only disparity map is saved. |
## **Details of Post-processing noise filter method**
- **open3d**: used for denoising point clouds.
- **median**: used to reduce noise in the disparity map.
## **Details of Subpixel Interpolation Methods**
- **Parabolic**: Fits a parabola to the ZNCC values and finds the peak.
- **Gaussian**: Uses the logarithm of ZNCC values to model a Gaussian distribution and find the peak.
- **Equiangular**: Uses angular interpolation for smoother and more robust subpixel shifts.
## **Notes**
- Ensure stereo images are rectified before processing.
- Adjust the disparity ranges (`H_neg_range`, `H_pos_range`, etc.) based on your dataset.
- If disparity maps appear noisy, enable median filtering or refine the ZNCC threshold.
## **Execution Time**
- Execution time depends on the number of images, window size, and disparity ranges.
- Subpixel interpolation adds computational overhead but improves accuracy.
## **Point Cloud File**
- The generated `.ply` file can be visualized using point cloud tools like MeshLab or CloudCompare.
- Depth values are normalized and color-coded using the `jet` colormap.
## **Troubleshooting**
- Ensure the `Q.cvstore` file exists in the specified path.
- Check file permissions.
- Ensure the left and right images are rectified and have the same resolution.
- Reduce the number of images or use a smaller window size.
- Run on a machine with higher processing power.
---
## **Pipeline Usage (Automated Path Resolution)**
Use `run_zncc_pipeline.py` instead of calling `stereo_disparity_main.py` directly.
It resolves all paths automatically from the project folder structure and processes
every scan in a session (or a single scan you name).
### **Folder structure assumed**
```
~/Speckle-Scanner_Processing_data/
└── <project>/
└── <date>/
└── <session>/
├── params_link/
│ └── lc-rc_Q.cvstore ← Q matrix (input)
└── <ScanXXXXXX>/
├── 02_rect_images/ ← lc_ts*.png + rc_ts*.png (input)
├── 04_zncc_disp_map/ ← disparity .npy + colorbar .png (created)
└── 06_zncc_pcl/ ← Point_cloud.ply + .txt (created)
```
### **Commands**
```bash
cd ~/Speckle-Scanner/05_disparity/zncc
# Process ALL scans in a session (all matched lc/rc pairs per scan)
python run_zncc_pipeline.py \
--project Olsen_wings \
--date 2026-05-12 \
--session session1
# Process ALL sessions on a date (omit --session)
python run_zncc_pipeline.py \
--project Olsen_wings \
--date 2026-05-12
# Process a SINGLE scan — only the last 3 pairs (highest timestamps)
python run_zncc_pipeline.py \
--project Olsen_wings \
--date 2026-05-12 \
--session session1 \
--scan Scan000001 \
--num_images 3
# Full outputs including point cloud and debug maps (troubleshooting mode)
python run_zncc_pipeline.py \
--project Olsen_wings \
--date 2026-05-12 \
--session session1 \
--scan Scan000001 \
--troubleshooting
# Custom ZNCC parameters
python run_zncc_pipeline.py \
--project Olsen_wings \
--date 2026-05-12 \
--session session1 \
--window_size 7 \
--H_neg_range 0 \
--H_pos_range 80 \
--v_neg_range -4 \
--v_pos_range 2 \
--zncc_threshold 0.5 \
--noise_filter open3d \
--method gaussian
```
### **Pipeline parameters**
| Parameter | Default | Description |
|---------------------|---------|------------------------------------------------------------------------------------|
| `--project` | — | Project name (e.g. `Olsen_wings`) |
| `--date` | — | Date string (e.g. `2026-05-12`) |
| `--session` | all | Session name (e.g. `session1`); omit to process **all sessions** on that date |
| `--scan` | all | Single scan to process (e.g. `Scan000001`); omit to process all scans in session |
| `--troubleshooting` | off | When set, saves vertical shift map, correlation map, and point cloud PLY/TXT; by default only `disparity.npy` and `Disparity_map_colorbar.png` are saved |
| `--num_images` | all | Image pairs per scan (matched on `ts`; last N if limited) |
| All other ZNCC params | see above table | Forwarded directly to `stereo_disparity_main.py` |
### **What gets saved**
| File | Default | `--troubleshooting` |
|------|:-------:|:-------------------:|
| `04_zncc_disp_map/disparity.npy` | ✓ | ✓ |
| `04_zncc_disp_map/Disparity_map_colorbar.png` | ✓ | ✓ |
| `04_zncc_disp_map/vertical_shift_map.npy` | | ✓ |
| `04_zncc_disp_map/vertical_shift_map_colorbar.png` | | ✓ |
| `04_zncc_disp_map/correlation_map.npy` | | ✓ |
| `04_zncc_disp_map/correlation_map_colorbar.png` | | ✓ |
| `06_zncc_pcl/Point_cloud.ply` | | ✓ |
| `06_zncc_pcl/Point_cloud.txt` | | ✓ |
---
Contributions and improvements are welcome! Feel free to open an issue or submit a pull request on GitHub.