Name | zaowr-polsl-kisiel JSON |
Version |
0.0.31
JSON |
| download |
home_page | None |
Summary | A simple Python package used by me and my friends at university in the 'Advanced Image, Video and Motion Analysis' course. |
upload_time | 2025-01-08 16:31:37 |
maintainer | None |
docs_url | None |
author | Maksymilian Kisiel |
requires_python | >=3.8 |
license | Copyright (c) 2018 The Python Packaging Authority Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
keywords |
polsl
zaowr
2024/2025
igt
zaowr
|
VCS |
 |
bugtrack_url |
|
requirements |
opencv-python
numpy
tqdm
colorama
matplotlib
scikit-image
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# ZAOWR Package
<br/>
This is a **ZAOWR** (Zaawansowana Analiza Obrazu, Wideo i Ruchu, eng. _Advanced Image, Video, and Motion Analysis_) Python package used by me and my friends at the university.
<br/>
PyPI link to the package: <a href="https://pypi.org/project/zaowr-polsl-kisiel/" target="_blank"><b>MAIN PyPI</b></a>, <a href="https://test.pypi.org/project/zaowr-polsl-kisiel/" target="_blank"><b>TEST PyPI</b></a>.
<br/>
<br/>
## Table of contents
1. [Windows tutorial](./docs/WINDOWS.md)
2. [RTFM - Use Cases for zaowr_polsl_kisiel and the importance of docstrings](#rtfm---use-cases-for-zaowr_polsl_kisiel-and-the-importance-of-docstrings)
3. [Installing the package on Linux using `pip`](#installing-the-package-on-linux-using-pip)
4. [Removing the package on Linux using `pip`](#removing-the-package-on-linux-using-pip)
5. [Installing extras (optional dependencies for the package - development)](#installing-extras-optional-dependencies-for-the-package---development)
6. [Creating virtual environment and installing the package](#creating-virtual-environment-and-installing-the-package)
7. [Testing the installation](#testing-the-installation)
8. [Automation: building and uploading with `Makefile` - DEV Tutorial](./docs/DEV_TUTORIAL.md#automation-building-and-uploading-with-makefile---dev-tutorial)
9. [Building package - DEV Tutorial based on official DOCS](./docs/DEV_TUTORIAL.md#building-package---dev-tutorial-based-on-official-docs)
10. [TODO for tracking issues / backlog / progress](./docs/TODO.md)
11. [Code requirements](#code-requirements)
12. [Sources](#sources)
<br/>
<br/>
## Windows tutorial
The Windows tutorial can be found [here](./docs/WINDOWS.md)
<br/>
<br/>
## RTFM - Use Cases for zaowr_polsl_kisiel and the importance of docstrings
<ol>
<li>
<div style="font-size: 22px">
[RTFM v1 here](./docs/USAGE.md) (custom-made explanations with examples)
</div>
</li>
<li>
<div style="font-size: 22px">
[RTFM v2 here (GitHub Pages)](https://revalew.github.io/zaowr-py-package) (auto-generated documentation with `pdoc`)
</div>
</li>
</ol>
<br/>
> [!IMPORTANT]
>
> It is really important to understand how to use the package.
>
> The manual explains the use cases and tells you how to use docstrings.
>
> More examples (exact lab solutions) can be found [here](./tests/lab_exercise_solutions/)
<br/>
<br/>
## Installing the package on Linux using `pip`
<ol>
<li> PyPI MAIN
<br/>
<br/>
```bash
python3 -m pip install --upgrade zaowr-polsl-kisiel
```
</li>
<br/>
<li> TestPyPI
<br/>
<br/>
```bash
python3 -m pip install --index-url https://test.pypi.org/simple/ --upgrade zaowr-polsl-kisiel
```
</li>
</ol>
<br/>
<br/>
## Removing the package on Linux using `pip`
<br/>
```bash
python3 -m pip uninstall zaowr-polsl-kisiel
```
<br/>
<br/>
## Installing extras (optional dependencies for the package - development)
```bash
python3 -m pip install --upgrade "zaowr-polsl-kisiel[dev]"
```
<br/>
<br/>
## Creating virtual environment and installing the package
<br/>
> [!NOTE]
>
> Complete instructions on managing Python virtual environments
>
> can be found [here](https://github.com/revalew/Python-Venv).
<br/>
<ol>
<li> Create project directory and open it (directory where you will create your files and where the venv will be created). Below is an example of how to do it through Bash - you can also do it through file explorer
<br/>
<br/>
```bash
testDir=/home/user/test
```
```bash
mkdir -p $testDir
```
```bash
cd $testDir
```
<br/>
</li>
<li> Create venv
<br/>
<br/>
```bash
python -m venv ENV_NAME
```
</li>
<br/>
> [!NOTE]
>
> `ENV_NAME` is the name of your venv, so you can change it however you like
<br/>
<li> Activate the venv (while in the project directory)
<br/>
<br/>
```bash
source ENV_NAME/bin/activate
```
or
```bash
. ENV_NAME/bin/activate
```
</li>
<br/>
<li> Install the package from PyPI
<br/>
<br/>
```bash
python3 -m pip install --upgrade zaowr-polsl-kisiel
```
</li>
<br/>
<li> <b>(ADDITIONAL COMMAND)</b> If you want to deactivate the currently active venv
<br/>
<br/>
```bash
deactivate
```
</li>
<br/>
<li> <b>(ADDITIONAL COMMAND)</b> To reactivate the venv, navigate to the path where you created the venv and source it again (command shown above in section number 3)
</li>
</ol>
<br/>
<br/>
## Testing the installation
<br/>
<ul>
<li> Activate the venv (while in the project directory) - <b>Skip this step if you are not using a virtual environment</b>
<br/>
<br/>
```bash
source ENV_NAME/bin/activate
```
or
```bash
. ENV_NAME/bin/activate
```
</li>
<br/>
<li> Launch python
<br/>
<br/>
```bash
python3
```
</li>
<br/>
<li> Import the package
<br/>
<br/>
```python
from zaowr_polsl_kisiel import load_calibration
```
</li>
<br/>
<li> Locate the file with calibration params in tests folder and download it (link below)
<br/>
<br/>
[`./tests/misc/calibration_params/calibration_params.json`](./tests/misc/calibration_params/calibration_params.json)
</li>
<br/>
<li> Try reading the params from file
<br/>
<br/>
```python
# remember to provide appropriate path to the calibration params
calibrationParams = load_calibration("/path/to/calibration_params.json")
```
</li>
<br/>
<li> Display the <code>MSE</code> value to test if the load succeeded
<br/>
<br/>
```python
print(calibrationParams["mse"])
```
</li>
</ul>
<br/>
<br/>
## Code requirements
The code fulfills all the requirements necessary to pass the course. Detailed descriptions of the requirements for each lab are provided in the [`./docs/code_requirements`](./docs/code_requirements/) directory in the form of images (in Polish).
<br/>
<br/>
## Sources
This package has been prepared following [this tutorial](https://packaging.python.org/en/latest/tutorials/packaging-projects/)
The publishing to PyPI was created with [this tutorial](https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/)
# RTFM - Use Cases for zaowr_polsl_kisiel and the importance of docstrings
<br/>
<br/>
<div style="font-size: 22px">
[RTFM v2 here (GitHub Pages)](https://revalew.github.io/zaowr-py-package) (auto-generated documentation with `pdoc`)
</div>
<br/>
<br/>
## Table of Contents
1. [`Docstrings`](#docstrings)
2. [`@measure_perf() decorator`](#measure_perf-decorator)
3. [`calibrate_camera()`](#calibrate_camera)
4. [`are_params_valid()`](#are_params_valid)
5. [`remove_distortion()`](#remove_distortion)
6. [`stereo_calibration()`](#stereo_calibration)
7. [`calculate_fov()`](#calculate_fov)
8. [`stereo_rectify()`](#stereo_rectify)
9. [`find_aruco_dict()`](#find_aruco_dict)
10. [`load_calibration()`](#load_calibration)
11. [`load_rectification_maps()`](#load_rectification_maps)
12. [`load_stereo_calibration()`](#load_stereo_calibration)
13. [`save_calibration()`](#save_calibration)
14. [`load_pgm_file()`](#load_pgm_file)
15. [`calculate_disparity_map()`](#calculate_disparity_map)
16. [`save_disparity_map()`](#save_disparity_map)
17. [`calculate_color_difference_map()`](#calculate_color_difference_map)
18. [`crop_image()`](#crop_image)
19. [`calculate_mse_disparity()`](#calculate_mse_disparity)
20. [`calculate_ssim_disparity()`](#calculate_ssim_disparity)
21. [`plot_disparity_map_comparison()`](#plot_disparity_map_comparison)
22. [`load_depth_map_calibration()`](#load_depth_map_calibration)
23. [`load_pfm_file()`](#load_pfm_file)
24. [`write_ply_file()`](#write_ply_file)
25. [`decode_depth_map()`](#decode_depth_map)
26. [`depth_map_normalize()`](#depth_map_normalize)
27. [`depth_to_disparity_map()`](#depth_to_disparity_map)
28. [`disparity_map_normalize()`](#disparity_map_normalize)
29. [`disparity_to_depth_map()`](#disparity_to_depth_map)
30. [`display_img_plt()`](#display_img_plt)
31. [`compare_images()`](#compare_images).
<br/>
<br/>
### Docstrings
Using Python Docstrings to Enhance Understanding
In Python, docstrings are a way to provide documentation for your functions, classes, and modules. They explain what your code does, what each parameter does, what is returned and how to use it. They are written between triple quotes (""") and are often used to explain the purpose of a function, class, or module.
<ul>
<li> In IDEs or Text Editors: Many modern Integrated Development Environments (IDEs) and text editors, such as PyCharm, Visual Studio Code, or Jupyter Notebook, allow you to hover your mouse over a function to see its description provided by the docstring. Similarly, hovering over a parameter will display information about what that parameter does (if it is described in the docstring).
</li>
<br/>
<li> In the Terminal: You can read docstrings in the terminal using the help() function, which prints the docstring to the console.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
# Display documentation for the entire module
help(zw)
# Display specific submodule's documentation
help(zw.calibration)
# Display detailed documentation for a specific function
help(zw.calibrate_camera)
```
</li>
</ul>
<br/>
<br/>
### `@measure_perf()` decorator
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Example usage
After importing the package we can use the `@measure_perf()` decorator to measure the performance of a function. The decorator will print the function name and the time it takes to run.
We can also save the results to a file using the `output_file` parameter (`@measure_perf(output_file="perf_results.txt")`).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
@zw.measure_perf()
def my_function():
pass
my_function()
```
</li>
<br/>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `calibrate_camera()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def calibrate_camera(
chessBoardSize: tuple[int, int],
squareRealDimensions: float,
calibImgDirPath: str,
globImgExtension: str = "png",
saveCalibrationParams: bool = False,
calibrationParamsPath: str = "",
displayFoundCorners: bool = False,
displayMSE: bool = False,
improveSubPix: bool = True,
showListOfImagesWithChessboardFound: bool = False,
terminationCriteria: tuple[Any, int, float] = (
cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER,
30,
0.001,
),
useCharuco: bool = False,
charucoDictName: str = "DICT_6X6_250",
markerLength: float = 20.0,
displayIds: bool = False,
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to calibrate a MONO camera.
As a result, the camera matrix, distortion coefficients, and rotation and translation vectors are saved to a JSON file, which can be used later to process images.
To properly calibrate the camera, we have to specify the number of inner corners, the real-world dimension of one side of a square, and the path to the calibration images.
Before running the function we have to check the image extensions and image paths. If the extensions are not the same, an error will be raised and the function will fail.
When we want to save the calibration parameters, we also have to specify the path to the file where we want to save them and enable the `saveCalibrationParams` parameter.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
calibrationFile = "./tests/calibration_params/calibration_params.json"
imgPath = "./ZAOWiR Image set - Calibration/Chessboard/Mono 1/cam4/"
zw.calibrate_camera(
chessBoardSize=(10, 7), # NUMBER OF INNER CORNERS
squareRealDimensions=28.67, # mm
calibImgDirPath=imgPath, # PATH TO CALIBRATION IMAGES
saveCalibrationParams=True, # SAVE CALIBRATION PARAMETERS
calibrationParamsPath=calibrationFile, # PATH TO CALIBRATION PARAMETERS
displayFoundCorners=True, # DISPLAY FOUND CORNERS
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `are_params_valid()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def are_params_valid(path: str) -> tuple[bool, dict[str, Any] | None]
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to check if the calibration parameters are valid. If they are not valid, we can calibrate the camera and save the new parameters. If they are valid, we can skip the calibration and use them to process images quickly.
If the parameters are valid, the function returns `True` and the parameters as a `tuple[bool, dict[str, Any]]` and if they are not valid, the function returns `False` and `None`. If validation fails, an error will be raised.
This function **WILL NOT** provide type hints for the returned dictionary (as opposed to the `load_calibration`, `load_rectification_maps`, and `load_stereo_calibration` functions).
To check if the parameters are valid, we have to specify the path to the file where we saved them.
If the file does not exist, an error will be raised and the function will return `False` and `None` but the program will not exit.
After calibrating the camera, we can use the `are_params_valid` function to check if the new parameters are valid and exit the program if they are not.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
calibrationFile = "./tests/calibration_params/calibration_params.json"
imgPath = "./ZAOWiR Image set - Calibration/Chessboard/Mono 1/cam4/"
sub_valid, calibrationParams1 = zw.are_params_valid(calibrationFile)
if not sub_valid:
zw.calibrate_camera(
chessBoardSize=(10, 7),
squareRealDimensions=28.67,
calibImgDirPath=imgPath,
saveCalibrationParams=True,
calibrationParamsPath=calibrationFile,
displayFoundCorners=False,
)
sub_valid, calibrationParams1 = zw.are_params_valid(calibrationFile)
if not sub_valid:
raise RuntimeError("Calibration failed. Parameters are still invalid.")
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `remove_distortion()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def remove_distortion(
cameraMatrix: Any,
distortionCoefficients: Any,
imgToUndistortPath: str,
showImgToUndistort: bool = False,
showUndistortedImg: bool = False,
saveUndistortedImg: bool = False,
undistortedImgPath: str = "",
undistortionMethod: str = "undistort",
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to remove distortion from an image. As a result, we get an undistorted image.
To remove distortion from an image, we have to specify the camera matrix, distortion coefficients, and the path to the image to be undistorted. The calibration params must be valid, and we can use the `are_params_valid` function to check if they are valid and load them.
If we want to save the undistorted image, we also have to specify the path to the directory where we want to save it and enable the `saveUndistortedImg` parameter. The file will be saved with the name `{original_image_name}_undistorted{original_file_extension}`. If the directory does not exist, it will be created.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
calibrationFile = "./tests/calibration_params/calibration_params.json"
imgToUndistort = "./tests/undistorted/distorted.png"
undistortedImgPath = "./tests/undistorted/"
sub_valid, calibrationParams1 = zw.are_params_valid(calibrationFile)
if sub_valid:
zw.remove_distortion(
cameraMatrix=calibrationParams1["cameraMatrix"],
distortionCoefficients=calibrationParams1["distortionCoefficients"],
imgToUndistortPath=imgToUndistort,
saveUndistortedImg=True,
undistortedImgPath=undistortedImgPath,
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `stereo_calibration()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def stereo_calibration(
chessBoardSize: tuple[int, int],
squareRealDimensions: float,
calibImgDirPath_left: str,
calibImgDirPath_right: str,
globImgExtension: str = "png",
saveCalibrationParams: bool = False,
loadCalibrationParams: bool = False,
calibrationParamsPath_left: str = "",
calibrationParamsPath_right: str = "",
saveStereoCalibrationParams: bool = False,
stereoCalibrationParamsPath: str = "",
displayFoundCorners: bool = False,
displayMSE: bool = False,
improveSubPix: bool = True,
showListOfImagesWithChessboardFound: bool = False,
terminationCriteria: tuple[Any, int, float] = (
cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER,
30,
0.001
),
stereoCalibrationFlags: Any = cv.CALIB_FIX_INTRINSIC,
useCharuco: bool = False,
charucoDictName: str = "DICT_6X6_250",
markerLength: float = 20.0,
displayIds: bool = False,
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to calibrate the stereo camera. As a result, we get 3 files with stereo calibration parameters and the left and right camera calibration parameters.
To properly calibrate the stereo camera, we have to specify the number of inner corners, the real-world dimension of one side of a square, and the paths to the left and right calibration images.
Before running the function we have to check the image extensions and image paths. If the extensions are not the same, an error will be raised and the function will fail.
After calibrating the stereo camera, we can use the `are_params_valid` function to check if the new parameters are valid and exit the program if they are not.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
left_cam = "./ZAOWiR Image set - Calibration/Chessboard/Stereo 2/cam1/"
right_cam = "./ZAOWiR Image set - Calibration/Chessboard/Stereo 2/cam4/"
left_cam_params_stereo = "./tests/stereo_calibration_params/left_params.json"
right_cam_params_stereo = "./tests/stereo_calibration_params/right_params.json"
stereo_cam_params = "./tests/stereo_calibration_params/stereo_params.json"
left_valid, params_left = zw.are_params_valid(left_cam_params_stereo)
right_valid, params_right = zw.are_params_valid(right_cam_params_stereo)
stereo_valid, stereo_params = zw.are_params_valid(stereo_cam_params)
if not left_valid or not right_valid or not stereo_valid:
# hover over function parameters to see what they do (if names are not enough...)
zw.stereo_calibration(
chessBoardSize=(10, 7),
# squareRealDimensions=28.67,
squareRealDimensions=50.0,
calibImgDirPath_left=left_cam,
calibImgDirPath_right=right_cam,
globImgExtension="png",
saveCalibrationParams=True,
calibrationParamsPath_left=left_cam_params_stereo,
calibrationParamsPath_right=right_cam_params_stereo,
saveStereoCalibrationParams=True,
stereoCalibrationParamsPath=stereo_cam_params,
showListOfImagesWithChessboardFound=True, # Zapisz listę plików użytych do kalibracji lewej i prawej kamery.
)
# Revalidate parameters after calibration
left_valid, params_left = zw.are_params_valid(left_cam_params_stereo)
right_valid, params_right = zw.are_params_valid(right_cam_params_stereo)
stereo_valid, stereo_params = zw.are_params_valid(stereo_cam_params)
# Check again to ensure parameters are valid
if not left_valid or not right_valid or not stereo_valid:
raise RuntimeError("Calibration failed. Parameters are still invalid.")
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `calculate_fov()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def calculate_fov(cameraMatrix: np.ndarray, imageSize: tuple[float, float]) -> tuple[float, float]
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to calculate the field of view (FOV) of the camera. As a result, we get the horizontal and vertical FOV.
To calculate the FOV, we have to specify the camera matrix and the image size. The image size is the size of one of the images in the calibration images. And the camera matrix can be found in the calibration parameters.
<br/>
<br/>
```python
import cv2
import zaowr_polsl_kisiel as zw
calibrationFile = "./tests/calibration_params/calibration_params.json"
imgPath = "./ZAOWiR Image set - Calibration/Chessboard/Mono 1/cam4/1.png"
imgSize = cv2.cvtColor(cv2.imread(imgPath), cv2.COLOR_BGR2GRAY).shape[::-1]
# OR imgSize = cv2.imread(imgPath).shape[2:][::-1]
sub_valid, calibrationParams1 = zw.are_params_valid(calibrationFile)
if sub_valid:
fov_horizontal, fov_vertical = zw.calculate_fov(
cameraMatrix=calibrationParams1["cameraMatrix"],
imageSize=imgSize,
)
print(f"Horizontal fov: {fov_horizontal:.2f} degrees")
print(f"Vertical fov: {fov_vertical:.2f} degrees")
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `stereo_rectify()`
[Back to the top (TOC))](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def stereo_rectify(
calibImgDirPath_left: str,
calibImgDirPath_right: str,
cameraMatrix_left: np.ndarray = None,
cameraMatrix_right: np.ndarray = None,
distortionCoefficients_left: np.ndarray = None,
distortionCoefficients_right: np.ndarray = None,
R: np.ndarray = None,
T: np.ndarray = None,
F: np.ndarray = None,
imgPoints_left: np.ndarray = None,
imgPoints_right: np.ndarray = None,
whichImage: int = 0,
saveRectifiedImages: bool = False,
rectifiedImagesDirPath: str = "./rectifiedImages",
globImgExtension: str = "png",
showRectifiedImages: bool = False,
loadStereoCalibrationParams: bool = False,
stereoCalibrationParamsPath: str = "",
saveRectificationMaps: bool = False,
loadRectificationMaps: bool = False,
rectificationMapsPath: str = "",
testInterpolationMethods: bool = False,
drawEpipolarLinesParams: tuple[int, int, int] = (15, 2, 2),
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to rectify the stereo images. As a result, we get 3 files with stereo rectified images.
To properly rectify the stereo images, we have to specify the paths to the left and right calibration images, as well as the paths to the stereo, left and right calibration parameters and the path to the directory where we want to save the rectified images. If the directory for rectified images does not exist, it will be created.
Best practices are to calibrate the stereo camera first and then rectify the images. We can load the stereo calibration parameters in the main function and pass them to the `stereo_rectify` function, or we can pass the paths to the stereo calibration parameters and enable the `loadStereoCalibrationParams` parameter.
Before running the function we have to check the image extensions and image paths. If the extensions are not the same, an error will be raised and the function will fail.
We can specify the parameters for drawing the epipolar lines - the number of lines, the thickness of the lines, and the thickness of the ROI with the `drawEpipolarLinesParams` parameter.
`whichImage` parameter is used to specify which image to rectify. By default, it is set to 0, which means that the first set of images in the `left_cam` and `right_cam` directories will be rectified. Sometimes `glob` function can change the order ot the images in the list (in my case, `0` was actually `28.png` and not `1.png`).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
left_cam = "./ZAOWiR Image set - Calibration/Chessboard/Stereo 2/cam1/"
right_cam = "./ZAOWiR Image set - Calibration/Chessboard/Stereo 2/cam4/"
left_cam_params_stereo = "./tests/stereo_calibration_params/left_params.json"
right_cam_params_stereo = "./tests/stereo_calibration_params/right_params.json"
stereo_cam_params = "./tests/stereo_calibration_params/stereo_params.json"
rectified_images_dir = "./tests/stereo_rectified_images/"
left_valid, params_left = zw.are_params_valid(left_cam_params_stereo)
right_valid, params_right = zw.are_params_valid(right_cam_params_stereo)
stereo_valid, stereo_params = zw.are_params_valid(stereo_cam_params)
if left_valid and right_valid and stereo_valid:
zw.stereo_rectify(
calibImgDirPath_left=left_cam,
calibImgDirPath_right=right_cam,
imgPoints_left=params_left["imgPoints"],
imgPoints_right=params_right["imgPoints"],
loadStereoCalibrationParams=True,
stereoCalibrationParamsPath=stereo_cam_params,
saveRectifiedImages=True,
rectifiedImagesDirPath=rectified_images_dir,
whichImage=0,
drawEpipolarLinesParams=(20, 3, 2)
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `find_aruco_dict()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def find_aruco_dict(imgPath) -> None
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to find the aruco dictionary used by the calibration board.
This function will print the dictionary names and the number of markers found in that dictionary to the console.
e.g.
"[INFO] detected 4 markers for '4X4_50'"
"[INFO] detected 44 markers for '6X6_50'"
"[INFO] detected 44 markers for '6X6_100'"
"[INFO] detected 44 markers for '6X6_250'"
"[INFO] detected 44 markers for '6X6_1000'"
We should choose the dictionary with the highest number of markers found and lowest number of IDs in that dictionary - "6X6_100" means that the ArUco markers are 6x6 and have 100 IDs. Each charuco board should come with detailed information about the size, square size, marker size and the dictionary type [e.g. here](../tests/charuco_tests/charuco_details.jpg).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
imgPath = "./ZAOWiR Image set - Calibration/Chessboard/Mono 1/cam4/1.png"
zw.find_aruco_dict(imgPath)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `load_calibration()`
[Back to the top (TOC))](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
class CalibrationParams(TypedDict):
mse: float
rms: float
objPoints: np.ndarray
imgPoints: np.ndarray
cameraMatrix: np.ndarray
distortionCoefficients: np.ndarray
rotationVectors: list
translationVectors: list
def load_calibration(calibrationParamsPath: str) -> CalibrationParams
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to load the calibration parameters from a JSON file and return them as a `dict[str, Any]`.
This function will provide type hints for the returned dictionary.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
calibrationFile = "./tests/calibration_params/calibration_params.json"
calibrationParams1 = zw.load_calibration(calibrationFile)
mse = calibrationParams1["mse"]
rms = calibrationParams1["rms"]
# ...
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `load_rectification_maps()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
class RectificationMaps(TypedDict):
map1_left: np.ndarray
map2_left: np.ndarray
map1_right: np.ndarray
map2_right: np.ndarray
def load_rectification_maps(rectificationMapsPath: str) -> RectificationMaps
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to load the rectification maps from a JSON file and return them as a `dict[str, Any]`.
This function will provide type hints for the returned dictionary.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
rectificationMapsFile = "./tests/rectification_maps/rectification_maps.json"
rectificationMaps = zw.load_rectification_maps(rectificationMapsFile)
map1_left = rectificationMaps["map1_left"]
map2_left = rectificationMaps["map2_left"]
# ...
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `load_stereo_calibration()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
class StereoCalibrationParams(TypedDict):
reprojectionError: float
fov_left: tuple[float, float]
fov_right: tuple[float, float]
baseline: float
cameraMatrix_left: np.ndarray
distortionCoefficients_left: np.ndarray
cameraMatrix_right: np.ndarray
distortionCoefficients_right: np.ndarray
rotationMatrix: np.ndarray
translationVector: np.ndarray
essentialMatrix: np.ndarray
fundamentalMatrix: np.ndarray
def load_stereo_calibration(calibrationParamsPath: str) -> StereoCalibrationParams
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to load the stereo calibration parameters from a JSON file and return them as a `dict[str, Any]`.
This function will provide type hints for the returned dictionary.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
calibrationFile = "./tests/stereo_calibration_params/stereo_params.json"
stereoParams = zw.load_stereo_calibration(calibrationFile)
reprojectionError = stereoParams["reprojectionError"]
fov_left = stereoParams["fov_left"]
# ...
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `save_calibration()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def save_calibration(
calibrationParams: dict[str, list | Any], calibrationParamsPath: str
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to save the calibration parameters to a JSON file OR use it to save the dictionary to a JSON file.
If the directory in the `calibrationParamsPath` does not exist, it will be created.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
calibrationFile = "./tests/calibration_params/calibration_params.json"
calibrationParams = zw.load_calibration(calibrationFile)
zw.save_calibration(calibrationParams, calibrationFile)
# OR
distorted_params = {
"k1": calibrationParams["distortionCoefficients"][0][0],
"k2": calibrationParams["distortionCoefficients"][0][1],
"p1": calibrationParams["distortionCoefficients"][0][2],
"p2": calibrationParams["distortionCoefficients"][0][3],
"k3": calibrationParams["distortionCoefficients"][0][4],
}
zw.save_calibration(distorted_params, "./tests/distorted_params/distorted_params.json")
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `load_pgm_file()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def load_pgm_file(
pgmPath: str,
targetShape: tuple[int, int]
) -> np.ndarray
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to load a PGM file and return it as a numpy array. The function also resizes the image to the specified shape (usually the shape of the calculated disparity map).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
pgmPath = "./tests/disparity_maps/ground_truth.pgm"
groundTruth = zw.load_pgm_file(pgmPath, targetShape=(512, 512))
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `calculate_disparity_map()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def calculate_disparity_map(
leftImagePath: str,
rightImagePath: str,
blockSize: int = 9, # for StereoBM, StereoSGBM & Custom 2
numDisparities: int = 16, # for StereoBM & StereoSGBM
minDisparity: int = 0, # for StereoSGBM
maxDisparity: int = 64, # for Custom 1 & Custom 2
windowSize: tuple[int, int] = (11, 11), # for Custom 1
disparityCalculationMethod: str = "bm",
saveDisparityMap: bool = False,
saveDisparityMapPath: str = None,
showDisparityMap: bool = False,
normalizeDisparityMap: bool = True,
normalizeDisparityMapRange: str = "8-bit",
) -> np.ndarray:
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to calculate the disparity map and optionally save it and/or show it. We have to specify the path to the left and right images (**already rectified images!**), the block size, the number of disparities, the minimum disparity, the maximum disparity, the window size, the disparity calculation method, the save disparity map and/or show disparity map parameters.
We can choose the disparity calculation method between StereoBM, StereoSGBM, Custom 1 and Custom 2. Depending on the disparity calculation method, we have to specify different parameters.
We can normalize the disparity map using the `normalizeDisparityMap` and `normalizeDisparityMapRange` parameters (8-bit, 16-bit, 24-bit, 32-bit).
We can also show the map using the `showDisparityMap` parameter with or without saving.
<br/>
<br/>
```python
import os
import zaowr_polsl_kisiel as zw
disparityMapSGBM = zw.calculate_disparity_map(
leftImagePath="left.png", # path to the left image
rightImagePath="right.png", # path to the right image
blockSize=9, # block size for StereoBM & StereoSGBM
numDisparities=16, # number of disparities for StereoBM & StereoSGBM
minDisparity=0, # minimum disparity for StereoSGBM
disparityCalculationMethod="sgbm", # use StereoSGBM for disparity calculation
saveDisparityMap=True, # save the disparity map
saveDisparityMapPath=os.path.join("./tests/disparity_maps", "disparity_map_SGBM.png"), # path to save the disparity map
showDisparityMap=True, # show the disparity map
normalizeDisparityMap=True, # normalize the disparity map
normalizeDisparityMapRange="8-bit", # normalize the disparity map to 8-bit
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `save_disparity_map()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def save_disparity_map(
disparityMap: np.ndarray,
savePath: str,
show: bool = False,
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to save a disparity map as a PNG file and optionally show it.
We can save the disparity map to a file using the `saveDisparityMap` parameter (and `saveDisparityMapPath`) directly in the function `calculate_disparity_map()` (**recommended**).
We can also show the map using the `show` parameter with or without saving.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
disparityMap = zw.calculate_disparity_map(
leftImagePath="./tests/disparity_maps/left.png",
rightImagePath="./tests/disparity_maps/right.png",
)
zw.save_disparity_map(
disparityMap=disparityMap,
savePath="./tests/disparity_maps/disparity_map.png",
show=True
)
#######################
# OR (RECOMMENDED)
#######################
disparityMap = zw.calculate_disparity_map(
leftImagePath="./tests/disparity_maps/left.png",
rightImagePath="./tests/disparity_maps/right.png",
saveDisparityMap=True, # set saveDisparityMap to True
saveDisparityMapPath="./tests/disparity_maps/disparity_map.png", # desired path to save
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `calculate_color_difference_map()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def calculate_color_difference_map(
disparityMap: np.ndarray,
groundTruth: np.ndarray
) -> np.ndarray
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to calculate the color difference map and return it as a numpy array. We have to specify the disparity map and the ground truth image. The disparity map is calculated using the `calculate_disparity_map()` function and the ground truth image is loaded using the `load_pgm_file()` function.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
import os
disparityMapBM = zw.calculate_disparity_map(
leftImagePath=img_left,
rightImagePath=img_right,
blockSize=9,
numDisparities=16,
disparityCalculationMethod="bm",
saveDisparityMap=saveDisparityMap,
saveDisparityMapPath=os.path.join(saveDisparityMapPath, "disparity_map_BM.png"),
showDisparityMap=showMaps
)
groundTruth = zw.load_pgm_file(groundTruthPath, disparityMapBM.shape)
colorDiffBM = zw.calculate_color_difference_map(disparityMapBM, groundTruth)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `crop_image()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def crop_image(
img: np.ndarray,
cropPercentage: float = 0.75
) -> np.ndarray
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to crop an image and return it as a numpy array. We have to specify the image and the percentage of the image to crop.
Image is cropped from the top, bottom, left and right to retain only a certain percentage of the original image (75% by default).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
import os
groundTruth = zw.load_pgm_file("./tests/disparity_maps/ground_truth.pgm")
groundTruth = zw.crop_image(groundTruth, cropPercentage=0.75)
# AND
disparityMapBM = zw.calculate_disparity_map(
leftImagePath=img_left,
rightImagePath=img_right,
blockSize=9,
numDisparities=16,
disparityCalculationMethod="bm",
saveDisparityMap=saveDisparityMap,
saveDisparityMapPath=os.path.join(saveDisparityMapPath, "disparity_map_BM.png"),
showDisparityMap=showMaps
)
disparityMapBM = zw.crop_image(disparityMapBM, cropPercentage=0.75)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `calculate_mse_disparity()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def calculate_mse_disparity(
map1: np.ndarray,
map2: np.ndarray
) -> float
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to calculate the **Mean Squared Error (MSE)** of two disparity maps and return it as a float. We have to specify the two disparity maps to compare - the ground truth and the calculated disparity map. Images are cropped before calculating the MSE.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
import os
disparityMapBM = zw.calculate_disparity_map(
leftImagePath=img_left,
rightImagePath=img_right,
blockSize=9,
numDisparities=16,
disparityCalculationMethod="bm",
saveDisparityMap=saveDisparityMap,
saveDisparityMapPath=os.path.join(saveDisparityMapPath, "disparity_map_BM.png"),
showDisparityMap=showMaps
)
groundTruth = zw.load_pgm_file("./tests/disparity_maps/ground_truth.pgm", disparityMapBM.shape)
groundTruth = zw.crop_image(groundTruth, cropPercentage=0.75)
disparityMapBM = zw.crop_image(disparityMapBM, cropPercentage=0.75)
mseBM = zw.calculate_mse_disparity(disparityMapBM, groundTruth)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `calculate_ssim_disparity()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def calculate_ssim_disparity(
map1: np.ndarray,
map2: np.ndarray
) -> float
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to calculate the **Structural Similarity Index (SSIM)** of two disparity maps and return it as a float. We have to specify the two disparity maps to compare - the ground truth and the calculated disparity map. Images are cropped before calculating the SSIM.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
import os
disparityMapBM = zw.calculate_disparity_map(
leftImagePath=img_left,
rightImagePath=img_right,
blockSize=9,
numDisparities=16,
disparityCalculationMethod="bm",
saveDisparityMap=saveDisparityMap,
saveDisparityMapPath=os.path.join(saveDisparityMapPath, "disparity_map_BM.png"),
showDisparityMap=showMaps
)
groundTruth = zw.load_pgm_file("./tests/disparity_maps/ground_truth.pgm", disparityMapBM.shape)
groundTruth = zw.crop_image(groundTruth, cropPercentage=0.75)
disparityMapBM = zw.crop_image(disparityMapBM, cropPercentage=0.75)
ssimBM = zw.calculate_ssim_disparity(disparityMapBM, groundTruth)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `plot_disparity_map_comparison()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def plot_disparity_map_comparison(
disparityMapBM: np.ndarray,
disparityMapSGBM: np.ndarray,
disparityMapCustom: np.ndarray,
groundTruth: np.ndarray,
colorDiffMapBM: np.ndarray = None,
colorDiffMapSGBM: np.ndarray = None,
colorDiffMapCustom: np.ndarray = None,
showComparison: bool = False,
saveComparison: bool = False,
savePath: str = None
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to plot the comparison of three disparity maps and the ground truth. Before plotting we have to calculate the disparity maps and the color difference maps.
We can save the comparison to a file using the `saveComparison` parameter (and `savePath`) directly in the function `plot_disparity_map_comparison()` (**recommended**).
We can also show the comparison using the `showComparison` parameter with or without saving.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
import os
disparityMapBM = zw.calculate_disparity_map(...)
disparityMapSGBM = zw.calculate_disparity_map(...)
disparityMapCustom = zw.calculate_disparity_map(...)
groundTruth = zw.load_pgm_file("./ground_truth.pgm", disparityMapBM.shape)
colorDiffMapBM = zw.calculate_color_difference_map(disparityMapBM, groundTruth)
colorDiffMapSGBM = zw.calculate_color_difference_map(disparityMapSGBM, groundTruth)
colorDiffMapCustom = zw.calculate_color_difference_map(disparityMapCustom, groundTruth)
zw.plot_disparity_map_comparison(
disparityMapBM=disparityMapBM,
disparityMapSGBM=disparityMapSGBM,
disparityMapCustom=disparityMapCustom,
groundTruth=groundTruth,
colorDiffMapBM=colorDiffMapBM,
colorDiffMapSGBM=colorDiffMapSGBM,
colorDiffMapCustom=colorDiffMapCustom,
showComparison=True
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `load_depth_map_calibration()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
class DepthCalibrationParams(TypedDict):
cam0: list[list[float]]
cam1: list[list[float]]
doffs: float
baseline: float
dyavg: float
dymax: float
vmin: float
vmax: float
width: int
height: int
ndisp: int
isint: int
focalLength: float
def load_dept_map_calibration(calibFile: str) -> DepthCalibrationParams
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to load the calibration parameters from a TXT file. The function returns a dictionary with the calibration parameters as a `dict[str, Any]`.
This function will provide type hints for the returned dictionary.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
calibrationParams = zw.load_depth_map_calibration("./calibration_params.txt")
print(calibrationParams["cam0"])
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `load_pfm_file()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def load_pfm_file(
filePath: str = None
) -> tuple[np.ndarray, float]
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to load a PFM file and return it as a numpy array and a float (the image and the scale factor). We have to specify the path to the file.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
image, scale = zw.load_pfm_file("./image.pfm")
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `write_ply_file()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def write_ply_file(
fileName: str,
verts: np.ndarray,
colors: np.ndarray
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to write a PLY file. We have to specify the name of the file, the vertices and the colors.
To get the vertices and colors from an image, we can use the `cv2.reprojectImageTo3D()` and `cv2.cvtColor()` functions. Then we can apply a mask to the vertices and colors to remove the points that are too far from the camera.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
import cv2
import numpy as np
img = cv2.imread("./image.png", 0)
disparityMap = cv2.imread("./disparity_map.png", 0)
depthMap = cv2.imread("./depth_map.png", 0)
h, w = img.shape[:2]
f = 0.8 * w # focal length
Q = np.float32([[1, 0, 0, -0.5 * w],
[0, -1, 0, 0.5 * h], # turn points 180 deg around x-axis,
[0, 0, 0, -f], # so that y-axis looks up
[0, 0, 1, 0]])
points = cv2.reprojectImageTo3D(disparityMap, Q)
colors = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
mask = depthMap < 50
outPoints = points[mask]
outColors = colors[mask]
zw.write_ply_file(
fileName="./image.ply",
verts=outPoints,
colors=outColors,
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `decode_depth_map()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def decode_depth_map(
depthMap: np.ndarray,
maxDepth: float = 1000.0,
decodeDepthMapRange: str = "24-bit"
) -> np.ndarray
```
</li>
<br/>
<li> Example usage
After importing the package we can use the function to decode a depth map. We have to specify the depth map, the maximum depth and the range of the depth map to decode (e.g. **"8-bit"**, **"16-bit"**, **"24-bit"**. **ONLY USE THE 24-BIT RANGE - OTHER RANGES MAY BE INCORRECT**, check the docstring for more info).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
import cv2
depthMap_uint24 = cv2.imread("./depth_map.png", cv2.IMREAD_UNCHANGED)
maxDepth = 1000.0 # meters
depthMap_decoded = zw.decode_depth_map(
depthMap=depthMap_uint24,
maxDepth=maxDepth,
decodeDepthMapRange="24-bit",
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `depth_map_normalize()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def depth_map_normalize(
depthMap: np.ndarray,
normalizeDepthMapRange: str = "8-bit"
) -> np.ndarray
```
</li>
<br/>
<li> Example usage
After importing the package, we can use the function to normalize a depth map. The function requires the depth map and the desired range for normalization (e.g. **"8-bit"**, **"16-bit"**, **"24-bit"**. **ONLY USE THE 8-BIT AND 24-BIT RANGES - OTHER RANGES MAY BE INCORRECT**, check the docstring for more info).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
calibrationParams = zw.load_depth_map_calibration(calibFile="./calibration_params.txt")
disparityMap, scale = zw.load_pfm_file(filePath="./disparity_map.pfm")
depthMap = zw.disparity_to_depth_map(
disparityMap=disparityMap,
baseline=calibrationParams["baseline"],
focalLength=calibrationParams["focalLength"],
aspect=1000.0
)
depthMap_8bit = zw.depth_map_normalize(
depthMap=depthMap,
normalizeDepthMapRange="8-bit"
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `depth_to_disparity_map()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def depth_to_disparity_map(
depthMap: np.ndarray,
baseline: float,
focalLength: float,
minDepth: float = 0.001,
normalizeDisparityMapRange: str = "8-bit"
) -> np.ndarray
```
</li>
<br/>
<li> Example usage
After importing the package, we can use the function to convert a depth map to a disparity map. We have to specify the depth map, the baseline and the focal length of the camera. The function returns the disparity map.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
import cv2
import numpy as np
hFOV = 60
baseline = 0.1 # meters
maxDepth = 1000.0 # meters
depthMap_uint24 = cv2.imread("./depth_map.png", cv2.IMREAD_UNCHANGED) # load the 24-bit depth map
focalLength = (depthMap_uint24[0] / 2) / np.tan(np.radians(hFOV / 2))
depthMap = zw.decode_depth_map(
depthMap=depthMap_uint24,
maxDepth=maxDepth,
decodeDepthMapRange="24-bit",
)
disparityMap = zw.depth_to_disparity_map(
depthMap=depthMap,
baseline=baseline,
focalLength=focalLength,
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `disparity_map_normalize()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def disparity_map_normalize(
disparityMap: np.ndarray,
normalizeDisparityMapRange: str = "8-bit"
) -> np.ndarray
```
</li>
<br/>
<li> Example usage
This function is used only internally by the `depth_to_disparity_map()` function to normalize the disparity map after conversion, but it can also be used to normalize a disparity map on its own if we use the `calculate_disparity_map()` function with the `normalizeDisparityMap` parameter set to `False`.
After importing the package, we can use the function to normalize the calculated disparity map to the desired range.
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
disparityMapSGBM = zw.calculate_disparity_map(
leftImagePath="./left.png",
rightImagePath="./right.png",
blockSize=9,
numDisparities=256,
minDisparity=0,
disparityCalculationMethod="sgbm",
normalizeDisparityMap=False,
)
disparityMap_8bit = zw.disparity_map_normalize(
disparityMap=disparityMapSGBM,
normalizeDisparityMapRange="8-bit", # normalize the disparity map to 8-bit range (default)
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `disparity_to_depth_map()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def disparity_to_depth_map(
disparityMap: np.ndarray,
baseline: float,
focalLength: float,
aspect: float = 1000.0
) -> np.ndarray
```
</li>
<br/>
<li> Example usage
After importing the package, we can use the function to convert a disparity map into a depth map. The function requires the disparity map, the baseline (distance between the two cameras), the focal length, and an optional aspect ratio for scaling (default is 1000, which returns the depth in meters).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
calibrationParams = zw.load_depth_map_calibration(calibFile="./depth_calibration.txt")
disparityMap, _ = zw.load_pfm_file(filePath="./disparity_map.pfm")
depthMap = zw.disparity_to_depth_map(
disparityMap=disparityMap,
baseline=calibrationParams["baseline"],
focalLength=calibrationParams["focalLength"],
aspect=1000.0 # return depth in meters
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `display_img_plt()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def display_img_plt(
img: np.ndarray,
pltLabel: str = 'Map',
show: bool = False,
save: bool = False,
savePath: str = None,
cmap: str = 'gray'
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package, we can use the function to display an image using Matplotlib. The function requires the image and an optional plot label.
If the `show` parameter is set to `True`, the image will be displayed in a new window.
It can also save the image to a file if a `savePath` is provided and the `save` parameter is set to `True`.
You can also specify a custom color map using the `cmap` parameter (default is `'gray'`).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
disparityMap, _ = zw.load_pfm_file(filePath="./disparity_map.pfm")
zw.display_img_plt(
img=disparityMap,
pltLabel="Disparity map (Ground Truth PFM)",
show=True,
save=True,
savePath="./disparity_map.png",
cmap=None
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
<br/>
<br/>
### `compare_images()`
[Back to the top (TOC)](#table-of-contents)
<ol>
<li> Function definition
<br/>
<br/>
```python
def compare_images(
images: list[np.ndarray],
cmaps: list[str] = None,
pltLabel: str = 'Comparison',
titles: list[str] = None,
nrows: int = None,
ncols: int = None,
show: bool = False,
save: bool = False,
savePath: str = None
) -> None
```
</li>
<br/>
<li> Example usage
After importing the package, we can use the function to compare multiple images. The function accepts a list of images, their corresponding colormaps, and titles. You can also specify the number of rows and columns for the layout. Optionally, the resulting comparison can be saved to a file.
The function displays the images using Matplotlib and plots them in a grid layout. If `nrows` and `ncols` are not provided, the grid layout will be determined automatically based on the number of images (1 row and `n` columns, where `n` is the number of images).
<br/>
<br/>
```python
import zaowr_polsl_kisiel as zw
import cv2
# Load multiple images (e.g., disparity maps or depth maps)
disparityMap1, _ = cv2.imread("./disparity_map1.png", cv2.IMREAD_GRAYSCALE)
disparityMap2, _ = cv2.imread("./disparity_map2.png", cv2.IMREAD_GRAYSCALE)
disparityMap3, _ = cv2.imread("./disparity_map3.png", cv2.IMREAD_GRAYSCALE)
disparityMap4, _ = cv2.imread("./disparity_map4.png", cv2.IMREAD_GRAYSCALE)
# Prepare the images and their corresponding colormaps
images = [disparityMap1, disparityMap2, disparityMap3, disparityMap4]
cmaps = ['gray', 'hot', 'viridis', 'plasma'] # Different colormaps for each image
titles = ['Disparity Map 1', 'Disparity Map 2', 'Disparity Map 3', 'Disparity Map 4']
# Display and compare the images using a grid layout
zw.compare_images(
images=images,
cmaps=cmaps,
pltLabel='Comparison of Disparity and Depth Maps',
titles=titles,
nrows=2, # 2 rows in the grid
ncols=2, # 2 columns in the grid
show=True, # Display the plot
save=True, # Save the plot to a file
savePath='./output/comparison_plot.png' # File path for saving
)
```
<br/>
</li>
<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).
</li>
</ol>
Raw data
{
"_id": null,
"home_page": null,
"name": "zaowr-polsl-kisiel",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "polsl, zaowr, 2024/2025, IGT, ZAOWR",
"author": "Maksymilian Kisiel",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/0b/2d/b01b46fb8551cbaa223407185d0b2dfd1110a34d423f47472fa3c93011da/zaowr_polsl_kisiel-0.0.31.tar.gz",
"platform": null,
"description": "# ZAOWR Package\n\n<br/>\n\nThis is a **ZAOWR** (Zaawansowana Analiza Obrazu, Wideo i Ruchu, eng. _Advanced Image, Video, and Motion Analysis_) Python package used by me and my friends at the university.\n\n<br/>\n\nPyPI link to the package: <a href=\"https://pypi.org/project/zaowr-polsl-kisiel/\" target=\"_blank\"><b>MAIN PyPI</b></a>, <a href=\"https://test.pypi.org/project/zaowr-polsl-kisiel/\" target=\"_blank\"><b>TEST PyPI</b></a>.\n\n<br/>\n<br/>\n\n## Table of contents\n\n1. [Windows tutorial](./docs/WINDOWS.md)\n\n2. [RTFM - Use Cases for zaowr_polsl_kisiel and the importance of docstrings](#rtfm---use-cases-for-zaowr_polsl_kisiel-and-the-importance-of-docstrings)\n\n3. [Installing the package on Linux using `pip`](#installing-the-package-on-linux-using-pip)\n\n4. [Removing the package on Linux using `pip`](#removing-the-package-on-linux-using-pip)\n\n5. [Installing extras (optional dependencies for the package - development)](#installing-extras-optional-dependencies-for-the-package---development)\n\n6. [Creating virtual environment and installing the package](#creating-virtual-environment-and-installing-the-package)\n\n7. [Testing the installation](#testing-the-installation)\n\n8. [Automation: building and uploading with `Makefile` - DEV Tutorial](./docs/DEV_TUTORIAL.md#automation-building-and-uploading-with-makefile---dev-tutorial)\n\n9. [Building package - DEV Tutorial based on official DOCS](./docs/DEV_TUTORIAL.md#building-package---dev-tutorial-based-on-official-docs)\n\n10. [TODO for tracking issues / backlog / progress](./docs/TODO.md)\n\n11. [Code requirements](#code-requirements)\n\n12. [Sources](#sources)\n\n<br/>\n<br/>\n\n## Windows tutorial\n\nThe Windows tutorial can be found [here](./docs/WINDOWS.md)\n\n<br/>\n<br/>\n\n## RTFM - Use Cases for zaowr_polsl_kisiel and the importance of docstrings\n\n<ol>\n<li>\n<div style=\"font-size: 22px\">\n\n[RTFM v1 here](./docs/USAGE.md) (custom-made explanations with examples)\n\n</div>\n</li>\n<li>\n<div style=\"font-size: 22px\">\n\n[RTFM v2 here (GitHub Pages)](https://revalew.github.io/zaowr-py-package) (auto-generated documentation with `pdoc`)\n\n</div>\n</li>\n</ol>\n<br/>\n\n> [!IMPORTANT]\n>\n> It is really important to understand how to use the package.\n>\n> The manual explains the use cases and tells you how to use docstrings.\n>\n> More examples (exact lab solutions) can be found [here](./tests/lab_exercise_solutions/)\n\n<br/>\n<br/>\n\n## Installing the package on Linux using `pip`\n\n<ol>\n\n<li> PyPI MAIN\n\n<br/>\n<br/>\n\n```bash\npython3 -m pip install --upgrade zaowr-polsl-kisiel\n```\n\n</li>\n<br/>\n<li> TestPyPI\n\n<br/>\n<br/>\n\n```bash\npython3 -m pip install --index-url https://test.pypi.org/simple/ --upgrade zaowr-polsl-kisiel\n```\n\n</li>\n\n</ol>\n\n<br/>\n<br/>\n\n## Removing the package on Linux using `pip`\n\n<br/>\n\n```bash\npython3 -m pip uninstall zaowr-polsl-kisiel\n```\n\n<br/>\n<br/>\n\n## Installing extras (optional dependencies for the package - development)\n\n```bash\npython3 -m pip install --upgrade \"zaowr-polsl-kisiel[dev]\"\n```\n\n<br/>\n<br/>\n\n## Creating virtual environment and installing the package\n\n<br/>\n\n> [!NOTE]\n>\n> Complete instructions on managing Python virtual environments\n>\n> can be found [here](https://github.com/revalew/Python-Venv).\n\n<br/>\n<ol>\n<li> Create project directory and open it (directory where you will create your files and where the venv will be created). Below is an example of how to do it through Bash - you can also do it through file explorer\n\n<br/>\n<br/>\n\n```bash\ntestDir=/home/user/test\n```\n\n```bash\nmkdir -p $testDir\n```\n\n```bash\ncd $testDir\n```\n\n<br/>\n\n</li>\n<li> Create venv\n\n<br/>\n<br/>\n\n```bash\npython -m venv ENV_NAME\n```\n\n</li>\n<br/>\n\n> [!NOTE]\n>\n> `ENV_NAME` is the name of your venv, so you can change it however you like\n\n<br/>\n\n<li> Activate the venv (while in the project directory)\n\n<br/>\n<br/>\n\n```bash\nsource ENV_NAME/bin/activate\n```\n\nor\n\n```bash\n. ENV_NAME/bin/activate\n```\n\n</li>\n\n<br/>\n\n<li> Install the package from PyPI\n\n<br/>\n<br/>\n\n```bash\npython3 -m pip install --upgrade zaowr-polsl-kisiel\n```\n\n</li>\n\n<br/>\n\n<li> <b>(ADDITIONAL COMMAND)</b> If you want to deactivate the currently active venv\n\n<br/>\n<br/>\n\n```bash\ndeactivate\n```\n\n</li>\n\n<br/>\n\n<li> <b>(ADDITIONAL COMMAND)</b> To reactivate the venv, navigate to the path where you created the venv and source it again (command shown above in section number 3)\n</li>\n\n</ol>\n\n<br/>\n<br/>\n\n## Testing the installation\n\n<br/>\n\n<ul>\n<li> Activate the venv (while in the project directory) - <b>Skip this step if you are not using a virtual environment</b>\n\n<br/>\n<br/>\n\n```bash\nsource ENV_NAME/bin/activate\n```\n\nor\n\n```bash\n. ENV_NAME/bin/activate\n```\n\n</li>\n\n<br/>\n\n<li> Launch python\n\n<br/>\n<br/>\n\n```bash\npython3\n```\n\n</li>\n\n<br/>\n\n<li> Import the package\n\n<br/>\n<br/>\n\n```python\nfrom zaowr_polsl_kisiel import load_calibration\n```\n\n</li>\n<br/>\n\n<li> Locate the file with calibration params in tests folder and download it (link below)\n\n<br/>\n<br/>\n\n[`./tests/misc/calibration_params/calibration_params.json`](./tests/misc/calibration_params/calibration_params.json)\n\n</li>\n<br/>\n\n<li> Try reading the params from file\n\n<br/>\n<br/>\n\n```python\n# remember to provide appropriate path to the calibration params\ncalibrationParams = load_calibration(\"/path/to/calibration_params.json\")\n```\n\n</li>\n<br/>\n\n<li> Display the <code>MSE</code> value to test if the load succeeded\n\n<br/>\n<br/>\n\n```python\nprint(calibrationParams[\"mse\"])\n```\n\n</li>\n</ul>\n\n<br/>\n<br/>\n\n## Code requirements\n\nThe code fulfills all the requirements necessary to pass the course. Detailed descriptions of the requirements for each lab are provided in the [`./docs/code_requirements`](./docs/code_requirements/) directory in the form of images (in Polish).\n\n<br/>\n<br/>\n\n## Sources\n\nThis package has been prepared following [this tutorial](https://packaging.python.org/en/latest/tutorials/packaging-projects/)\n\nThe publishing to PyPI was created with [this tutorial](https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/)\n\n# RTFM - Use Cases for zaowr_polsl_kisiel and the importance of docstrings\n\n<br/>\n<br/>\n\n<div style=\"font-size: 22px\">\n\n[RTFM v2 here (GitHub Pages)](https://revalew.github.io/zaowr-py-package) (auto-generated documentation with `pdoc`)\n\n</div>\n\n<br/>\n<br/>\n\n## Table of Contents\n\n1. [`Docstrings`](#docstrings)\n2. [`@measure_perf() decorator`](#measure_perf-decorator)\n3. [`calibrate_camera()`](#calibrate_camera)\n4. [`are_params_valid()`](#are_params_valid)\n5. [`remove_distortion()`](#remove_distortion)\n6. [`stereo_calibration()`](#stereo_calibration)\n7. [`calculate_fov()`](#calculate_fov)\n8. [`stereo_rectify()`](#stereo_rectify)\n9. [`find_aruco_dict()`](#find_aruco_dict)\n10. [`load_calibration()`](#load_calibration)\n11. [`load_rectification_maps()`](#load_rectification_maps)\n12. [`load_stereo_calibration()`](#load_stereo_calibration)\n13. [`save_calibration()`](#save_calibration)\n14. [`load_pgm_file()`](#load_pgm_file)\n15. [`calculate_disparity_map()`](#calculate_disparity_map)\n16. [`save_disparity_map()`](#save_disparity_map)\n17. [`calculate_color_difference_map()`](#calculate_color_difference_map)\n18. [`crop_image()`](#crop_image)\n19. [`calculate_mse_disparity()`](#calculate_mse_disparity)\n20. [`calculate_ssim_disparity()`](#calculate_ssim_disparity)\n21. [`plot_disparity_map_comparison()`](#plot_disparity_map_comparison)\n22. [`load_depth_map_calibration()`](#load_depth_map_calibration)\n23. [`load_pfm_file()`](#load_pfm_file)\n24. [`write_ply_file()`](#write_ply_file)\n25. [`decode_depth_map()`](#decode_depth_map)\n26. [`depth_map_normalize()`](#depth_map_normalize)\n27. [`depth_to_disparity_map()`](#depth_to_disparity_map)\n28. [`disparity_map_normalize()`](#disparity_map_normalize)\n29. [`disparity_to_depth_map()`](#disparity_to_depth_map)\n30. [`display_img_plt()`](#display_img_plt)\n31. [`compare_images()`](#compare_images). \n\n<br/>\n<br/>\n\n### Docstrings\n\nUsing Python Docstrings to Enhance Understanding\n\nIn Python, docstrings are a way to provide documentation for your functions, classes, and modules. They explain what your code does, what each parameter does, what is returned and how to use it. They are written between triple quotes (\"\"\") and are often used to explain the purpose of a function, class, or module.\n\n<ul>\n<li> In IDEs or Text Editors: Many modern Integrated Development Environments (IDEs) and text editors, such as PyCharm, Visual Studio Code, or Jupyter Notebook, allow you to hover your mouse over a function to see its description provided by the docstring. Similarly, hovering over a parameter will display information about what that parameter does (if it is described in the docstring).\n\n</li>\n<br/>\n<li> In the Terminal: You can read docstrings in the terminal using the help() function, which prints the docstring to the console.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\n# Display documentation for the entire module\nhelp(zw)\n\n# Display specific submodule's documentation\nhelp(zw.calibration)\n\n# Display detailed documentation for a specific function\nhelp(zw.calibrate_camera)\n```\n\n</li>\n</ul>\n<br/>\n<br/>\n\n### `@measure_perf()` decorator\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Example usage\n\nAfter importing the package we can use the `@measure_perf()` decorator to measure the performance of a function. The decorator will print the function name and the time it takes to run.\n\nWe can also save the results to a file using the `output_file` parameter (`@measure_perf(output_file=\"perf_results.txt\")`).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\n@zw.measure_perf()\ndef my_function():\n pass\n\nmy_function()\n```\n\n</li>\n<br/>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n\n<br/>\n<br/>\n\n### `calibrate_camera()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef calibrate_camera(\n chessBoardSize: tuple[int, int],\n squareRealDimensions: float,\n calibImgDirPath: str,\n globImgExtension: str = \"png\",\n saveCalibrationParams: bool = False,\n calibrationParamsPath: str = \"\",\n displayFoundCorners: bool = False,\n displayMSE: bool = False,\n improveSubPix: bool = True,\n showListOfImagesWithChessboardFound: bool = False,\n terminationCriteria: tuple[Any, int, float] = (\n cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER,\n 30,\n 0.001,\n ),\n useCharuco: bool = False,\n charucoDictName: str = \"DICT_6X6_250\",\n markerLength: float = 20.0,\n displayIds: bool = False,\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to calibrate a MONO camera.\nAs a result, the camera matrix, distortion coefficients, and rotation and translation vectors are saved to a JSON file, which can be used later to process images.\n\nTo properly calibrate the camera, we have to specify the number of inner corners, the real-world dimension of one side of a square, and the path to the calibration images.\n\nBefore running the function we have to check the image extensions and image paths. If the extensions are not the same, an error will be raised and the function will fail.\n\nWhen we want to save the calibration parameters, we also have to specify the path to the file where we want to save them and enable the `saveCalibrationParams` parameter.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ncalibrationFile = \"./tests/calibration_params/calibration_params.json\"\n\nimgPath = \"./ZAOWiR Image set - Calibration/Chessboard/Mono 1/cam4/\"\n\nzw.calibrate_camera(\n chessBoardSize=(10, 7), # NUMBER OF INNER CORNERS\n squareRealDimensions=28.67, # mm\n calibImgDirPath=imgPath, # PATH TO CALIBRATION IMAGES\n saveCalibrationParams=True, # SAVE CALIBRATION PARAMETERS\n calibrationParamsPath=calibrationFile, # PATH TO CALIBRATION PARAMETERS\n displayFoundCorners=True, # DISPLAY FOUND CORNERS\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `are_params_valid()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef are_params_valid(path: str) -> tuple[bool, dict[str, Any] | None]\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to check if the calibration parameters are valid. If they are not valid, we can calibrate the camera and save the new parameters. If they are valid, we can skip the calibration and use them to process images quickly.\n\nIf the parameters are valid, the function returns `True` and the parameters as a `tuple[bool, dict[str, Any]]` and if they are not valid, the function returns `False` and `None`. If validation fails, an error will be raised.\n\nThis function **WILL NOT** provide type hints for the returned dictionary (as opposed to the `load_calibration`, `load_rectification_maps`, and `load_stereo_calibration` functions).\n\nTo check if the parameters are valid, we have to specify the path to the file where we saved them.\n\nIf the file does not exist, an error will be raised and the function will return `False` and `None` but the program will not exit.\n\nAfter calibrating the camera, we can use the `are_params_valid` function to check if the new parameters are valid and exit the program if they are not.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ncalibrationFile = \"./tests/calibration_params/calibration_params.json\"\n\nimgPath = \"./ZAOWiR Image set - Calibration/Chessboard/Mono 1/cam4/\"\n\nsub_valid, calibrationParams1 = zw.are_params_valid(calibrationFile)\n\nif not sub_valid:\n zw.calibrate_camera(\n chessBoardSize=(10, 7),\n squareRealDimensions=28.67,\n calibImgDirPath=imgPath,\n saveCalibrationParams=True,\n calibrationParamsPath=calibrationFile,\n displayFoundCorners=False,\n )\n\n sub_valid, calibrationParams1 = zw.are_params_valid(calibrationFile)\n\n if not sub_valid:\n raise RuntimeError(\"Calibration failed. Parameters are still invalid.\")\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `remove_distortion()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef remove_distortion(\n cameraMatrix: Any,\n distortionCoefficients: Any,\n imgToUndistortPath: str,\n showImgToUndistort: bool = False,\n showUndistortedImg: bool = False,\n saveUndistortedImg: bool = False,\n undistortedImgPath: str = \"\",\n undistortionMethod: str = \"undistort\",\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to remove distortion from an image. As a result, we get an undistorted image.\n\nTo remove distortion from an image, we have to specify the camera matrix, distortion coefficients, and the path to the image to be undistorted. The calibration params must be valid, and we can use the `are_params_valid` function to check if they are valid and load them.\n\nIf we want to save the undistorted image, we also have to specify the path to the directory where we want to save it and enable the `saveUndistortedImg` parameter. The file will be saved with the name `{original_image_name}_undistorted{original_file_extension}`. If the directory does not exist, it will be created.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ncalibrationFile = \"./tests/calibration_params/calibration_params.json\"\n\nimgToUndistort = \"./tests/undistorted/distorted.png\"\n\nundistortedImgPath = \"./tests/undistorted/\"\n\nsub_valid, calibrationParams1 = zw.are_params_valid(calibrationFile)\n\nif sub_valid:\n zw.remove_distortion(\n cameraMatrix=calibrationParams1[\"cameraMatrix\"],\n distortionCoefficients=calibrationParams1[\"distortionCoefficients\"],\n imgToUndistortPath=imgToUndistort,\n saveUndistortedImg=True,\n undistortedImgPath=undistortedImgPath,\n )\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `stereo_calibration()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef stereo_calibration(\n chessBoardSize: tuple[int, int],\n squareRealDimensions: float,\n calibImgDirPath_left: str,\n calibImgDirPath_right: str,\n globImgExtension: str = \"png\",\n saveCalibrationParams: bool = False,\n loadCalibrationParams: bool = False,\n calibrationParamsPath_left: str = \"\",\n calibrationParamsPath_right: str = \"\",\n saveStereoCalibrationParams: bool = False,\n stereoCalibrationParamsPath: str = \"\",\n displayFoundCorners: bool = False,\n displayMSE: bool = False,\n improveSubPix: bool = True,\n showListOfImagesWithChessboardFound: bool = False,\n terminationCriteria: tuple[Any, int, float] = (\n cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER,\n 30,\n 0.001\n ),\n stereoCalibrationFlags: Any = cv.CALIB_FIX_INTRINSIC,\n useCharuco: bool = False,\n charucoDictName: str = \"DICT_6X6_250\",\n markerLength: float = 20.0,\n displayIds: bool = False,\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to calibrate the stereo camera. As a result, we get 3 files with stereo calibration parameters and the left and right camera calibration parameters.\n\nTo properly calibrate the stereo camera, we have to specify the number of inner corners, the real-world dimension of one side of a square, and the paths to the left and right calibration images.\n\nBefore running the function we have to check the image extensions and image paths. If the extensions are not the same, an error will be raised and the function will fail.\n\nAfter calibrating the stereo camera, we can use the `are_params_valid` function to check if the new parameters are valid and exit the program if they are not.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\nleft_cam = \"./ZAOWiR Image set - Calibration/Chessboard/Stereo 2/cam1/\"\nright_cam = \"./ZAOWiR Image set - Calibration/Chessboard/Stereo 2/cam4/\"\n\nleft_cam_params_stereo = \"./tests/stereo_calibration_params/left_params.json\"\nright_cam_params_stereo = \"./tests/stereo_calibration_params/right_params.json\"\nstereo_cam_params = \"./tests/stereo_calibration_params/stereo_params.json\"\n\nleft_valid, params_left = zw.are_params_valid(left_cam_params_stereo)\nright_valid, params_right = zw.are_params_valid(right_cam_params_stereo)\nstereo_valid, stereo_params = zw.are_params_valid(stereo_cam_params)\n\nif not left_valid or not right_valid or not stereo_valid:\n # hover over function parameters to see what they do (if names are not enough...)\n zw.stereo_calibration(\n chessBoardSize=(10, 7),\n # squareRealDimensions=28.67,\n squareRealDimensions=50.0,\n calibImgDirPath_left=left_cam,\n calibImgDirPath_right=right_cam,\n globImgExtension=\"png\",\n saveCalibrationParams=True,\n calibrationParamsPath_left=left_cam_params_stereo,\n calibrationParamsPath_right=right_cam_params_stereo,\n saveStereoCalibrationParams=True,\n stereoCalibrationParamsPath=stereo_cam_params,\n showListOfImagesWithChessboardFound=True, # Zapisz list\u0119 plik\u00f3w u\u017cytych do kalibracji lewej i prawej kamery.\n )\n\n # Revalidate parameters after calibration\n left_valid, params_left = zw.are_params_valid(left_cam_params_stereo)\n right_valid, params_right = zw.are_params_valid(right_cam_params_stereo)\n stereo_valid, stereo_params = zw.are_params_valid(stereo_cam_params)\n\n # Check again to ensure parameters are valid\n if not left_valid or not right_valid or not stereo_valid:\n raise RuntimeError(\"Calibration failed. Parameters are still invalid.\")\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `calculate_fov()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef calculate_fov(cameraMatrix: np.ndarray, imageSize: tuple[float, float]) -> tuple[float, float]\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to calculate the field of view (FOV) of the camera. As a result, we get the horizontal and vertical FOV.\n\nTo calculate the FOV, we have to specify the camera matrix and the image size. The image size is the size of one of the images in the calibration images. And the camera matrix can be found in the calibration parameters.\n\n<br/>\n<br/>\n\n```python\nimport cv2\nimport zaowr_polsl_kisiel as zw\n\ncalibrationFile = \"./tests/calibration_params/calibration_params.json\"\n\nimgPath = \"./ZAOWiR Image set - Calibration/Chessboard/Mono 1/cam4/1.png\"\n\nimgSize = cv2.cvtColor(cv2.imread(imgPath), cv2.COLOR_BGR2GRAY).shape[::-1]\n# OR imgSize = cv2.imread(imgPath).shape[2:][::-1]\n\nsub_valid, calibrationParams1 = zw.are_params_valid(calibrationFile)\n\nif sub_valid:\n fov_horizontal, fov_vertical = zw.calculate_fov(\n cameraMatrix=calibrationParams1[\"cameraMatrix\"],\n imageSize=imgSize,\n )\n print(f\"Horizontal fov: {fov_horizontal:.2f} degrees\")\n print(f\"Vertical fov: {fov_vertical:.2f} degrees\")\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `stereo_rectify()`\n\n[Back to the top (TOC))](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef stereo_rectify(\n calibImgDirPath_left: str,\n calibImgDirPath_right: str,\n cameraMatrix_left: np.ndarray = None,\n cameraMatrix_right: np.ndarray = None,\n distortionCoefficients_left: np.ndarray = None,\n distortionCoefficients_right: np.ndarray = None,\n R: np.ndarray = None,\n T: np.ndarray = None,\n F: np.ndarray = None,\n imgPoints_left: np.ndarray = None,\n imgPoints_right: np.ndarray = None,\n whichImage: int = 0,\n saveRectifiedImages: bool = False,\n rectifiedImagesDirPath: str = \"./rectifiedImages\",\n globImgExtension: str = \"png\",\n showRectifiedImages: bool = False,\n loadStereoCalibrationParams: bool = False,\n stereoCalibrationParamsPath: str = \"\",\n saveRectificationMaps: bool = False,\n loadRectificationMaps: bool = False,\n rectificationMapsPath: str = \"\",\n testInterpolationMethods: bool = False,\n drawEpipolarLinesParams: tuple[int, int, int] = (15, 2, 2),\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to rectify the stereo images. As a result, we get 3 files with stereo rectified images.\n\nTo properly rectify the stereo images, we have to specify the paths to the left and right calibration images, as well as the paths to the stereo, left and right calibration parameters and the path to the directory where we want to save the rectified images. If the directory for rectified images does not exist, it will be created.\n\nBest practices are to calibrate the stereo camera first and then rectify the images. We can load the stereo calibration parameters in the main function and pass them to the `stereo_rectify` function, or we can pass the paths to the stereo calibration parameters and enable the `loadStereoCalibrationParams` parameter. \n\nBefore running the function we have to check the image extensions and image paths. If the extensions are not the same, an error will be raised and the function will fail.\n\nWe can specify the parameters for drawing the epipolar lines - the number of lines, the thickness of the lines, and the thickness of the ROI with the `drawEpipolarLinesParams` parameter.\n\n`whichImage` parameter is used to specify which image to rectify. By default, it is set to 0, which means that the first set of images in the `left_cam` and `right_cam` directories will be rectified. Sometimes `glob` function can change the order ot the images in the list (in my case, `0` was actually `28.png` and not `1.png`).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\nleft_cam = \"./ZAOWiR Image set - Calibration/Chessboard/Stereo 2/cam1/\"\nright_cam = \"./ZAOWiR Image set - Calibration/Chessboard/Stereo 2/cam4/\"\n\nleft_cam_params_stereo = \"./tests/stereo_calibration_params/left_params.json\"\nright_cam_params_stereo = \"./tests/stereo_calibration_params/right_params.json\"\nstereo_cam_params = \"./tests/stereo_calibration_params/stereo_params.json\"\n\nrectified_images_dir = \"./tests/stereo_rectified_images/\"\n\nleft_valid, params_left = zw.are_params_valid(left_cam_params_stereo)\nright_valid, params_right = zw.are_params_valid(right_cam_params_stereo)\nstereo_valid, stereo_params = zw.are_params_valid(stereo_cam_params)\n\nif left_valid and right_valid and stereo_valid:\n zw.stereo_rectify(\n calibImgDirPath_left=left_cam,\n calibImgDirPath_right=right_cam,\n imgPoints_left=params_left[\"imgPoints\"],\n imgPoints_right=params_right[\"imgPoints\"],\n loadStereoCalibrationParams=True,\n stereoCalibrationParamsPath=stereo_cam_params,\n saveRectifiedImages=True,\n rectifiedImagesDirPath=rectified_images_dir,\n whichImage=0,\n drawEpipolarLinesParams=(20, 3, 2)\n )\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `find_aruco_dict()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef find_aruco_dict(imgPath) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to find the aruco dictionary used by the calibration board. \n\nThis function will print the dictionary names and the number of markers found in that dictionary to the console.\n\ne.g.\n \"[INFO] detected 4 markers for '4X4_50'\"\n \"[INFO] detected 44 markers for '6X6_50'\"\n \"[INFO] detected 44 markers for '6X6_100'\"\n \"[INFO] detected 44 markers for '6X6_250'\"\n \"[INFO] detected 44 markers for '6X6_1000'\"\n\nWe should choose the dictionary with the highest number of markers found and lowest number of IDs in that dictionary - \"6X6_100\" means that the ArUco markers are 6x6 and have 100 IDs. Each charuco board should come with detailed information about the size, square size, marker size and the dictionary type [e.g. here](../tests/charuco_tests/charuco_details.jpg).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\nimgPath = \"./ZAOWiR Image set - Calibration/Chessboard/Mono 1/cam4/1.png\"\n\nzw.find_aruco_dict(imgPath)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `load_calibration()`\n\n[Back to the top (TOC))](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\nclass CalibrationParams(TypedDict):\n mse: float\n rms: float\n objPoints: np.ndarray\n imgPoints: np.ndarray\n cameraMatrix: np.ndarray\n distortionCoefficients: np.ndarray\n rotationVectors: list\n translationVectors: list\n\n\ndef load_calibration(calibrationParamsPath: str) -> CalibrationParams\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to load the calibration parameters from a JSON file and return them as a `dict[str, Any]`.\n\nThis function will provide type hints for the returned dictionary.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ncalibrationFile = \"./tests/calibration_params/calibration_params.json\"\n\ncalibrationParams1 = zw.load_calibration(calibrationFile)\n\nmse = calibrationParams1[\"mse\"]\nrms = calibrationParams1[\"rms\"]\n# ...\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `load_rectification_maps()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\nclass RectificationMaps(TypedDict):\n map1_left: np.ndarray\n map2_left: np.ndarray\n map1_right: np.ndarray\n map2_right: np.ndarray\n\n\ndef load_rectification_maps(rectificationMapsPath: str) -> RectificationMaps\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to load the rectification maps from a JSON file and return them as a `dict[str, Any]`.\n\nThis function will provide type hints for the returned dictionary.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\nrectificationMapsFile = \"./tests/rectification_maps/rectification_maps.json\"\n\nrectificationMaps = zw.load_rectification_maps(rectificationMapsFile)\n\nmap1_left = rectificationMaps[\"map1_left\"]\nmap2_left = rectificationMaps[\"map2_left\"]\n# ...\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `load_stereo_calibration()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\nclass StereoCalibrationParams(TypedDict):\n reprojectionError: float\n fov_left: tuple[float, float]\n fov_right: tuple[float, float]\n baseline: float\n cameraMatrix_left: np.ndarray\n distortionCoefficients_left: np.ndarray\n cameraMatrix_right: np.ndarray\n distortionCoefficients_right: np.ndarray\n rotationMatrix: np.ndarray\n translationVector: np.ndarray\n essentialMatrix: np.ndarray\n fundamentalMatrix: np.ndarray\n\n\ndef load_stereo_calibration(calibrationParamsPath: str) -> StereoCalibrationParams\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to load the stereo calibration parameters from a JSON file and return them as a `dict[str, Any]`.\n\nThis function will provide type hints for the returned dictionary.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ncalibrationFile = \"./tests/stereo_calibration_params/stereo_params.json\"\n\nstereoParams = zw.load_stereo_calibration(calibrationFile)\n\nreprojectionError = stereoParams[\"reprojectionError\"]\nfov_left = stereoParams[\"fov_left\"]\n# ...\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `save_calibration()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef save_calibration(\n calibrationParams: dict[str, list | Any], calibrationParamsPath: str\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to save the calibration parameters to a JSON file OR use it to save the dictionary to a JSON file.\n\nIf the directory in the `calibrationParamsPath` does not exist, it will be created.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ncalibrationFile = \"./tests/calibration_params/calibration_params.json\"\n\ncalibrationParams = zw.load_calibration(calibrationFile)\n\nzw.save_calibration(calibrationParams, calibrationFile)\n\n# OR\n\ndistorted_params = {\n \"k1\": calibrationParams[\"distortionCoefficients\"][0][0],\n \"k2\": calibrationParams[\"distortionCoefficients\"][0][1],\n \"p1\": calibrationParams[\"distortionCoefficients\"][0][2],\n \"p2\": calibrationParams[\"distortionCoefficients\"][0][3],\n \"k3\": calibrationParams[\"distortionCoefficients\"][0][4],\n}\n\nzw.save_calibration(distorted_params, \"./tests/distorted_params/distorted_params.json\")\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `load_pgm_file()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef load_pgm_file(\n pgmPath: str,\n targetShape: tuple[int, int]\n) -> np.ndarray\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to load a PGM file and return it as a numpy array. The function also resizes the image to the specified shape (usually the shape of the calculated disparity map).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\npgmPath = \"./tests/disparity_maps/ground_truth.pgm\"\n\ngroundTruth = zw.load_pgm_file(pgmPath, targetShape=(512, 512))\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `calculate_disparity_map()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef calculate_disparity_map(\n leftImagePath: str,\n rightImagePath: str,\n blockSize: int = 9, # for StereoBM, StereoSGBM & Custom 2\n numDisparities: int = 16, # for StereoBM & StereoSGBM\n minDisparity: int = 0, # for StereoSGBM\n maxDisparity: int = 64, # for Custom 1 & Custom 2\n windowSize: tuple[int, int] = (11, 11), # for Custom 1\n disparityCalculationMethod: str = \"bm\",\n saveDisparityMap: bool = False,\n saveDisparityMapPath: str = None,\n showDisparityMap: bool = False,\n normalizeDisparityMap: bool = True,\n normalizeDisparityMapRange: str = \"8-bit\",\n) -> np.ndarray:\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to calculate the disparity map and optionally save it and/or show it. We have to specify the path to the left and right images (**already rectified images!**), the block size, the number of disparities, the minimum disparity, the maximum disparity, the window size, the disparity calculation method, the save disparity map and/or show disparity map parameters.\n\nWe can choose the disparity calculation method between StereoBM, StereoSGBM, Custom 1 and Custom 2. Depending on the disparity calculation method, we have to specify different parameters.\n\nWe can normalize the disparity map using the `normalizeDisparityMap` and `normalizeDisparityMapRange` parameters (8-bit, 16-bit, 24-bit, 32-bit). \n\nWe can also show the map using the `showDisparityMap` parameter with or without saving.\n\n<br/>\n<br/>\n\n```python\nimport os\nimport zaowr_polsl_kisiel as zw\n\ndisparityMapSGBM = zw.calculate_disparity_map(\n leftImagePath=\"left.png\", # path to the left image\n rightImagePath=\"right.png\", # path to the right image\n blockSize=9, # block size for StereoBM & StereoSGBM\n numDisparities=16, # number of disparities for StereoBM & StereoSGBM\n minDisparity=0, # minimum disparity for StereoSGBM\n disparityCalculationMethod=\"sgbm\", # use StereoSGBM for disparity calculation\n saveDisparityMap=True, # save the disparity map\n saveDisparityMapPath=os.path.join(\"./tests/disparity_maps\", \"disparity_map_SGBM.png\"), # path to save the disparity map\n showDisparityMap=True, # show the disparity map\n normalizeDisparityMap=True, # normalize the disparity map\n normalizeDisparityMapRange=\"8-bit\", # normalize the disparity map to 8-bit\n )\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `save_disparity_map()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef save_disparity_map(\n disparityMap: np.ndarray,\n savePath: str,\n show: bool = False,\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to save a disparity map as a PNG file and optionally show it.\n\nWe can save the disparity map to a file using the `saveDisparityMap` parameter (and `saveDisparityMapPath`) directly in the function `calculate_disparity_map()` (**recommended**). \n\nWe can also show the map using the `show` parameter with or without saving.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ndisparityMap = zw.calculate_disparity_map(\n leftImagePath=\"./tests/disparity_maps/left.png\",\n rightImagePath=\"./tests/disparity_maps/right.png\",\n)\n\nzw.save_disparity_map(\n disparityMap=disparityMap,\n savePath=\"./tests/disparity_maps/disparity_map.png\",\n show=True\n)\n\n#######################\n# OR (RECOMMENDED)\n#######################\n\ndisparityMap = zw.calculate_disparity_map(\n leftImagePath=\"./tests/disparity_maps/left.png\",\n rightImagePath=\"./tests/disparity_maps/right.png\",\n saveDisparityMap=True, # set saveDisparityMap to True\n saveDisparityMapPath=\"./tests/disparity_maps/disparity_map.png\", # desired path to save\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `calculate_color_difference_map()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef calculate_color_difference_map(\n disparityMap: np.ndarray,\n groundTruth: np.ndarray\n) -> np.ndarray\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to calculate the color difference map and return it as a numpy array. We have to specify the disparity map and the ground truth image. The disparity map is calculated using the `calculate_disparity_map()` function and the ground truth image is loaded using the `load_pgm_file()` function.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\nimport os\n\ndisparityMapBM = zw.calculate_disparity_map(\n leftImagePath=img_left,\n rightImagePath=img_right,\n blockSize=9,\n numDisparities=16,\n disparityCalculationMethod=\"bm\",\n saveDisparityMap=saveDisparityMap,\n saveDisparityMapPath=os.path.join(saveDisparityMapPath, \"disparity_map_BM.png\"),\n showDisparityMap=showMaps\n )\ngroundTruth = zw.load_pgm_file(groundTruthPath, disparityMapBM.shape)\ncolorDiffBM = zw.calculate_color_difference_map(disparityMapBM, groundTruth)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `crop_image()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef crop_image(\n img: np.ndarray,\n cropPercentage: float = 0.75\n) -> np.ndarray\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to crop an image and return it as a numpy array. We have to specify the image and the percentage of the image to crop.\n\nImage is cropped from the top, bottom, left and right to retain only a certain percentage of the original image (75% by default).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\nimport os\n\ngroundTruth = zw.load_pgm_file(\"./tests/disparity_maps/ground_truth.pgm\")\ngroundTruth = zw.crop_image(groundTruth, cropPercentage=0.75)\n\n# AND\n\ndisparityMapBM = zw.calculate_disparity_map(\n leftImagePath=img_left,\n rightImagePath=img_right,\n blockSize=9,\n numDisparities=16,\n disparityCalculationMethod=\"bm\",\n saveDisparityMap=saveDisparityMap,\n saveDisparityMapPath=os.path.join(saveDisparityMapPath, \"disparity_map_BM.png\"),\n showDisparityMap=showMaps\n )\ndisparityMapBM = zw.crop_image(disparityMapBM, cropPercentage=0.75)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `calculate_mse_disparity()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef calculate_mse_disparity(\n map1: np.ndarray,\n map2: np.ndarray\n) -> float\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to calculate the **Mean Squared Error (MSE)** of two disparity maps and return it as a float. We have to specify the two disparity maps to compare - the ground truth and the calculated disparity map. Images are cropped before calculating the MSE.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\nimport os\n\ndisparityMapBM = zw.calculate_disparity_map(\n leftImagePath=img_left,\n rightImagePath=img_right,\n blockSize=9,\n numDisparities=16,\n disparityCalculationMethod=\"bm\",\n saveDisparityMap=saveDisparityMap,\n saveDisparityMapPath=os.path.join(saveDisparityMapPath, \"disparity_map_BM.png\"),\n showDisparityMap=showMaps\n )\ngroundTruth = zw.load_pgm_file(\"./tests/disparity_maps/ground_truth.pgm\", disparityMapBM.shape)\n\ngroundTruth = zw.crop_image(groundTruth, cropPercentage=0.75)\ndisparityMapBM = zw.crop_image(disparityMapBM, cropPercentage=0.75)\n\nmseBM = zw.calculate_mse_disparity(disparityMapBM, groundTruth)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `calculate_ssim_disparity()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef calculate_ssim_disparity(\n map1: np.ndarray,\n map2: np.ndarray\n) -> float\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to calculate the **Structural Similarity Index (SSIM)** of two disparity maps and return it as a float. We have to specify the two disparity maps to compare - the ground truth and the calculated disparity map. Images are cropped before calculating the SSIM.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\nimport os\n\ndisparityMapBM = zw.calculate_disparity_map(\n leftImagePath=img_left,\n rightImagePath=img_right,\n blockSize=9,\n numDisparities=16,\n disparityCalculationMethod=\"bm\",\n saveDisparityMap=saveDisparityMap,\n saveDisparityMapPath=os.path.join(saveDisparityMapPath, \"disparity_map_BM.png\"),\n showDisparityMap=showMaps\n )\ngroundTruth = zw.load_pgm_file(\"./tests/disparity_maps/ground_truth.pgm\", disparityMapBM.shape)\n\ngroundTruth = zw.crop_image(groundTruth, cropPercentage=0.75)\ndisparityMapBM = zw.crop_image(disparityMapBM, cropPercentage=0.75)\n\nssimBM = zw.calculate_ssim_disparity(disparityMapBM, groundTruth)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `plot_disparity_map_comparison()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef plot_disparity_map_comparison(\n disparityMapBM: np.ndarray,\n disparityMapSGBM: np.ndarray,\n disparityMapCustom: np.ndarray,\n groundTruth: np.ndarray,\n colorDiffMapBM: np.ndarray = None,\n colorDiffMapSGBM: np.ndarray = None,\n colorDiffMapCustom: np.ndarray = None,\n showComparison: bool = False,\n saveComparison: bool = False,\n savePath: str = None\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to plot the comparison of three disparity maps and the ground truth. Before plotting we have to calculate the disparity maps and the color difference maps.\n\nWe can save the comparison to a file using the `saveComparison` parameter (and `savePath`) directly in the function `plot_disparity_map_comparison()` (**recommended**).\n\nWe can also show the comparison using the `showComparison` parameter with or without saving.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\nimport os\n\ndisparityMapBM = zw.calculate_disparity_map(...)\ndisparityMapSGBM = zw.calculate_disparity_map(...)\ndisparityMapCustom = zw.calculate_disparity_map(...)\n\ngroundTruth = zw.load_pgm_file(\"./ground_truth.pgm\", disparityMapBM.shape)\n\ncolorDiffMapBM = zw.calculate_color_difference_map(disparityMapBM, groundTruth)\ncolorDiffMapSGBM = zw.calculate_color_difference_map(disparityMapSGBM, groundTruth)\ncolorDiffMapCustom = zw.calculate_color_difference_map(disparityMapCustom, groundTruth)\n\nzw.plot_disparity_map_comparison(\n disparityMapBM=disparityMapBM,\n disparityMapSGBM=disparityMapSGBM,\n disparityMapCustom=disparityMapCustom,\n groundTruth=groundTruth,\n colorDiffMapBM=colorDiffMapBM,\n colorDiffMapSGBM=colorDiffMapSGBM,\n colorDiffMapCustom=colorDiffMapCustom,\n showComparison=True\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `load_depth_map_calibration()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\nclass DepthCalibrationParams(TypedDict):\n cam0: list[list[float]]\n cam1: list[list[float]]\n doffs: float\n baseline: float\n dyavg: float\n dymax: float\n vmin: float\n vmax: float\n width: int\n height: int\n ndisp: int\n isint: int\n focalLength: float\n\n \ndef load_dept_map_calibration(calibFile: str) -> DepthCalibrationParams\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to load the calibration parameters from a TXT file. The function returns a dictionary with the calibration parameters as a `dict[str, Any]`.\n\nThis function will provide type hints for the returned dictionary.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ncalibrationParams = zw.load_depth_map_calibration(\"./calibration_params.txt\")\n\nprint(calibrationParams[\"cam0\"])\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `load_pfm_file()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef load_pfm_file(\n filePath: str = None\n) -> tuple[np.ndarray, float]\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to load a PFM file and return it as a numpy array and a float (the image and the scale factor). We have to specify the path to the file.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\nimage, scale = zw.load_pfm_file(\"./image.pfm\")\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `write_ply_file()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef write_ply_file(\n fileName: str,\n verts: np.ndarray,\n colors: np.ndarray\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to write a PLY file. We have to specify the name of the file, the vertices and the colors.\n\nTo get the vertices and colors from an image, we can use the `cv2.reprojectImageTo3D()` and `cv2.cvtColor()` functions. Then we can apply a mask to the vertices and colors to remove the points that are too far from the camera.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\nimport cv2\nimport numpy as np\n\nimg = cv2.imread(\"./image.png\", 0)\ndisparityMap = cv2.imread(\"./disparity_map.png\", 0)\ndepthMap = cv2.imread(\"./depth_map.png\", 0)\n\nh, w = img.shape[:2]\nf = 0.8 * w # focal length\nQ = np.float32([[1, 0, 0, -0.5 * w],\n [0, -1, 0, 0.5 * h], # turn points 180 deg around x-axis,\n [0, 0, 0, -f], # so that y-axis looks up\n [0, 0, 1, 0]])\n\npoints = cv2.reprojectImageTo3D(disparityMap, Q)\ncolors = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\nmask = depthMap < 50\n\noutPoints = points[mask]\noutColors = colors[mask]\n\nzw.write_ply_file(\n fileName=\"./image.ply\",\n verts=outPoints,\n colors=outColors,\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `decode_depth_map()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef decode_depth_map(\n depthMap: np.ndarray,\n maxDepth: float = 1000.0,\n decodeDepthMapRange: str = \"24-bit\"\n) -> np.ndarray\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package we can use the function to decode a depth map. We have to specify the depth map, the maximum depth and the range of the depth map to decode (e.g. **\"8-bit\"**, **\"16-bit\"**, **\"24-bit\"**. **ONLY USE THE 24-BIT RANGE - OTHER RANGES MAY BE INCORRECT**, check the docstring for more info).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\nimport cv2\n\ndepthMap_uint24 = cv2.imread(\"./depth_map.png\", cv2.IMREAD_UNCHANGED)\nmaxDepth = 1000.0 # meters\n\ndepthMap_decoded = zw.decode_depth_map(\n depthMap=depthMap_uint24,\n maxDepth=maxDepth,\n decodeDepthMapRange=\"24-bit\",\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `depth_map_normalize()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef depth_map_normalize(\n depthMap: np.ndarray,\n normalizeDepthMapRange: str = \"8-bit\"\n) -> np.ndarray\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package, we can use the function to normalize a depth map. The function requires the depth map and the desired range for normalization (e.g. **\"8-bit\"**, **\"16-bit\"**, **\"24-bit\"**. **ONLY USE THE 8-BIT AND 24-BIT RANGES - OTHER RANGES MAY BE INCORRECT**, check the docstring for more info).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ncalibrationParams = zw.load_depth_map_calibration(calibFile=\"./calibration_params.txt\")\n\ndisparityMap, scale = zw.load_pfm_file(filePath=\"./disparity_map.pfm\")\n\ndepthMap = zw.disparity_to_depth_map(\n disparityMap=disparityMap,\n baseline=calibrationParams[\"baseline\"],\n focalLength=calibrationParams[\"focalLength\"],\n aspect=1000.0\n)\n\ndepthMap_8bit = zw.depth_map_normalize(\n depthMap=depthMap,\n normalizeDepthMapRange=\"8-bit\"\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `depth_to_disparity_map()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef depth_to_disparity_map(\n depthMap: np.ndarray,\n baseline: float,\n focalLength: float,\n minDepth: float = 0.001,\n normalizeDisparityMapRange: str = \"8-bit\"\n) -> np.ndarray\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package, we can use the function to convert a depth map to a disparity map. We have to specify the depth map, the baseline and the focal length of the camera. The function returns the disparity map.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\nimport cv2\nimport numpy as np\n\nhFOV = 60\nbaseline = 0.1 # meters\nmaxDepth = 1000.0 # meters\ndepthMap_uint24 = cv2.imread(\"./depth_map.png\", cv2.IMREAD_UNCHANGED) # load the 24-bit depth map\nfocalLength = (depthMap_uint24[0] / 2) / np.tan(np.radians(hFOV / 2))\n\ndepthMap = zw.decode_depth_map(\n depthMap=depthMap_uint24,\n maxDepth=maxDepth,\n decodeDepthMapRange=\"24-bit\",\n)\n\ndisparityMap = zw.depth_to_disparity_map(\n depthMap=depthMap,\n baseline=baseline,\n focalLength=focalLength,\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `disparity_map_normalize()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef disparity_map_normalize(\n disparityMap: np.ndarray,\n normalizeDisparityMapRange: str = \"8-bit\"\n) -> np.ndarray\n```\n\n</li>\n<br/>\n<li> Example usage\n\nThis function is used only internally by the `depth_to_disparity_map()` function to normalize the disparity map after conversion, but it can also be used to normalize a disparity map on its own if we use the `calculate_disparity_map()` function with the `normalizeDisparityMap` parameter set to `False`.\n\nAfter importing the package, we can use the function to normalize the calculated disparity map to the desired range.\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ndisparityMapSGBM = zw.calculate_disparity_map(\n leftImagePath=\"./left.png\",\n rightImagePath=\"./right.png\",\n blockSize=9,\n numDisparities=256,\n minDisparity=0,\n disparityCalculationMethod=\"sgbm\",\n normalizeDisparityMap=False,\n)\n\ndisparityMap_8bit = zw.disparity_map_normalize(\n disparityMap=disparityMapSGBM,\n normalizeDisparityMapRange=\"8-bit\", # normalize the disparity map to 8-bit range (default)\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `disparity_to_depth_map()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef disparity_to_depth_map(\n disparityMap: np.ndarray,\n baseline: float,\n focalLength: float,\n aspect: float = 1000.0\n) -> np.ndarray\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package, we can use the function to convert a disparity map into a depth map. The function requires the disparity map, the baseline (distance between the two cameras), the focal length, and an optional aspect ratio for scaling (default is 1000, which returns the depth in meters).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ncalibrationParams = zw.load_depth_map_calibration(calibFile=\"./depth_calibration.txt\")\n\ndisparityMap, _ = zw.load_pfm_file(filePath=\"./disparity_map.pfm\")\n\ndepthMap = zw.disparity_to_depth_map(\n disparityMap=disparityMap,\n baseline=calibrationParams[\"baseline\"],\n focalLength=calibrationParams[\"focalLength\"],\n aspect=1000.0 # return depth in meters\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `display_img_plt()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef display_img_plt(\n img: np.ndarray,\n pltLabel: str = 'Map',\n show: bool = False,\n save: bool = False,\n savePath: str = None,\n cmap: str = 'gray'\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package, we can use the function to display an image using Matplotlib. The function requires the image and an optional plot label.\n\nIf the `show` parameter is set to `True`, the image will be displayed in a new window.\n\nIt can also save the image to a file if a `savePath` is provided and the `save` parameter is set to `True`.\n\nYou can also specify a custom color map using the `cmap` parameter (default is `'gray'`).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\n\ndisparityMap, _ = zw.load_pfm_file(filePath=\"./disparity_map.pfm\")\n\nzw.display_img_plt(\n img=disparityMap,\n pltLabel=\"Disparity map (Ground Truth PFM)\",\n show=True,\n save=True,\n savePath=\"./disparity_map.png\",\n cmap=None\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n<br/>\n<br/>\n\n### `compare_images()`\n\n[Back to the top (TOC)](#table-of-contents)\n\n<ol>\n<li> Function definition\n\n<br/>\n<br/>\n\n```python\ndef compare_images(\n images: list[np.ndarray],\n cmaps: list[str] = None,\n pltLabel: str = 'Comparison',\n titles: list[str] = None,\n nrows: int = None,\n ncols: int = None,\n show: bool = False,\n save: bool = False,\n savePath: str = None\n) -> None\n```\n\n</li>\n<br/>\n<li> Example usage\n\nAfter importing the package, we can use the function to compare multiple images. The function accepts a list of images, their corresponding colormaps, and titles. You can also specify the number of rows and columns for the layout. Optionally, the resulting comparison can be saved to a file.\n\nThe function displays the images using Matplotlib and plots them in a grid layout. If `nrows` and `ncols` are not provided, the grid layout will be determined automatically based on the number of images (1 row and `n` columns, where `n` is the number of images).\n\n<br/>\n<br/>\n\n```python\nimport zaowr_polsl_kisiel as zw\nimport cv2\n\n# Load multiple images (e.g., disparity maps or depth maps)\ndisparityMap1, _ = cv2.imread(\"./disparity_map1.png\", cv2.IMREAD_GRAYSCALE)\ndisparityMap2, _ = cv2.imread(\"./disparity_map2.png\", cv2.IMREAD_GRAYSCALE)\ndisparityMap3, _ = cv2.imread(\"./disparity_map3.png\", cv2.IMREAD_GRAYSCALE)\ndisparityMap4, _ = cv2.imread(\"./disparity_map4.png\", cv2.IMREAD_GRAYSCALE)\n\n# Prepare the images and their corresponding colormaps\nimages = [disparityMap1, disparityMap2, disparityMap3, disparityMap4]\ncmaps = ['gray', 'hot', 'viridis', 'plasma'] # Different colormaps for each image\ntitles = ['Disparity Map 1', 'Disparity Map 2', 'Disparity Map 3', 'Disparity Map 4']\n\n# Display and compare the images using a grid layout\nzw.compare_images(\n images=images,\n cmaps=cmaps,\n pltLabel='Comparison of Disparity and Depth Maps',\n titles=titles,\n nrows=2, # 2 rows in the grid\n ncols=2, # 2 columns in the grid\n show=True, # Display the plot\n save=True, # Save the plot to a file\n savePath='./output/comparison_plot.png' # File path for saving\n)\n```\n\n<br/>\n</li>\n<li> Other params are optional and have default values. Each of them can be found in the function definition, and their descriptions are provided in the docstrings (hover over the function name).\n\n</li>\n</ol>\n",
"bugtrack_url": null,
"license": "Copyright (c) 2018 The Python Packaging Authority Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"summary": "A simple Python package used by me and my friends at university in the 'Advanced Image, Video and Motion Analysis' course.",
"version": "0.0.31",
"project_urls": {
"Changelog": "https://github.com/revalew/zaowr-py-package/releases",
"Documentation": "https://github.com/revalew/zaowr-py-package/blob/master/docs/USAGE.md",
"Issues": "https://github.com/revalew/zaowr-py-package/issues",
"Repository": "https://github.com/revalew/zaowr-py-package"
},
"split_keywords": [
"polsl",
" zaowr",
" 2024/2025",
" igt",
" zaowr"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d4e2ec8ebbfcfba31c31a9ebeeed30a5d63b68e48a62327fb1918f2705146a85",
"md5": "e11130d75fdbdc04d68f5ca3a50f4635",
"sha256": "fa0a0766ee059cff58c82bebf1896ef51b648e523386bd56a61979b27560de2e"
},
"downloads": -1,
"filename": "zaowr_polsl_kisiel-0.0.31-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e11130d75fdbdc04d68f5ca3a50f4635",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 66570,
"upload_time": "2025-01-08T16:31:34",
"upload_time_iso_8601": "2025-01-08T16:31:34.414379Z",
"url": "https://files.pythonhosted.org/packages/d4/e2/ec8ebbfcfba31c31a9ebeeed30a5d63b68e48a62327fb1918f2705146a85/zaowr_polsl_kisiel-0.0.31-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "0b2db01b46fb8551cbaa223407185d0b2dfd1110a34d423f47472fa3c93011da",
"md5": "bef0cd9b2e10bcd968789e63212df782",
"sha256": "b10aa4725068a3ea5924911ce2221ab5efd1fae05eb753a304ddd24721371323"
},
"downloads": -1,
"filename": "zaowr_polsl_kisiel-0.0.31.tar.gz",
"has_sig": false,
"md5_digest": "bef0cd9b2e10bcd968789e63212df782",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 71477,
"upload_time": "2025-01-08T16:31:37",
"upload_time_iso_8601": "2025-01-08T16:31:37.506216Z",
"url": "https://files.pythonhosted.org/packages/0b/2d/b01b46fb8551cbaa223407185d0b2dfd1110a34d423f47472fa3c93011da/zaowr_polsl_kisiel-0.0.31.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-08 16:31:37",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "revalew",
"github_project": "zaowr-py-package",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "opencv-python",
"specs": [
[
"==",
"4.10.0.84"
]
]
},
{
"name": "numpy",
"specs": [
[
"==",
"2.1.3"
]
]
},
{
"name": "tqdm",
"specs": [
[
"==",
"4.67.1"
]
]
},
{
"name": "colorama",
"specs": [
[
"==",
"0.4.6"
]
]
},
{
"name": "matplotlib",
"specs": [
[
"==",
"3.10.0"
]
]
},
{
"name": "scikit-image",
"specs": [
[
"==",
"0.25.0"
]
]
}
],
"lcname": "zaowr-polsl-kisiel"
}