Whenever I was programming in Rust with OpenCV and using the inrange() function to mask out red for seeing red LEDs in the purview, I was struggling with what exact format to use for the arguments for the upper bound and lowerbound of color. I was using images taken from a simple WebCam attached to a Raspberry Pi. No one was really helping on the internet and it took a lot of fiddling, but I figured it out, and I hope this benefits you.
The idea behind finding colors in an image is to take the image and form a mask of pixels that are that certain color. This is done with inrange(). Then a bitwise and used to cut out the the parts of the image that relate to that color. The format of the upper bound and lower bound have been a mystery on the internet for the Rust OpenCV port. It is actually a Scalar that is used, and I believe the Scalar type is from the OpenCV implementation itself. What goes into this Scalar value might you ask? Well, it is float values. And, as you may have guessed, it is formatted as Blue, Green, Red with the Webcam image.
It took a little time to figure out the right values for the colors to filter out the correct values for the Blue, Green, and Red, but I imagine you can use a color mapper online.
Happy coding!!
async fn get_image(
payload: ToJson
) -> Result<impl warp::Reply, warp::Rejection> {
let mut cam = videoio::VideoCapture::new(0, videoio::CAP_ANY).unwrap();
let mut frame = Mat::default();
let mut result = HashMap::new();
let r = payload.message.read();
for (key,value) in r.iter() {
result.insert(key, value);
}
cam.read(&mut frame).unwrap();
let image_string = "image".to_string();
//let hsv_encoded_image = &mut Vector::<u8>::new();
//cvt_color(&frame,hsv_encoded_image,opencv::imgproc::COLOR_BGR2HLS, 0).unwrap();
let mask = &mut Mat::default();
let params = &mut Vector::<i32>::new();
let encoded_image = &mut Vector::<u8>::new();
let red_image = &mut Mat::default();
let lower_bound = Scalar::from((0 as f64, 0 as f64, 100 as f64));
let upper_bound = Scalar::from((100 as f64, 100 as f64, 255 as f64));
in_range(&frame, &lower_bound, &upper_bound, mask).unwrap();
bitwise_and(&frame, &frame, red_image, mask).unwrap();
let flag = opencv::imgcodecs::imencode(".bmp", red_image , encoded_image, params).unwrap();
let s = base64::encode(encoded_image);
match flag {
true => { result.insert(&image_string, &s);
},
false => { println!("cannot be encoded");
},
};
Ok(warp::reply::json(
&result
))
}