meteor_detect/examples/camera_demo.rs

183 lines
5.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use anyhow::Result;
use log::{error, info};
use std::path::PathBuf;
use std::time::Duration;
use tokio::time;
// 导入Camera模块组件
use meteor_detect::camera::{CameraController, CameraSettings, ExposureMode, Resolution, Frame};
use meteor_detect::config::Config;
/// 这是一个简单的演示程序展示如何使用Camera模块的主要功能
#[tokio::main]
async fn main() -> Result<()> {
// 初始化日志,默认设置为 info 级别
env_logger::Builder::from_default_env()
.filter_level(log::LevelFilter::Info)
.init();
// 1. 创建配置
let config = create_demo_config();
// 2. 初始化相机控制器
info!("初始化相机控制器");
let mut camera_controller = CameraController::new(&config).await?;
// 3. 初始化相机设备
info!("初始化相机设备");
camera_controller.initialize().await?;
// 4. 启动视频捕获
info!("启动视频捕获");
camera_controller.start_capture().await?;
// 5. 获取相机状态
let status = camera_controller.get_status().await?;
info!("相机状态: {}", status);
// 6. 订阅帧更新
info!("设置帧处理器");
let mut frame_receiver = camera_controller.subscribe_to_frames();
// 在单独的任务中处理帧
let frame_processor = tokio::spawn(async move {
let mut frame_count = 0;
// 处理10个帧后退出
while let Ok(frame) = frame_receiver.recv().await {
frame_count += 1;
info!("收到帧 #{}: 时间戳={}", frame.index, frame.timestamp);
// 示例: 保存第5帧为图像文件
if frame_count == 5 {
info!("保存第5帧为图像文件");
let path = PathBuf::from("demo_frame.jpg");
if let Err(e) = frame.save_to_file(&path) {
error!("保存帧失败: {}", e);
}
}
if frame_count >= 10 {
info!("已处理10帧退出处理循环");
break;
}
}
info!("帧处理器已完成");
frame_count
});
// 7. 等待5秒然后模拟一个流星事件
info!("等待5秒后模拟流星事件...");
time::sleep(Duration::from_secs(5)).await;
// 获取当前时间作为事件时间戳
let event_timestamp = chrono::Utc::now();
// 模拟流星事件检测 - 保存事件视频
info!("保存流星事件");
match camera_controller
.save_meteor_event(
event_timestamp,
0.85, // 置信度
(100, 100, 200, 150), // 边界框 (x, y, width, height)
3, // 事件前3秒
2, // 事件后2秒
)
.await
{
Ok(event) => {
info!("保存了流星事件: id={}, 视频='{}'", event.id, event.video_path);
}
Err(e) => {
error!("保存流星事件失败: {}", e);
}
}
// 8. 更新相机设置
info!("更新相机设置");
let mut new_settings = config.camera.clone();
new_settings.resolution = Resolution::HD1080p;
new_settings.fps = 24;
camera_controller.update_settings(new_settings).await?;
// 9. 检查相机健康状态
info!("检查相机健康状态");
let is_healthy = camera_controller.check_health().await?;
info!("相机健康状态: {}", if is_healthy { "正常" } else { "异常" });
// 10. 等待帧处理完成
info!("等待帧处理器完成");
let processed_frames = frame_processor.await?;
info!("共处理了 {} 帧", processed_frames);
// 11. 停止视频捕获
info!("停止视频捕获");
camera_controller.stop_capture().await?;
info!("演示完成");
Ok(())
}
/// 创建用于演示的配置
fn create_demo_config() -> Config {
// 根据操作系统自动选择合适的设备路径
let device = match std::env::consts::OS {
"linux" => "/dev/video0".to_string(),
"macos" => "0".to_string(),
// Windows和其他操作系统通常使用索引
_ => "0".to_string(),
};
info!("自动选择相机设备: {}", device);
let camera_settings = CameraSettings {
device, // 使用根据操作系统确定的设备路径
resolution: Resolution::HD720p,
fps: 30,
exposure: ExposureMode::Auto,
gain: 128,
focus_locked: true,
file_input_mode: false,
input_file_path: String::new(),
loop_video: true,
};
Config {
camera: camera_settings,
// 其他配置字段,使用其默认值
..Default::default()
}
}
//
// /// 如果需要,这里提供一个更复杂的帧处理示例
// /// 可以作为单独函数供参考
// #[allow(dead_code)]
// async fn process_frames_with_opencv(frame: &Frame) -> Result<()> {
// use opencv::{core, imgproc, prelude::*};
//
// // 1. 转换为灰度图像
// let mut gray = core::Mat::default();
// imgproc::cvt_color(&frame.mat, &mut gray, imgproc::COLOR_BGR2GRAY, 0)?;
//
// // 2. 应用高斯模糊
// let mut blurred = core::Mat::default();
// imgproc::gaussian_blur(
// &gray,
// &mut blurred,
// core::Size::new(5, 5),
// 1.5,
// 1.5,
// core::BORDER_DEFAULT,
// )?;
//
// // 3. 应用边缘检测
// let mut edges = core::Mat::default();
// imgproc::canny(&blurred, &mut edges, 50.0, 150.0, 3, false)?;
//
// // 保存处理后的图像(可选)
// opencv::imgcodecs::imwrite("processed_frame.jpg", &edges, &core::Vector::new())?;
//
// Ok(())
// }