meteor_detect/demos/camera_demo.rs

154 lines
4.9 KiB
Rust

use std::io;
use std::path::PathBuf;
use std::str::FromStr;
use chrono::{Utc, Local, DateTime, TimeZone, FixedOffset};
use chrono::format::Fixed::TimezoneOffset;
use opencv::{core, imgcodecs, imgproc, highgui, prelude::*};
// Simplified camera module for demo
mod camera {
use opencv::{core, prelude::*, videoio};
use chrono::{DateTime, Utc};
pub struct Frame {
pub image: core::Mat,
pub timestamp: DateTime<Utc>,
pub index: u64,
}
impl Frame {
pub fn new(image: core::Mat, timestamp: DateTime<Utc>, index: u64) -> Self {
Self { image, timestamp, index }
}
}
pub struct CameraDemo {
capture: videoio::VideoCapture,
frame_count: u64,
}
impl CameraDemo {
pub fn new(device_id: i32) -> Result<Self, Box<dyn std::error::Error>> {
let capture = videoio::VideoCapture::new(device_id, videoio::CAP_ANY)?;
if !capture.is_opened()? {
return Err(format!("Failed to open camera device {}", device_id).into());
}
Ok(Self {
capture,
frame_count: 0,
})
}
pub fn from_file(path: &str) -> Result<Self, Box<dyn std::error::Error>> {
let capture = videoio::VideoCapture::from_file(path, videoio::CAP_ANY)?;
if !capture.is_opened()? {
return Err(format!("Failed to open video file {}", path).into());
}
Ok(Self {
capture,
frame_count: 0,
})
}
pub fn capture_frame(&mut self) -> Result<Frame, Box<dyn std::error::Error>> {
let mut frame = core::Mat::default();
if self.capture.read(&mut frame)? {
if frame.empty() {
return Err("Captured frame is empty".into());
}
let timestamp = Utc::now();
let index = self.frame_count;
self.frame_count += 1;
Ok(Frame::new(frame, timestamp, index))
} else {
Err("Failed to capture frame".into())
}
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("*** Camera Module Demo ***");
println!("This demo captures frames from a camera device or video file and displays them");
println!("Press 'q' to quit");
println!();
println!("Choose input source:");
println!("1. Camera device");
println!("2. Video file");
let mut choice = String::new();
io::stdin().read_line(&mut choice)?;
let mut camera_demo = match choice.trim() {
"1" => {
println!("Enter camera device ID (default is 0):");
let mut device_id = String::new();
io::stdin().read_line(&mut device_id)?;
let device_id = device_id.trim().parse::<i32>().unwrap_or(0);
println!("Opening camera device {}", device_id);
camera::CameraDemo::new(device_id)?
},
"2" => {
println!("Enter video file path:");
let mut file_path = String::new();
io::stdin().read_line(&mut file_path)?;
let file_path = file_path.trim();
println!("Opening video file: {}", file_path);
camera::CameraDemo::from_file(file_path)?
},
_ => {
println!("Invalid choice, using default camera (device 0)");
camera::CameraDemo::new(0)?
}
};
highgui::named_window("Camera Module Demo", highgui::WINDOW_NORMAL)?;
loop {
match camera_demo.capture_frame() {
Ok(frame) => {
// Add timestamp to the frame
let mut display_frame = frame.image.clone();
// Convert UTC timestamp to local time
let local_timestamp = frame.timestamp.with_timezone(&Local);
let timestamp_text = local_timestamp.format("%Y-%m-%d %H:%M:%S%.3f").to_string();
imgproc::put_text(
&mut display_frame,
&timestamp_text,
core::Point::new(10, 30),
imgproc::FONT_HERSHEY_SIMPLEX,
1.0,
core::Scalar::new(0.0, 255.0, 0.0, 0.0),
2,
imgproc::LINE_AA,
false,
)?;
// Display the frame
highgui::imshow("Camera Module Demo", &display_frame)?;
// Break the loop if 'q' is pressed
if highgui::wait_key(30)? == 'q' as i32 {
break;
}
},
Err(e) => {
println!("Error capturing frame: {}", e);
break;
}
}
}
highgui::destroy_all_windows()?;
Ok(())
}