use std::path::PathBuf; use std::io::{self, Write}; use chrono::{Local, Utc}; use anyhow::{Context, Result}; use opencv::{highgui, core, prelude::*}; use tokio; use std::sync::{Arc, Mutex}; // 导入项目中的模块 use meteor_detect::camera::{CameraSettings, Resolution, ExposureMode, CameraController, Frame}; use meteor_detect::config::{Config, load_config}; use meteor_detect::overlay::star_chart::{StarChart, StarChartOptions}; use meteor_detect::gps::{GpsStatus, GeoPosition, CameraOrientation}; #[tokio::main] async fn main() -> Result<()> { println!("*** File Input Demo ***"); println!("This demo shows how to use a video file as input for the meteor detection system"); println!("It will apply the star chart overlay to the video frames"); println!("Press 'q' to quit"); println!(); // 读取视频文件路径 println!("Enter the path to a video file:"); let mut file_path = String::new(); io::stdin().read_line(&mut file_path)?; let file_path = file_path.trim(); // 检查文件是否存在 if !std::path::Path::new(file_path).exists() { println!("Error: File '{}' does not exist", file_path); return Ok(()); } // 创建配置 let mut config = load_config().unwrap(); // 设置为文件输入模式 config.camera.file_input_mode = true; config.camera.input_file_path = file_path.to_string(); config.camera.loop_video = true; // 确保星图配置已启用 config.star_chart.enabled = true; // 初始化相机控制器 let mut camera_controller = CameraController::new(&config).await.unwrap(); println!("Initializing with video file: {}", file_path); camera_controller.initialize().await.unwrap(); // 创建星图覆盖层 let gps_status = Arc::new(Mutex::new(GpsStatus::default())); let mut star_chart = StarChart::new( config.star_chart.clone(), gps_status.clone() ).await.unwrap(); println!("Starting video playback..."); camera_controller.start_capture().await.unwrap(); // 获取帧订阅 let mut frame_rx = camera_controller.subscribe_to_frames(); // 创建窗口 highgui::named_window("File Input Demo", highgui::WINDOW_NORMAL)?; highgui::resize_window("File Input Demo", 1280, 720)?; // 处理帧循环 while let Ok(frame) = frame_rx.recv().await { // 创建用于显示的帧 let mut display_frame = frame.mat.clone(); // 应用星图覆盖 if let Err(e) = star_chart.apply(&mut display_frame, frame.timestamp).await { println!("Error applying star chart: {}", e); } // 在帧上显示时间戳和帧计数 let timestamp_text = format!("Frame: {} - Time: {}", frame.index, frame.timestamp.with_timezone(&Local).format("%Y-%m-%d %H:%M:%S%.3f") ); opencv::imgproc::put_text( &mut display_frame, ×tamp_text, core::Point::new(10, 30), opencv::imgproc::FONT_HERSHEY_SIMPLEX, 1.0, core::Scalar::new(0.0, 255.0, 0.0, 0.0), 2, opencv::imgproc::LINE_AA, false, )?; // 显示帧 highgui::imshow("File Input Demo", &display_frame)?; // 检查按键 let key = highgui::wait_key(1)?; if key == 'q' as i32 { println!("Quitting..."); break; } } // 清理 println!("Shutting down..."); camera_controller.stop_capture().await.unwrap(); highgui::destroy_all_windows()?; println!("Demo completed successfully"); Ok(()) }