183 lines
5.6 KiB
Rust
183 lines
5.6 KiB
Rust
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(())
|
||
// }
|