Image: How can I implement a trait for `image::dynimage::DynamicImage`

Created on 22 Apr 2020  路  11Comments  路  Source: image-rs/image

I'm trying to use inline-python to get a pic from OpenCV camera, then manipulate this image with Rust, so I wrote the below code that catch the photo correctly, but once I try to handle it in Rust using image I get the below error:

error[E0277]: the trait bound `image::dynimage::DynamicImage: pyo3::pyclass::PyClass` is not satisfied
  --> src\main.rs:45:43
   |
45 |                 let img: DynamicImage = c.get("frame");
   |                                           ^^^ the trait `pyo3::pyclass::PyClass` is not implemented for `image::dynimage::DynamicImage`
   |
   = note: required because of the requirements on the impl of `for<'p> pyo3::conversion::FromPyObject<'p>` for `image::dynimage::DynamicImage`


The full code is:

#![feature(proc_macro_hygiene)]
use inline_python::*;

use image::{ImageFormat, GenericImageView, DynamicImage};
use web_view::*;

fn main() {
    let c = Context::new();

    web_view::builder()
    .title("Call open CV")
    .content(Content::Html(HTML))
    .size(800, 600)
    .user_data(())
    .invoke_handler(|_, arg| {
        match arg {
            "open" => {
                c.run(python!  {
                            import cv2
                            x = 2
                            cap = cv2.VideoCapture(0)
                            ret, frame = cap.read()
                            cv2.imshow('frame', frame)
                            cv2.waitKey(0)
                    })
            },
            "close" => {

                let img: DynamicImage = c.get("frame");

            },
            _ => (),
        }
        Ok(())
    }).run()
    .unwrap();
}

const HTML: &str  = r#"
<!doctype html>
<html>
    <body>
        <button onclick="external.invoke('open')">Run</button>
        <button onclick="external.invoke('close')">Close</button><br>
        <br>

    </body>
</html>
"#;

Can you help, Thanks.

question

All 11 comments

The type imgref::Img is part of imgref, not image. And you can not implement a trait for a foreign type. You either need to ask the maintainer to implement that trait or define a small wrapper type and manually implement it for that wrapper.

Wrong button, sorry :smile: Let me know if you need a clarification for defining a wrapper type.

Actually I was trying both packages, yours and imgref, I fixed my question now, can you help :)
Either implement that trait or guide me how to define a small wrapper type and manually implement it for that wrapper.

Sure. A wrapper type is a simple struct with a single member, the type you are wrapping (hence the name). This allows _your_ crate complete control over the trait impls which would not be otherwise possible for a foreign type. In this case, it allows you to annotate it with the proc-macro to automatically derive the desired trait impl (pyo3::pyclass::PyClass).

use pyo3::prelude::*;

#[pyclass]
pub struct YourImage {
    inner: DynamicImage,
}

// Later:
"close" => {
    let img: YourImage = c.get("frame");
    // If you need to access any of image's functions:
    let rgba = img.inner.to_rgba();
},

Hope this helps, I'm not an expert on PyO3 nor on the OpenCV bindings.

Thanks, the code run, but panicked at the output:

thread 'main' panicked at 'Unable to convert `frame` to `rust_webview::YourImage`',

Your code example doesn't clarify what you use as Context but where you _set_ that you'll need to pass the wrapper instead of DynamicImage. Such as c.set(YourImage { inner: img }).

Now I'm getting:

 c.set("frame", YourImage { inner: img });
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `pyo3::conversion::ToPyObject` is not implemented for `YourImage`

How you actually implement the traits of pyo3, you'll have to look up in that library. For example the documentation of that trait named by rustc here. I can only do guesswork here, and it's not very productive for either party.

Have you been able to make it work? Can this issue be closed?

Hi thanks, sorry for not feedbacking you, yes I found a simpler way to handle it, as the generated output I got is a 3D array, so I handles it as numbers as shown in #1210

Was this page helpful?
0 / 5 - 0 ratings