Skip to content

Commit 6db2686

Browse files
Refactor the pre-processing pipeline (#103)
This change refactors the `prepostprocess` module by moving code around, renaming things, and eliminating some extra code. The one key change to look out for that is not trivial is the switch to use `&mut self` for functions that use `*mut ...` pointers. This makes use of Rust's builtin borrow checking to avoid concurrent mutable access to the OpenVINO internal objects, which is hidden away by our `unsafe` FFI calls. Co-authored-by: Rahul <[email protected]>
1 parent 0ccb3bf commit 6db2686

File tree

4 files changed

+157
-179
lines changed

4 files changed

+157
-179
lines changed

crates/openvino/src/prepostprocess.rs

Lines changed: 129 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! See [`PrePostProcess Walkthrough`](https://docs.openvino.ai/2022.3/openvino_docs_OV_UG_Preprocessing_Overview.html).
44
//!
55
//! ```
6-
//!
76
//! # use openvino::{prepostprocess, Core, ElementType, Layout, Shape, Tensor, ResizeAlgorithm};
87
//! # use std::fs;
98
//! # let mut core = Core::new().expect("to instantiate the OpenVINO library");
@@ -18,16 +17,16 @@
1817
//! // Pre-process the input by:
1918
//! // - converting NHWC to NCHW
2019
//! // - resizing the input image
21-
//! let mut pre_post_process = prepostprocess::PrePostProcess::new(&model).expect("to create a new PrePostProcess instance");
22-
//! let input_info = pre_post_process.get_input_info_by_name("input").expect("to get input info by name");
23-
//! let mut input_tensor_info = input_info.preprocess_input_info_get_tensor_info().expect("to get tensor info");
24-
//! input_tensor_info.preprocess_input_tensor_set_from(&tensor).expect("to set tensor from");
25-
//! input_tensor_info.preprocess_input_tensor_set_layout(&Layout::new("NHWC").expect("to create a new layout")).expect("to set layout");
26-
//! let mut preprocess_steps = input_info.get_preprocess_steps().expect("to get preprocess steps");
27-
//! preprocess_steps.preprocess_steps_resize(ResizeAlgorithm::Linear).expect("to resize");
28-
//! let model_info = input_info.get_model_info().expect("to get model info");
29-
//! model_info.model_info_set_layout(&Layout::new("NCHW").expect("to create a new layout")).expect("to set layout");
30-
//! let new_model = pre_post_process.build_new_model().expect("to build new model with above prepostprocess steps");
20+
//! let mut pipeline = prepostprocess::Pipeline::new(&model).expect("to create a new pipeline");
21+
//! let input_info = pipeline.get_input_info_by_name("input").expect("to get input info by name");
22+
//! let mut input_tensor_info = input_info.get_tensor_info().expect("to get tensor info");
23+
//! input_tensor_info.set_from(&tensor).expect("to set tensor from");
24+
//! input_tensor_info.set_layout(&Layout::new("NHWC").expect("to create a new layout")).expect("to set layout");
25+
//! let mut preprocess_steps = input_info.get_steps().expect("to get preprocess steps");
26+
//! preprocess_steps.resize(ResizeAlgorithm::Linear).expect("to resize");
27+
//! let mut model_info = input_info.get_model_info().expect("to get model info");
28+
//! model_info.set_layout(&Layout::new("NCHW").expect("to create a new layout")).expect("to set layout");
29+
//! let new_model = pipeline.build_new_model().expect("to build new model with above prepostprocess steps");
3130
//! ```
3231
use crate::{
3332
cstr, drop_using_function, layout::Layout, try_unsafe, util::Result, ElementType, Model,
@@ -56,86 +55,12 @@ use openvino_sys::{
5655

5756
/// See [`PrePostProcess`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__prepostprocessor__t.html).
5857
#[derive(Debug)]
59-
pub struct PrePostProcess {
58+
pub struct Pipeline {
6059
ptr: *mut ov_preprocess_prepostprocessor_t,
6160
}
62-
drop_using_function!(PrePostProcess, ov_preprocess_prepostprocessor_free);
63-
64-
/// See [`PreProcessInputInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__input__info__t.html).
65-
pub struct PreProcessInputInfo {
66-
ptr: *mut ov_preprocess_input_info_t,
67-
}
68-
drop_using_function!(PreProcessInputInfo, ov_preprocess_input_info_free);
69-
70-
/// See [`PreprocessOutputInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__output__info__t.html).
71-
pub struct PreProcessOutputInfo {
72-
ptr: *mut ov_preprocess_output_info_t,
73-
}
74-
drop_using_function!(PreProcessOutputInfo, ov_preprocess_output_info_free);
75-
76-
/// See [`PreprocessSteps`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__preprocess__steps__t.html).
77-
pub struct PreProcessSteps {
78-
ptr: *mut ov_preprocess_preprocess_steps_t,
79-
}
80-
drop_using_function!(PreProcessSteps, ov_preprocess_preprocess_steps_free);
81-
82-
/// See [`PreprocessInputModelInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__input__model__info__t.html).
83-
pub struct PreProcessInputModelInfo {
84-
ptr: *mut ov_preprocess_input_model_info_t,
85-
}
86-
drop_using_function!(
87-
PreProcessInputModelInfo,
88-
ov_preprocess_input_model_info_free
89-
);
90-
91-
/// See [`PreprocessInputTensorInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__input__tensor__info__t.html).
92-
pub struct PreProcessInputTensorInfo {
93-
ptr: *mut ov_preprocess_input_tensor_info_t,
94-
}
95-
drop_using_function!(
96-
PreProcessInputTensorInfo,
97-
ov_preprocess_input_tensor_info_free
98-
);
99-
100-
/// See [`PreprocessOutputTensorInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__output__tensor__info__t.html).
101-
pub struct PreProcessOutputTensorInfo {
102-
ptr: *mut ov_preprocess_output_tensor_info_t,
103-
}
104-
drop_using_function!(
105-
PreProcessOutputTensorInfo,
106-
ov_preprocess_output_tensor_info_free
107-
);
108-
109-
impl PreProcessInputModelInfo {
110-
/// Sets the layout for the model information obj.
111-
pub fn model_info_set_layout(&self, layout: &Layout) -> Result<()> {
112-
try_unsafe!(ov_preprocess_input_model_info_set_layout(
113-
self.ptr,
114-
layout.as_ptr()
115-
))
116-
}
117-
}
118-
119-
impl PreProcessInputTensorInfo {
120-
/// Sets the layout for the input tensor.
121-
pub fn preprocess_input_tensor_set_layout(&self, layout: &Layout) -> Result<()> {
122-
try_unsafe!(ov_preprocess_input_tensor_info_set_layout(
123-
self.ptr,
124-
layout.as_ptr()
125-
))
126-
}
127-
128-
/// Sets the input tensor info from an existing tensor.
129-
pub fn preprocess_input_tensor_set_from(&mut self, tensor: &Tensor) -> Result<()> {
130-
try_unsafe!(ov_preprocess_input_tensor_info_set_from(
131-
self.ptr,
132-
tensor.as_ptr()
133-
))
134-
}
135-
}
136-
137-
impl PrePostProcess {
138-
/// Creates a new `PrePostProcess` pipeline for the given model.
61+
drop_using_function!(Pipeline, ov_preprocess_prepostprocessor_free);
62+
impl Pipeline {
63+
/// Creates a new [`Pipeline`] for the given [`Model`].
13964
pub fn new(model: &Model) -> Result<Self> {
14065
let mut ptr = std::ptr::null_mut();
14166
try_unsafe!(ov_preprocess_prepostprocessor_create(
@@ -146,65 +71,65 @@ impl PrePostProcess {
14671
}
14772

14873
/// Retrieves the input information by index.
149-
pub fn get_input_info_by_index(&self, index: usize) -> Result<PreProcessInputInfo> {
74+
pub fn get_input_info_by_index(&self, index: usize) -> Result<InputInfo> {
15075
let mut ptr = std::ptr::null_mut();
15176
try_unsafe!(ov_preprocess_prepostprocessor_get_input_info_by_index(
15277
self.ptr,
15378
index,
15479
std::ptr::addr_of_mut!(ptr)
15580
))?;
15681

157-
Ok(PreProcessInputInfo { ptr })
82+
Ok(InputInfo { ptr })
15883
}
15984

16085
/// Retrieves the input information by name.
161-
pub fn get_input_info_by_name(&self, name: &str) -> Result<PreProcessInputInfo> {
86+
pub fn get_input_info_by_name(&self, name: &str) -> Result<InputInfo> {
16287
let mut ptr = std::ptr::null_mut();
16388
try_unsafe!(ov_preprocess_prepostprocessor_get_input_info_by_name(
16489
self.ptr,
16590
cstr!(name),
16691
std::ptr::addr_of_mut!(ptr)
16792
))?;
16893

169-
Ok(PreProcessInputInfo { ptr })
94+
Ok(InputInfo { ptr })
17095
}
17196

17297
/// Retrieves the output information by name.
173-
pub fn get_output_info_by_name(&self, name: &str) -> Result<PreProcessOutputInfo> {
98+
pub fn get_output_info_by_name(&self, name: &str) -> Result<OutputInfo> {
17499
let mut ptr = std::ptr::null_mut();
175100
try_unsafe!(ov_preprocess_prepostprocessor_get_output_info_by_name(
176101
self.ptr,
177102
cstr!(name),
178103
std::ptr::addr_of_mut!(ptr)
179104
))?;
180-
Ok(PreProcessOutputInfo { ptr })
105+
Ok(OutputInfo { ptr })
181106
}
182107

183108
/// Retrieves the output information by index.
184-
pub fn get_output_info_by_index(&self, index: usize) -> Result<PreProcessOutputInfo> {
109+
pub fn get_output_info_by_index(&self, index: usize) -> Result<OutputInfo> {
185110
let mut ptr = std::ptr::null_mut();
186111
try_unsafe!(ov_preprocess_prepostprocessor_get_output_info_by_index(
187112
self.ptr,
188113
index,
189114
std::ptr::addr_of_mut!(ptr)
190115
))?;
191116

192-
Ok(PreProcessOutputInfo { ptr })
117+
Ok(OutputInfo { ptr })
193118
}
194119

195120
/// Retrieves the input information.
196121
///
197122
/// # Panics
198123
///
199124
/// Panics if the returned input info is null.
200-
pub fn get_input_info(&self) -> Result<PreProcessInputInfo> {
125+
pub fn get_input_info(&self) -> Result<InputInfo> {
201126
let mut ptr = std::ptr::null_mut();
202127
try_unsafe!(ov_preprocess_prepostprocessor_get_input_info(
203128
self.ptr,
204129
std::ptr::addr_of_mut!(ptr)
205130
))?;
206131
assert!(!ptr.is_null());
207-
Ok(PreProcessInputInfo { ptr })
132+
Ok(InputInfo { ptr })
208133
}
209134

210135
/// Builds a new model with all steps from pre/postprocessing.
@@ -218,88 +143,141 @@ impl PrePostProcess {
218143
}
219144
}
220145

221-
impl PreProcessSteps {
222-
/// Resizes data in tensor.
223-
pub fn preprocess_steps_resize(&mut self, resize_algo: ResizeAlgorithm) -> Result<()> {
224-
try_unsafe!(ov_preprocess_preprocess_steps_resize(
146+
/// See [`PreProcessInputInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__input__info__t.html).
147+
pub struct InputInfo {
148+
ptr: *mut ov_preprocess_input_info_t,
149+
}
150+
drop_using_function!(InputInfo, ov_preprocess_input_info_free);
151+
152+
impl InputInfo {
153+
/// Retrieves the preprocessing model input information.
154+
pub fn get_model_info(&self) -> Result<InputModelInfo> {
155+
let mut ptr = std::ptr::null_mut();
156+
try_unsafe!(ov_preprocess_input_info_get_model_info(
225157
self.ptr,
226-
resize_algo as u32,
158+
std::ptr::addr_of_mut!(ptr)
227159
))?;
228-
229-
Ok(())
160+
Ok(InputModelInfo { ptr })
230161
}
231162

232-
/// Converts the layout of data in tensor.
233-
pub fn preprocess_convert_layout(&self, layout: &Layout) -> Result<()> {
234-
try_unsafe!(ov_preprocess_preprocess_steps_convert_layout(
163+
/// Retrieves the input tensor information.
164+
pub fn get_tensor_info(&self) -> Result<InputTensorInfo> {
165+
let mut ptr: *mut ov_preprocess_input_tensor_info_t = std::ptr::null_mut();
166+
try_unsafe!(ov_preprocess_input_info_get_tensor_info(
235167
self.ptr,
236-
layout.as_ptr(),
168+
std::ptr::addr_of_mut!(ptr)
237169
))?;
170+
Ok(InputTensorInfo { ptr })
171+
}
238172

239-
Ok(())
173+
/// Retrieves the preprocessing steps.
174+
pub fn get_steps(&self) -> Result<Steps> {
175+
let mut ptr = std::ptr::null_mut();
176+
try_unsafe!(ov_preprocess_input_info_get_preprocess_steps(
177+
self.ptr,
178+
std::ptr::addr_of_mut!(ptr)
179+
))?;
180+
Ok(Steps { ptr })
240181
}
182+
}
241183

242-
/// Converts the element type of data in tensor.
243-
pub fn preprocess_convert_element_type(&self, element_type: ElementType) -> Result<()> {
244-
try_unsafe!(ov_preprocess_preprocess_steps_convert_element_type(
184+
/// See [`PreprocessOutputInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__output__info__t.html).
185+
pub struct OutputInfo {
186+
ptr: *mut ov_preprocess_output_info_t,
187+
}
188+
drop_using_function!(OutputInfo, ov_preprocess_output_info_free);
189+
impl OutputInfo {
190+
/// Retrieves preprocess output tensor information.
191+
pub fn get_tensor_info(&self) -> Result<OutputTensorInfo> {
192+
let mut ptr: *mut ov_preprocess_output_tensor_info_t = std::ptr::null_mut();
193+
try_unsafe!(ov_preprocess_output_info_get_tensor_info(
245194
self.ptr,
246-
element_type as u32
195+
std::ptr::addr_of_mut!(ptr)
247196
))?;
197+
Ok(OutputTensorInfo { ptr })
198+
}
199+
}
248200

249-
Ok(())
201+
/// See [`PreprocessInputModelInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__input__model__info__t.html).
202+
pub struct InputModelInfo {
203+
ptr: *mut ov_preprocess_input_model_info_t,
204+
}
205+
drop_using_function!(InputModelInfo, ov_preprocess_input_model_info_free);
206+
impl InputModelInfo {
207+
/// Sets the layout for the model information obj.
208+
pub fn set_layout(&mut self, layout: &Layout) -> Result<()> {
209+
try_unsafe!(ov_preprocess_input_model_info_set_layout(
210+
self.ptr,
211+
layout.as_ptr()
212+
))
250213
}
251214
}
252215

253-
impl PreProcessOutputTensorInfo {
254-
/// Sets the element type for output tensor info.
255-
pub fn preprocess_set_element_type(&self, element_type: ElementType) -> Result<()> {
256-
try_unsafe!(ov_preprocess_output_set_element_type(
216+
/// See [`PreprocessInputTensorInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__input__tensor__info__t.html).
217+
pub struct InputTensorInfo {
218+
ptr: *mut ov_preprocess_input_tensor_info_t,
219+
}
220+
drop_using_function!(InputTensorInfo, ov_preprocess_input_tensor_info_free);
221+
impl InputTensorInfo {
222+
/// Sets the [`Layout`] for the input tensor.
223+
pub fn set_layout(&mut self, layout: &Layout) -> Result<()> {
224+
try_unsafe!(ov_preprocess_input_tensor_info_set_layout(
257225
self.ptr,
258-
element_type as u32
226+
layout.as_ptr()
227+
))
228+
}
229+
230+
/// Sets the input tensor info from an existing tensor.
231+
pub fn set_from(&mut self, tensor: &Tensor) -> Result<()> {
232+
try_unsafe!(ov_preprocess_input_tensor_info_set_from(
233+
self.ptr,
234+
tensor.as_ptr()
259235
))
260236
}
261237
}
262238

263-
impl PreProcessOutputInfo {
264-
/// Retrieves preprocess output tensor information.
265-
pub fn get_output_info_get_tensor_info(&self) -> Result<PreProcessOutputTensorInfo> {
266-
let mut ptr: *mut ov_preprocess_output_tensor_info_t = std::ptr::null_mut();
267-
try_unsafe!(ov_preprocess_output_info_get_tensor_info(
239+
/// See [`PreprocessOutputTensorInfo`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__output__tensor__info__t.html).
240+
pub struct OutputTensorInfo {
241+
ptr: *mut ov_preprocess_output_tensor_info_t,
242+
}
243+
drop_using_function!(OutputTensorInfo, ov_preprocess_output_tensor_info_free);
244+
impl OutputTensorInfo {
245+
/// Sets the element type for output tensor info.
246+
pub fn set_element_type(&mut self, element_type: ElementType) -> Result<()> {
247+
try_unsafe!(ov_preprocess_output_set_element_type(
268248
self.ptr,
269-
std::ptr::addr_of_mut!(ptr)
270-
))?;
271-
Ok(PreProcessOutputTensorInfo { ptr })
249+
element_type as u32
250+
))
272251
}
273252
}
274253

275-
impl PreProcessInputInfo {
276-
/// Retrieves the preprocessing model input information.
277-
pub fn get_model_info(&self) -> Result<PreProcessInputModelInfo> {
278-
let mut ptr = std::ptr::null_mut();
279-
try_unsafe!(ov_preprocess_input_info_get_model_info(
254+
/// See [`PreprocessSteps`](https://docs.openvino.ai/2023.3/api/c_cpp_api/structov__preprocess__preprocess__steps__t.html).
255+
pub struct Steps {
256+
ptr: *mut ov_preprocess_preprocess_steps_t,
257+
}
258+
drop_using_function!(Steps, ov_preprocess_preprocess_steps_free);
259+
impl Steps {
260+
/// Resizes the data in a [`Tensor`].
261+
pub fn resize(&mut self, resize_algo: ResizeAlgorithm) -> Result<()> {
262+
try_unsafe!(ov_preprocess_preprocess_steps_resize(
280263
self.ptr,
281-
std::ptr::addr_of_mut!(ptr)
282-
))?;
283-
Ok(PreProcessInputModelInfo { ptr })
264+
resize_algo as u32
265+
))
284266
}
285267

286-
/// Retrieves the input tensor information.
287-
pub fn preprocess_input_info_get_tensor_info(&self) -> Result<PreProcessInputTensorInfo> {
288-
let mut ptr: *mut ov_preprocess_input_tensor_info_t = std::ptr::null_mut();
289-
try_unsafe!(ov_preprocess_input_info_get_tensor_info(
268+
/// Converts the [`Layout`] of the data in a [`Tensor`].
269+
pub fn convert_layout(&mut self, new_layout: &Layout) -> Result<()> {
270+
try_unsafe!(ov_preprocess_preprocess_steps_convert_layout(
290271
self.ptr,
291-
std::ptr::addr_of_mut!(ptr)
292-
))?;
293-
Ok(PreProcessInputTensorInfo { ptr })
272+
new_layout.as_ptr(),
273+
))
294274
}
295275

296-
/// Retrieves preprocessing steps object.
297-
pub fn get_preprocess_steps(&self) -> Result<PreProcessSteps> {
298-
let mut ptr = std::ptr::null_mut();
299-
try_unsafe!(ov_preprocess_input_info_get_preprocess_steps(
276+
/// Converts the element type of data in tensor.
277+
pub fn convert_element_type(&mut self, new_element_type: ElementType) -> Result<()> {
278+
try_unsafe!(ov_preprocess_preprocess_steps_convert_element_type(
300279
self.ptr,
301-
std::ptr::addr_of_mut!(ptr)
302-
))?;
303-
Ok(PreProcessSteps { ptr })
280+
new_element_type as u32
281+
))
304282
}
305283
}

0 commit comments

Comments
 (0)