PyO3 / rust-numpy

PyO3-based Rust bindings of the NumPy C-API
BSD 2-Clause "Simplified" License
1.11k stars 106 forks source link

Example for image I/O ? #406

Closed melMass closed 8 months ago

melMass commented 8 months ago

Hi,

I'm familiar with pyo3 but I'm hitting a road block when trying to do I/O between rust images (image crate buffers or anything) and numpy arrays.

Any help is appreciated.

Thanks

adamreichold commented 8 months ago

I suspect the main insight here is that you need to target ndarray as an intermediate format between image buffers and NumPy arrays. There are crates dedicated to that interface, c.f. nshare or ndarray-ndimage.

If that helps maybe you could contribute an example using one of these crates here?

melMass commented 8 months ago

Thanks nshare definitely seems like it has the answers I was looking for, I will try tomorrow and report here. And I'm definitely up to PR a sample for that, I've wondered before.

melMass commented 8 months ago

It's working! I've use nshare

Probably not the most efficient but this work:

use nshare::ToNdarray3;

 fn render(&self, py: Python<'_>) -> PyResult<Vec<Py<PyArray3<u8>>>> {
        // ...

        // .. Frame is an enum wrapping image::ImageBuffers by bitdepth
        let frames: Vec<&Frame> = renderer.frames.iter().collect();

        let frames: Vec<Py<PyArray3<u8>>> = renderer
            .frames
            .iter()
            .map(|f| match f {
                Frame::U8(frame) => frame.clone().into_ndarray3().to_pyarray(py).to_owned(),
                _ => panic!("not u8"),
            })
            .collect();

        Ok(frames)
    }

And in python

from PIL import Image
import engine

arr = engine.render()

first = np.transpose(arr[0], (1,2,0))

image = Image.fromarray(first)