如何解决 Rust 中的特征绑定错误并重新运行

问题描述 投票:0回答:1

我正在使用一种名为 rerun 的工具来可视化图像。我认为我应该使我的函数通用,而不是针对不同的数据类型使用多个函数,例如

f32
u8
等。

这是我的尝试:

use num::Zero; use opencv::core; use opencv::prelude::*; use rerun::external::ndarray; use shared::Point3d; trait AllowedTypes {} impl AllowedTypes for f32 {} impl AllowedTypes for u8 {} impl AllowedTypes for u16 {} pub fn visualize_image<T: AllowedTypes>( cv_image: &core::Mat, frame_idx: usize, rec: &rerun::RecordingStream, name: &str, ) where T: Zero + std::clone::Clone + std::fmt::Debug + core::DataType, { let mat = cv_image.clone(); let (width, height) = (mat.cols(), mat.rows()); let size = (width * height * mat.channels() as i32) as usize; let mut image_data = vec![T::zero(); size]; let data_typed = match mat.data_typed::<T>() { Ok(data_u8) => data_u8, Err(e) => panic!("Error extracting data: {}", e), }; image_data.copy_from_slice(data_typed); let img_array = match ndarray::Array2::from_shape_vec((height as usize, width as usize), image_data) { Ok(img_array) => img_array, Err(e) => panic!("Error creating Array from vec<u8>: {}", e), }; let rgb_image = match rerun::Image::from_color_model_and_tensor(rerun::ColorModel::L, img_array.clone()) { Ok(rgb_image) => rgb_image, Err(e) => panic!("Could not create image: {}", e), }; rec.set_time_sequence("frame_idx", frame_idx as i64); // RGB image match rec.log(name, &rgb_image) { Ok(_) => (), Err(e) => panic!("Could not log image: {}", e), } }
错误是:

error[E0277]: the trait bound `rerun::TensorData: From<ArrayBase<OwnedRepr<T>, Dim<[usize; 2]>>>` is not satisfied --> libs/visualization/src/visualizer.rs:39:15 | 39 | match rerun::Image::from_color_model_and_tensor(rerun::ColorModel::L, img_array.clone()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<ArrayBase<OwnedRepr<T>, Dim<[usize; 2]>>>` is not implemented for `rerun::TensorData`, which is required by `rerun::TensorData: TryFrom<ArrayBase<OwnedRepr<T>, Dim<[usize; 2]>>>` | = help: the following other types implement trait `From<T>`: <rerun::TensorData as From<&[f32]>> <rerun::TensorData as From<&[f64]>> <rerun::TensorData as From<&[i16]>> <rerun::TensorData as From<&[i32]>> <rerun::TensorData as From<&[i64]>> <rerun::TensorData as From<&[i8]>> <rerun::TensorData as From<&[rerun::external::re_arrow2::types::f16]>> <rerun::TensorData as From<&[u16]>> and 14 others = note: required for `ArrayBase<OwnedRepr<T>, Dim<[usize; 2]>>` to implement `Into<rerun::TensorData>` = note: required for `rerun::TensorData` to implement `TryFrom<ArrayBase<OwnedRepr<T>, Dim<[usize; 2]>>>`
我以为我可以通过限制 

AllowedTypes

 使用我感兴趣的数字类型来解决这个问题。但这似乎不起作用。

货物.toml

[package] name = "visualization" version = "0.1.0" edition = "2021" [dependencies] rerun = "0.19.0" opencv = "0.92.3" num = "0.4"
    
rust
1个回答
0
投票
有两个主要问题阻碍了这一点的直接实现,我将一一解释。

  1. 这个问题

    无法通过将 AllowedTypes 限制为

    TensorData
    最初接受的数字类型来解决
    ,因为这就是 Rust 类型系统的工作方式 - 所有特征边界都在本地检查,这意味着编译器将一无所知类型参数 
    T
     除了它的边界和它们的方法。具体来说,编译器不知道函数端类型参数的“底层类型”是什么;这与 C++ 世界有很大的不同。

  2. 知道缺乏足够的

    TryFrom

     会导致失败,人们自然会想要实现 
    TryFrom<ArrayBase<OwnedRepr<T>, D>> for TensorData
    ,其中 
    T: AllowedTypes
     模仿 
    rerun
     中预先存在的实现,试图满足 
    from_color_model_and_tensor
     的界限,但是不幸的是,这会失败,因为“孤儿规则”要求: 
    我们无法在外部类型上实现外部特征。这里, ArrayBaseTensorData
     都是外部类型,
    TryFrom
     是一个标准特征,它们都来自我们的板条箱外部。
    
    

    为了解决前一个问题,您可以使用“动态调度”,编译器几乎肯定会对其进行优化,通过将类型信息记录在
  3. Vec<T>
的“底层”类型的 vec 中

T

表示的枚举,并使用宏有效地扩展
AllowedTypes
的impl内所有可能的类型:
TryFrom
并且,绕过后一个的一种简单方法是定义一个 
macro_rules! impl_allowed { ( $( $t:tt ),* ) => { #[allow(non_camel_case_types)] pub enum Type { $( $t ),* } $( impl AllowedTypes for $t { fn actual_type() -> Type { Type::$t } } )* }; } // ... // at the end of `try_from` impl paste! { let buffer = match T::actual_type() { $( Type::$t => unsafe { let (ptr, len, cap) = vec.into_raw_parts(); let vec = Vec::from_raw_parts(ptr as *mut $t, len, cap); // use paste to format the typename to match `TensorBuffer`'s variant names TensorBuffer::[< $t:camel >](vec.into()) } )* }; }

,它简单地将任何值包装在其中,impl
Local<T>
,并将其作为参数传递。

TryFrom<Local<ArrayBase<OwnedRepr<T>, D>>> for TensorData
完整代码如下:

#[repr(transparent)] struct Local<T>(pub T); macro_rules! impl_try_from { ( $( $t:ident ),* ) => { impl<T: AllowedTypes, D: Dimension> TryFrom<Local<ArrayBase<OwnedRepr<T>, D>>> for TensorData { type Error = TensorCastError; fn try_from(value: Local<ArrayBase<OwnedRepr<T>, D>>) -> Result<Self, Self::Error> { let value = value.0; // ... // at call site let rgb_image = match rerun::Image::from_color_model_and_tensor( rerun::ColorModel::L, Local(img_array.clone()), ) { // ...
    

© www.soinside.com 2019 - 2024. All rights reserved.