Skip to content

Commit

Permalink
add compute_histogram python bindings (#64)
Browse files Browse the repository at this point in the history
* rename kornia-py

* include python bindings
  • Loading branch information
edgarriba authored Mar 26, 2024
1 parent e68d542 commit 8c3a8ae
Show file tree
Hide file tree
Showing 26 changed files with 104 additions and 14 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/python_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
target: ${{ matrix.target }}
manylinux: auto
command: build
args: --release --out dist -i python${{ matrix.python-version }} -m py-kornia/Cargo.toml --sdist
args: --release --out dist -i python${{ matrix.python-version }} -m kornia-py/Cargo.toml --sdist
- name: Upload wheels
uses: actions/upload-artifact@v2
with:
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:
with:
command: build
maturin-version: latest
args: --release --target ${{ matrix.target }}-apple-darwin --out dist -i python${{ matrix.python-version }} -m py-kornia/Cargo.toml --sdist
args: --release --target ${{ matrix.target }}-apple-darwin --out dist -i python${{ matrix.python-version }} -m kornia-py/Cargo.toml --sdist
- name: Upload wheels
uses: actions/upload-artifact@v2
with:
Expand Down Expand Up @@ -82,7 +82,7 @@ jobs:
with:
command: build
maturin-version: latest
args: --release --out dist -i python${{ matrix.python-version }} -m py-kornia/Cargo.toml --sdist
args: --release --out dist -i python${{ matrix.python-version }} -m kornia-py/Cargo.toml --sdist
- name: Upload wheels
uses: actions/upload-artifact@v2
with:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/python_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ on:
pull_request:
paths:
- Cargo.lock
- py-kornia/**
- kornia-py/**
- .github/workflows/test-python.yml
push:
branches:
- main
paths:
- Cargo.lock
- py-kornia/**
- kornia-py/**
- .github/workflows/test-python.yml

concurrency:
Expand Down Expand Up @@ -51,11 +51,11 @@ jobs:
with:
command: build
maturin-version: latest
args: --target x86_64-apple-darwin --out dist -m py-kornia/Cargo.toml
args: --target x86_64-apple-darwin --out dist -m kornia-py/Cargo.toml
- name: Install dependencies
run: |
python -m pip install --upgrade pip |
python -m pip install dist/*.whl |
python -m pip install pytest torch numpy
- name: Build and test
run: pytest py-kornia/tests
run: pytest kornia-py/tests
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ endif
.PHONY: requirements
requirements: .venv ## Install/refresh Python project requirements
$(VENV_BIN)/python -m pip install --upgrade pip
$(VENV_BIN)/python -m pip install -r py-kornia/requirements-dev.txt
$(VENV_BIN)/python -m pip install -r kornia-py/requirements-dev.txt

.PHONY: build-python
build-python: .venv ## Compile and install Python for development
@unset CONDA_PREFIX && source $(VENV_BIN)/activate \
&& maturin develop -m py-kornia/Cargo.toml \
&& maturin develop -m kornia-py/Cargo.toml \

.PHONY: build-python-release
build-python-release: .venv ## Compile and install a faster Python binary with full optimizations
@unset CONDA_PREFIX && source $(VENV_BIN)/activate \
&& maturin develop -m py-kornia/Cargo.toml --release \
&& maturin develop -m kornia-py/Cargo.toml --release \

.PHONY: test-python
test-python: .venv ## Run Python tests
@unset CONDA_PREFIX && source $(VENV_BIN)/activate \
&& maturin develop -m py-kornia/Cargo.toml \
&& $(VENV_BIN)/pytest py-kornia/tests
&& maturin develop -m kornia-py/Cargo.toml \
&& $(VENV_BIN)/pytest kornia-py/tests

.PHONY: clippy
clippy: ## Run clippy with all features
Expand All @@ -53,7 +53,7 @@ clean: ## Clean up caches and build artifacts
@rm -rf target/
@rm -f Cargo.lock
@cargo clean
@$(MAKE) -s -C py-kornia/ $@
@$(MAKE) -s -C kornia-py/ $@

.PHONY: help
help: ## Display this help screen
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
42 changes: 42 additions & 0 deletions kornia-py/benchmark/bench_histogram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import timeit

import cv2
import kornia_rs as K
import numpy as np

image_path = "tests/data/dog.jpeg"
N = 5000 # number of iterations

img = K.read_image_jpeg(image_path)[..., :1]


# 0.04 ms :)
def hist_opencv(image: np.ndarray) -> np.ndarray:
return cv2.calcHist([image], [0], None, [256], [0, 256])


# 0.17 ms :(
def hist_kornia(image: np.ndarray) -> np.ndarray:
return K.compute_histogram(image, num_bins=256)


tests = [
{
"name": "OpenCV",
"stmt": "hist_opencv(image)",
"setup": "from __main__ import hist_opencv",
"globals": {"image": img},
},
{
"name": "Kornia",
"stmt": "hist_kornia(image)",
"setup": "from __main__ import hist_kornia",
"globals": {"image": img},
},
]

for test in tests:
timer = timeit.Timer(
stmt=test["stmt"], setup=test["setup"], globals=test["globals"]
)
print(f"{test['name']}: {timer.timeit(N)/ N * 1e3:.2f} ms")
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions kornia-py/src/histogram.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use pyo3::prelude::*;

use crate::image::{FromPyImage, PyImage};
use kornia_rs::image::Image;

/// Compute the pixel-wise histogram of an image.
/// --
///
/// This function computes the histogram of an image with a given number of bins.
///
/// # Arguments
///
/// * `image` - The input image to compute the histogram with shape (H, W, 1) and dtype uint8.
/// * `num_bins` - The number of bins to use for the histogram.
///
/// # Returns
///
/// A vector of size `num_bins` containing the histogram.
#[pyfunction]
pub fn compute_histogram(image: PyImage, num_bins: usize) -> PyResult<Vec<usize>> {
let image = Image::from_pyimage(image)
.map_err(|e| PyErr::new::<pyo3::exceptions::PyException, _>(format!("{}", e)))?;

let histogram = kornia_rs::histogram::compute_histogram(&image, num_bins)
.map_err(|e| PyErr::new::<pyo3::exceptions::PyException, _>(format!("{}", e)))?;

Ok(histogram)
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 2 additions & 0 deletions py-kornia/src/lib.rs → kornia-py/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod histogram;
mod image;
mod io;
mod resize;
Expand All @@ -24,6 +25,7 @@ pub fn kornia_rs(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(write_image_jpeg, m)?)?;
m.add_function(wrap_pyfunction!(read_image_any, m)?)?;
m.add_function(wrap_pyfunction!(resize::resize, m)?)?;
m.add_function(wrap_pyfunction!(histogram::compute_histogram, m)?)?;
m.add_class::<PyImageSize>()?;
m.add_class::<PyImageDecoder>()?;
m.add_class::<PyImageEncoder>()?;
Expand Down
File renamed without changes.
18 changes: 18 additions & 0 deletions kornia-py/tests/test_histogram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from __future__ import annotations
import kornia_rs as K

import numpy as np


def test_histogram():
# load an image with libjpeg-turbo
img = np.array([0, 2, 4, 128, 130, 132, 254, 255, 255], dtype=np.uint8).reshape(
3, 3, 1
)

img_histogram: list[int] = K.compute_histogram(img, num_bins=3)

assert len(img_histogram) == 3
assert img_histogram[0] == 3
assert img_histogram[1] == 3
assert img_histogram[2] == 3
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/histogram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::Result;

use crate::image::Image;

/// Compute the histogram of an image.
/// Compute the pixel intensity histogram of an image.
///
/// NOTE: this is limited to 8-bit 1-channel images.
///
Expand Down

0 comments on commit 8c3a8ae

Please # to comment.