我目前正在学习 Rust,为了获得实践经验,我一直在玩一些小项目。
目前我正在做一个小型计算机视觉管道,用于进行多种不同的图像处理(目前是 QRDetection 和解码),并在屏幕上显示处理后的图像以及一些信息的表格。为此,我考虑了以下主要组成部分:
现在的主要流程是让 UIManager 拥有 PipelineManager,并在每一帧上运行管道(包含 CameraSource 和 QrDecoder)。
之后问题来了,我还想在UIManager拥有的表中显示最后一帧的QR信息,所以我需要在UIManager中保存一个QrDecoder的引用。 Stages 对象应该由 PipelineManager 拥有,但同一个对象可以被多次引用(不需要可变性)。
我能想到的解决这个问题的唯一方法是对每个阶段使用 Rc
管道管理器
use opencv::{prelude::*};
use std::cell::{RefCell};
use std::rc::Rc;
pub trait Stage {
fn process(&mut self, input: &mut Mat) -> Result<()>;
}
pub trait SourceStage {
fn get_frame(&mut self) -> Result<Box<Mat>>;
}
pub struct CVPipelineManager{
start_stage: Option<Rc<RefCell<dyn SourceStage>>>,
stages: Vec<Rc<RefCell<dyn Stage>>>
}
impl CVPipelineManager{
pub fn new() -> Self {
Self {
stages: Vec::new(),
start_stage: None,
}
}
pub fn add_stage(&mut self, stage: Rc<RefCell<dyn Stage>>){
self.stages.push(stage);
}
pub fn process(&mut self) -> Result<Box<Mat>>{
if let Some(ref mut start_stage) = self.start_stage {
let mut frame = start_stage.borrow_mut().get_frame()?;
self.process_image(frame.as_mut());
return Ok(frame);
}
return Err(anyhow!("Process cannot be called if a start stage was not defined"));
}
pub fn process_image(&mut self, input: &mut Mat) -> Result<()> {
for stage in self.stages.iter_mut() {
stage.borrow_mut().process(input)?;
}
Ok(())
}
此代码仅实现 PipelineManager 和所需的特征,以便更好地理解问题。
是否有更好的架构或者 Rust 是否提供了更好的工具来处理此类问题?我想不出任何其他方法来设计这个,而不会在实施新阶段时增加太多工作量。