twistedfall / opencv-rust

Rust bindings for OpenCV 3 & 4
MIT License
1.86k stars 144 forks source link

Need help: How to build a CV::Mat from Vec<u8> of BGR24? #585

Closed tubzby closed 2 weeks ago

tubzby commented 2 weeks ago

I want to create a cv::Mat from a Vec<u8> which is in BGR24 format, I tried the following:


let mat= Mat::new_rows_cols_with_data(
    1920,
    1080,
    &rgb_data,
)?;

But it failed with error: The length of the slice: 6220800 must match the passed row: 1920 and column: 1080 counts exactly (code: StsUnmatchedSizes, -209).

It seems that new_rows_cols_with_data only supports Vec<u32>, is that the case? do I need to make a Vec<u32> manually?

twistedfall commented 2 weeks ago

One of the ways to do that without copying the data is with a bit of unsafe:

let mat = unsafe { Mat::new_rows_cols_with_data_unsafe_def(1920, 1080, Vec3b::opencv_type(), rgb_data.as_mut_ptr().cast()) }?;

And you must make sure that you drop mat before rgb_data so that it doesn't reference the freed data.

But your use case is completely valid, I will add ability to build such Mats without copying the data from byte arrays in the next release, thanks for the report!

tubzby commented 2 weeks ago

Thank you! Another question: Is there a way to update an existing Mat with Vec<u8>

twistedfall commented 2 weeks ago

You can do something like this:

mat.data_bytes_mut()?.copy_from_slice(&bytes);
tubzby commented 2 weeks ago

Very helpful!