Start the inference engine from both apps and show its choice in Settings
The desktop names where a package may have put libonnxruntime — an override variable, beside the executable, the package's own library directory, the Flatpak prefix, the system library directory — and Android points at the APK's native library directory, which is also what Qualcomm's DSP loader must be told for the Hexagon skel. Android starts the engine at the end of the model unpack rather than at launch, because the probe fingerprints the model files and a first launch has none until then. The About panel gains an Inference row beside Graphics, re-read every two seconds while the probe runs and engines land, and faces.model_id carries the detector's form: an int8 detector finds a different set of faces and is a different population (docs/inference.md §7). A low-memory signal drops every idle session with the GPU caches. The APK assembly bundles ONNX Runtime and the Qualcomm HTP libraries from Maven, fetched by tools/fetch-android-runtime.sh with their published checksums; RUNTIME_DIR=none builds the tract-only APK, which is a slower app and not a broken one. The desktop packages carry no runtime yet. Two probe fixes from the first desktop run: the floor must not be built with CPU fallback disabled, and a versioned libonnxruntime.so is a runtime too. On the reference desktop the probe now loads ONNX Runtime 1.30, measures 30 ms on the CPU provider, and selects TensorRT at 1.5 ms.
This commit is contained in:
@@ -40,16 +40,17 @@ use crate::align::{
|
||||
};
|
||||
use crate::eyes::{Eye, EyeReading};
|
||||
use crate::landmarks::{Landmarker, Landmarks};
|
||||
use crate::{install_backend, FaceError, Pixels};
|
||||
use crate::{FaceError, Pixels};
|
||||
use dr_inference_engine::{Form, Model, Role};
|
||||
|
||||
/// A loaded OCEC graph.
|
||||
pub struct EyeClassifier {
|
||||
session: ort::session::Session,
|
||||
session: Model,
|
||||
}
|
||||
|
||||
/// A loaded SGC graph.
|
||||
pub struct SunglassesClassifier {
|
||||
session: ort::session::Session,
|
||||
session: Model,
|
||||
}
|
||||
|
||||
/// Open a single-input, single-output classifier and check it is the shape
|
||||
@@ -63,12 +64,10 @@ fn open_classifier(
|
||||
bytes: &[u8],
|
||||
expected: &'static str,
|
||||
(h, w): (usize, usize),
|
||||
) -> Result<ort::session::Session, FaceError> {
|
||||
install_backend();
|
||||
let session = ort::session::Session::builder()
|
||||
.map_err(FaceError::Inference)?
|
||||
.commit_from_memory(bytes)
|
||||
.map_err(FaceError::Inference)?;
|
||||
) -> Result<Model, FaceError> {
|
||||
let model = dr_inference_engine::open(Role::EyeClassifier, Form::F32, bytes)?;
|
||||
let acquired = model.acquire()?;
|
||||
let session = acquired.lock();
|
||||
|
||||
let input = session.inputs().first().ok_or(FaceError::WrongModel {
|
||||
expected,
|
||||
@@ -93,7 +92,9 @@ fn open_classifier(
|
||||
detail: format!("{} outputs, expected one", session.outputs().len()),
|
||||
});
|
||||
}
|
||||
Ok(session)
|
||||
drop(session);
|
||||
drop(acquired);
|
||||
Ok(model)
|
||||
}
|
||||
|
||||
/// Lay a `h × w` RGB crop out as the `[1, 3, h, w]` tensor both graphs take.
|
||||
@@ -110,11 +111,9 @@ fn to_nchw(pixels: &[f32], h: usize, w: usize) -> Array4<f32> {
|
||||
}
|
||||
|
||||
/// Run a one-number classifier and read its sigmoid back, clamped.
|
||||
fn run_scalar(
|
||||
session: &mut ort::session::Session,
|
||||
input: Array4<f32>,
|
||||
expected: &'static str,
|
||||
) -> Result<f32, FaceError> {
|
||||
fn run_scalar(model: &Model, input: Array4<f32>, expected: &'static str) -> Result<f32, FaceError> {
|
||||
let acquired = model.acquire()?;
|
||||
let mut session = acquired.lock();
|
||||
let outputs = session
|
||||
.run(ort::inputs![
|
||||
ort::value::Tensor::from_array(input).map_err(FaceError::Inference)?
|
||||
@@ -149,7 +148,7 @@ impl EyeClassifier {
|
||||
/// P(open) for one eye.
|
||||
pub fn classify(&mut self, eye: &EyePatch) -> Result<f32, FaceError> {
|
||||
let input = to_nchw(eye.pixels(), EYE_PATCH_HEIGHT, EYE_PATCH_WIDTH);
|
||||
run_scalar(&mut self.session, input, "OCEC")
|
||||
run_scalar(&self.session, input, "OCEC")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +169,7 @@ impl SunglassesClassifier {
|
||||
let mut best = 0.0_f32;
|
||||
for view in head.views() {
|
||||
let input = to_nchw(view, SUNGLASSES_EDGE, SUNGLASSES_EDGE);
|
||||
best = best.max(run_scalar(&mut self.session, input, "SGC")?);
|
||||
best = best.max(run_scalar(&self.session, input, "SGC")?);
|
||||
}
|
||||
Ok(best)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
use ndarray::Array4;
|
||||
|
||||
use crate::align::crop_box;
|
||||
use crate::{install_backend, FaceError, Pixels};
|
||||
use crate::{FaceError, Pixels};
|
||||
use dr_inference_engine::{Form, Model, Role};
|
||||
|
||||
/// The graph's input edge, in pixels.
|
||||
pub const INPUT_EDGE: usize = 192;
|
||||
@@ -118,7 +119,7 @@ impl Landmarks {
|
||||
|
||||
/// A loaded `2d106det` graph.
|
||||
pub struct Landmarker {
|
||||
session: ort::session::Session,
|
||||
session: Model,
|
||||
}
|
||||
|
||||
impl Landmarker {
|
||||
@@ -128,11 +129,9 @@ impl Landmarker {
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, FaceError> {
|
||||
install_backend();
|
||||
let session = ort::session::Session::builder()
|
||||
.map_err(FaceError::Inference)?
|
||||
.commit_from_memory(bytes)
|
||||
.map_err(FaceError::Inference)?;
|
||||
let model = dr_inference_engine::open(Role::Landmarks, Form::F32, bytes)?;
|
||||
let acquired = model.acquire()?;
|
||||
let session = acquired.lock();
|
||||
|
||||
let input = session.inputs().first().ok_or(FaceError::WrongModel {
|
||||
expected: "2d106det",
|
||||
@@ -167,7 +166,9 @@ impl Landmarker {
|
||||
),
|
||||
});
|
||||
}
|
||||
Ok(Self { session })
|
||||
drop(session);
|
||||
drop(acquired);
|
||||
Ok(Self { session: model })
|
||||
}
|
||||
|
||||
/// The landmarks of the face in `bbox` — `(x0, y0, x1, y1)` in source
|
||||
@@ -206,8 +207,9 @@ impl Landmarker {
|
||||
}
|
||||
}
|
||||
}
|
||||
let outputs = self
|
||||
.session
|
||||
let acquired = self.session.acquire()?;
|
||||
let mut session = acquired.lock();
|
||||
let outputs = session
|
||||
.run(ort::inputs![
|
||||
ort::value::Tensor::from_array(input).map_err(FaceError::Inference)?
|
||||
])
|
||||
|
||||
Reference in New Issue
Block a user