apple_vision/objectness_saliency/
mod.rs1#![allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
2#![allow(clippy::too_long_first_doc_paragraph)]
3use std::ffi::{CStr, CString};
7use std::path::Path;
8use std::ptr;
9
10use crate::error::VisionError;
11use crate::ffi;
12
13#[derive(Debug, Clone, Copy, PartialEq)]
15pub struct ObjectnessRegion {
16 pub x: f64,
17 pub y: f64,
18 pub w: f64,
19 pub h: f64,
20 pub confidence: f32,
21}
22
23pub fn objectness_saliency(path: impl AsRef<Path>) -> Result<Vec<ObjectnessRegion>, VisionError> {
30 let path_str = path
31 .as_ref()
32 .to_str()
33 .ok_or_else(|| VisionError::InvalidArgument("non-UTF-8 path".into()))?;
34 let cpath = CString::new(path_str)
35 .map_err(|e| VisionError::InvalidArgument(format!("path NUL byte: {e}")))?;
36 let mut rects_ptr: *mut ffi::SimpleRectRaw = ptr::null_mut();
37 let mut count: isize = 0;
38 let mut err: *mut std::ffi::c_char = ptr::null_mut();
39 let status = unsafe {
41 ffi::vn_objectness_saliency_in_path(cpath.as_ptr(), &mut rects_ptr, &mut count, &mut err)
42 };
43 if status != ffi::status::OK {
44 let msg = unsafe { take_err(err) };
46 return Err(VisionError::RequestFailed(msg));
47 }
48 let mut out = Vec::with_capacity(count.max(0) as usize);
49 for i in 0..count {
50 let r = unsafe { rects_ptr.offset(i).read() };
52 out.push(ObjectnessRegion {
53 x: r.x,
54 y: r.y,
55 w: r.w,
56 h: r.h,
57 confidence: r.confidence,
58 });
59 }
60 if !rects_ptr.is_null() {
61 unsafe { ffi::vn_simple_rects_free(rects_ptr, count) };
63 }
64 Ok(out)
65}
66
67unsafe fn take_err(p: *mut std::ffi::c_char) -> String {
74 if p.is_null() {
75 return String::new();
76 }
77 let s = unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned();
79 unsafe { libc::free(p.cast()) };
81 s
82}