Title could be worded better, but essentially I am trying to use open cv in Rust and I found the opencv crate
I am using Rust 1.76.0 and opencv crate version 0.88.8
I am running things on Ubuntu 22.04
Per the installation instructions from github I downloaded these
apt install libopencv-dev clang libclang-dev
Per the example from the github page I then tried this to display camera feed
use opencv::{highgui, prelude::*, videoio, Result};
fn main() -> Result<()> {
let window = "video capture";
highgui::named_window(window, highgui::WINDOW_AUTOSIZE)?;
let mut cam = videoio::VideoCapture::new(0, videoio::CAP_ANY)?; // 0 is the default camera
let opened = videoio::VideoCapture::is_opened(&cam)?;
if !opened {
panic!("Unable to open default camera!");
}
loop {
let mut frame = Mat::default();
cam.read(&mut frame)?;
if frame.size()?.width > 0 {
highgui::imshow(window, &frame)?;
}
let key = highgui::wait_key(10)?;
if key > 0 && key != 255 {
break;
}
}
Ok(())
}
It works, but it is extremely slow, feels very laggy
I am using a webcam as the camera device, it should have around 22-24 FPS but in Rust it's most like 8 FPS
let fps_start = Instant::now();
let num_frames_to_measure = 60;
for _ in 0..num_frames_to_measure {
let mut temp_frame = Mat::default();
cam.read(&mut temp_frame)?;
}
let fps_duration = fps_start.elapsed();
let fps = num_frames_to_measure as f64 / fps
println!("Measured FPS: {:?}", fps);
This is the comparison Python code
import cv2
vid = cv2.VideoCapture(0)
while True:
ret, frame = vid.read()
cv2.imshow('window', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
vid.release()
cv2.destroyAllWindows()
Python version has no lag what so ever
Is the camera feed being slow just something I overlooked or is it just simply the way things currently are?
My scenario is that I need to take pictures, convert them into HSV and do some processing
By doing this in Rust I was hoping to speed up both the picture taking and processing part
EDIT:
To answer my own question setting a WIDTH and HEIGHT on the camera fixes the FPS issues.
use opencv::core::Vector;
use opencv::{
highgui,
prelude::*,
videoio,
imgcodecs
};
use std::time::Instant;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. Setup
let setup_start = Instant::now();
let mut cam = videoio::VideoCapture::new(0, videoio::CAP_ANY)?; // 0 is the default camera
let opened = videoio::VideoCapture::is_opened(&cam)?;
if !opened {
println!("Unable to open default camera!");
return Ok(());
}
cam.set(videoio::CAP_PROP_FRAME_WIDTH, 640.0)?; // Set frame width
cam.set(videoio::CAP_PROP_FRAME_HEIGHT, 480.0)?; // Set frame height
let setup_duration = setup_start.elapsed().as_secs_f64(); // Calculate setup duration
println!("Setup duration: {:?}", setup_duration); // Print setup duration
// 2. Measure FPS
let fps_start = Instant::now();
let num_frames_to_measure = 60;
for _ in 0..num_frames_to_measure {
let mut temp_frame = Mat::default();
cam.read(&mut temp_frame)?;
}
let fps_duration = fps_start.elapsed();
let fps = num_frames_to_measure as f64 / fps_duration.as_secs_f64();
println!("Measured FPS: {:?}", fps);
// 3. Display the video feed
loop {
let mut frame = Mat::default();
cam.read(&mut frame)?;
if frame.size()?.width > 0 {
highgui::imshow("camera", &frame)?;
let key = highgui::wait_key(1)?;
if key == 13 { // If you press 'q' program exits
break;
}
}
}
// 5. Function end
Ok(())
}