Metadata-Version: 2.4
Name: feret
Version: 1.4.3
Summary: Calculate the maximum and minimum Feret diameter of a binary image.
Author-email: matthiasnwt <62239991+matthiasnwt@users.noreply.github.com>
License: MIT License
        
        Copyright (c) 2022 Matthias Nwt
        
        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.
Project-URL: Homepage, https://github.com/matthiasnwt/feret
Project-URL: Repository, https://github.com/matthiasnwt/feret
Project-URL: Changelog, https://github.com/matthiasnwt/feret/blob/main/CHANGELOG.md
Keywords: feret,feretdiameter,maxferet,diameter,maximum,caliper,caliper diameter,python,minferet,minimum,feret diameter
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: Unix
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Topic :: Scientific/Engineering :: Image Processing
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Topic :: Utilities
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.22
Requires-Dist: scipy>=1.8
Requires-Dist: matplotlib>=3.5
Requires-Dist: opencv-python>=4.5
Provides-Extra: plot
Requires-Dist: matplotlib>=3.5; extra == "plot"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Requires-Dist: mypy>=1.8; extra == "dev"
Requires-Dist: pre-commit>=3; extra == "dev"
Requires-Dist: tifffile; extra == "dev"
Requires-Dist: build; extra == "dev"
Dynamic: license-file

# *Feret*: A Python Module to calculate the Feret Diameter of Binary Images

[![PyPI](https://img.shields.io/pypi/v/feret.svg)](https://pypi.org/project/feret/)
[![Downloads](https://static.pepy.tech/badge/feret)](https://pepy.tech/project/feret)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21727752.svg)](https://doi.org/10.5281/zenodo.21727752)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## 📖 How to cite

If you use this software in academic work, **please cite it**. GitHub renders a
"Cite this repository" button in the sidebar that reads the
[CITATION.cff](https://github.com/matthiasnwt/feret/blob/main/CITATION.cff)
file and produces BibTeX / APA on demand.

> Neuwirth-Trapp, M. (2026). *Feret: A Python Module to calculate the Feret
> Diameter of Binary Images* [Computer software]. Zenodo.
> https://doi.org/10.5281/zenodo.21727752

BibTeX:

```bibtex
@software{neuwirth_trapp_feret,
  author    = {Neuwirth-Trapp, Matthias},
  title     = {Feret: A Python Module to calculate the Feret Diameter of Binary Images},
  year      = {2026},
  publisher = {Zenodo},
  doi       = {10.5281/zenodo.21727752},
  url       = {https://doi.org/10.5281/zenodo.21727752}
}
```

---

<img src="https://raw.githubusercontent.com/matthiasnwt/feret/main/README.assets/plot_method.png" width="400" />

This python module can calculate the following parameters for binary images:

* maximum Feret diameter (maxferet, maxf)
* minimum Feret diameter (minferet, minf)
* Feret diameter 90 ° to the minferet (minferet90, minf90) 
* Feret diameter 90 ° to maxferet (maxferet90, maxf90) 

See this [Wikipedia page](https://en.wikipedia.org/wiki/Feret_diameter) to get the definition of those parameters.

This module reproduces ImageJ's results exactly (use `edge=True` as shown below), all the parameters are exactly calculated and **not** approximated.

## Installation

```
pip install feret
```

Requires Python 3.8 or newer. The following runtime dependencies are pulled
in automatically: `numpy`, `scipy`, `opencv-python`, `matplotlib`. The package
works on both NumPy 1.x and NumPy 2.x.

### Development install

```
git clone https://github.com/matthiasnwt/feret
cd feret
python -m venv .venv
.venv\Scripts\activate            # Windows PowerShell / cmd
# or: source .venv/bin/activate    # Linux / macOS
pip install -e ".[dev]"
pytest
pre-commit install
```

`pip install -e ".[dev]"` adds `pytest`, `ruff`, `mypy`, `pre-commit`,
`tifffile` and `build`. Run the full test matrix with `pytest`, lint with
`ruff check src tests` and `ruff format --check src tests`, and type-check
with `mypy`.

## Pieces of Information

#### Convex Hull

The definition of the maxferet and minferet uses the image of a caliper. Therefore, only the points which correspond to the convex hull of the object play a role. That is why before any calculations the convex hull is determined to reduce the runtime.

#### Maxferet
The maxferet is calculated as the maximum Euclidean distance of all pixels.

#### Minferet

The minferet is exactly calculated and **not** approximated. My algorithm uses the fact, that the calipers that define the minferet run on one side through two points and on the other through one point. The script iterates over all edge points and defines a line through the point and the one next to it. Then all the distances to the other points are calculated and the maximum is taken. The minimum of all those maximums is the minferet. The maximum of all those maximums is **not** the maxferet, that is the reason it is calculated separately. The runtime of this is already pretty good but hopefully I can improve it in the future.

## Use
The module can be used as followed:

First you need a binary image for which the feret diameter should be calculated. The background has to have the value zero, the object can have any nonzero  value. The object doesn't have to be convex. At the moment the module only supports one object per image. This means, that if there are multiple not connected regions, the script will calculate a convexhull which include all regions and for this hull the feret diameter is calculated.

The calls are:

```python
import feret

# tifffile is not required nor included in this module.
import tifffile as tif
img = tif.imread('example.tif') # Image has to be a numpy 2d-array.


# get the values
maxf, minf, minf90, maxf90 = feret.all(img)

# get only maxferet
maxf = feret.max(img)

# get only minferet
minf = feret.min(img)

# get only minferet90
minf90 = feret.min90(img)

# get only maxferet90
maxf90 = feret.max90(img)

# get all the informations
res = feret.calc(img)
maxf = res.maxf
minf =  res.minf
minf90 = res.minf90
minf_angle = res.minf_angle
minf90_angle = res.minf90_angle
maxf_angle = res.maxf_angle
maxf90_angle = res.maxf90_angle
```

There is an option to calculate the Feret diameters for the pixel edges instead of the centers. Just add an `edge=True` in the call as shown below. This works for all calls analogous.

```python
import feret

# tifffile is not required nor included in this module.
import tifffile as tif
img = tif.imread('example.tif') # Image has to be a numpy 2d-array.

# get only maxferet
maxf = feret.max(img, edge=True)
```

This module can also plot the result. Just use

```python
import feret

# tifffile is not required nor included in this module.
import tifffile as tif
img = tif.imread('example.tif') # Image has to be a numpy 2d-array.

# plot the result
feret.plot(img) #edge=True can be passed here too
```

<img src="https://raw.githubusercontent.com/matthiasnwt/feret/main/README.assets/plot_method.png" width="400" />

The reason for the two MinFeret points on the left is described above. The MinFeret line does not have to run in between its two base points or through one of them. MaxFeret and MinFeret do not have to be 90° to each other. To calculate the 90° to MaxFeret and MinFeret use `feret.max90(img)` and `feret.min90(img)` methods.
