break submodules out into separate files
This commit is contained in:
parent
c9df4410fb
commit
9e7abe0945
37
src/face_mesh.rs
Normal file
37
src/face_mesh.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//! Face detection utilities.
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub struct FaceMeshDetector {
|
||||||
|
graph: Detector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FaceMeshDetector {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let graph = Detector::new(
|
||||||
|
FACE_GRAPH_TYPE,
|
||||||
|
include_str!("graphs/face_mesh_desktop_live.pbtxt"),
|
||||||
|
"multi_face_landmarks",
|
||||||
|
);
|
||||||
|
|
||||||
|
Self { graph }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Processes the input frame, returns a face mesh if detected.
|
||||||
|
pub fn process(&mut self, input: &Mat) -> Option<FaceMesh> {
|
||||||
|
let landmarks = self.graph.process(input);
|
||||||
|
|
||||||
|
if landmarks.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut face_mesh = FaceMesh::default();
|
||||||
|
face_mesh.data.copy_from_slice(landmarks);
|
||||||
|
Some(face_mesh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FaceMeshDetector {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
65
src/hands.rs
Normal file
65
src/hands.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
//! Hand detection utilities.
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Hand landmark indices.
|
||||||
|
pub enum HandLandmark {
|
||||||
|
WRIST = 0,
|
||||||
|
THUMB_CMC = 1,
|
||||||
|
THUMB_MCP = 2,
|
||||||
|
THUMB_IP = 3,
|
||||||
|
THUMB_TIP = 4,
|
||||||
|
INDEX_FINGER_MCP = 5,
|
||||||
|
INDEX_FINGER_PIP = 6,
|
||||||
|
INDEX_FINGER_DIP = 7,
|
||||||
|
INDEX_FINGER_TIP = 8,
|
||||||
|
MIDDLE_FINGER_MCP = 9,
|
||||||
|
MIDDLE_FINGER_PIP = 10,
|
||||||
|
MIDDLE_FINGER_DIP = 11,
|
||||||
|
MIDDLE_FINGER_TIP = 12,
|
||||||
|
RING_FINGER_MCP = 13,
|
||||||
|
RING_FINGER_PIP = 14,
|
||||||
|
RING_FINGER_DIP = 15,
|
||||||
|
RING_FINGER_TIP = 16,
|
||||||
|
PINKY_MCP = 17,
|
||||||
|
PINKY_PIP = 18,
|
||||||
|
PINKY_DIP = 19,
|
||||||
|
PINKY_TIP = 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HandDetector {
|
||||||
|
graph: Detector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HandDetector {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let graph = Detector::new(
|
||||||
|
HANDS_GRAPH_TYPE,
|
||||||
|
include_str!("graphs/hand_tracking_desktop_live.pbtxt"),
|
||||||
|
"hand_landmarks",
|
||||||
|
);
|
||||||
|
|
||||||
|
Self { graph }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Processes the input frame, returns a tuple of hands if detected.
|
||||||
|
pub fn process(&mut self, input: &Mat) -> Option<[Hand; 2]> {
|
||||||
|
let landmarks = self.graph.process(input);
|
||||||
|
|
||||||
|
if landmarks.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut lh = Hand::default();
|
||||||
|
let mut rh = Hand::default();
|
||||||
|
lh.data.copy_from_slice(&landmarks[0..21]);
|
||||||
|
rh.data.copy_from_slice(&landmarks[21..42]);
|
||||||
|
|
||||||
|
Some([lh, rh])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for HandDetector {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
238
src/lib.rs
238
src/lib.rs
|
@ -15,6 +15,10 @@ use opencv::prelude::*;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
mod bindings;
|
mod bindings;
|
||||||
|
pub mod face_mesh;
|
||||||
|
pub mod hands;
|
||||||
|
pub mod pose;
|
||||||
|
pub mod segmentation;
|
||||||
|
|
||||||
use bindings::*;
|
use bindings::*;
|
||||||
|
|
||||||
|
@ -151,15 +155,27 @@ impl Effect {
|
||||||
/// Processes the input frame, returns a slice of landmarks if any are detected.
|
/// Processes the input frame, returns a slice of landmarks if any are detected.
|
||||||
pub fn process(&mut self, input: &Mat) -> Mat {
|
pub fn process(&mut self, input: &Mat) -> Mat {
|
||||||
let mut data = input.clone();
|
let mut data = input.clone();
|
||||||
|
let cols = data.cols();
|
||||||
|
let rows = data.rows();
|
||||||
|
let typ = data.typ();
|
||||||
let out_data = unsafe {
|
let out_data = unsafe {
|
||||||
mediagraph_Effect_Process(
|
mediagraph_Effect_Process(
|
||||||
self.graph as *mut std::ffi::c_void,
|
self.graph as *mut std::ffi::c_void,
|
||||||
data.data_mut(),
|
data.data_mut(),
|
||||||
data.cols(),
|
cols,
|
||||||
data.rows(),
|
rows,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
unsafe { Mat::from_raw(out_data as *mut std::ffi::c_void) }
|
unsafe {
|
||||||
|
Mat::new_rows_cols_with_data(
|
||||||
|
rows,
|
||||||
|
cols,
|
||||||
|
typ,
|
||||||
|
out_data as *mut std::ffi::c_void,
|
||||||
|
opencv::core::Mat_AUTO_STEP,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,219 +186,3 @@ impl Drop for Effect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod pose {
|
|
||||||
//! Pose detection utilities.
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// Pose landmark indices.
|
|
||||||
pub enum PoseLandmark {
|
|
||||||
NOSE = 0,
|
|
||||||
LEFT_EYE_INNER = 1,
|
|
||||||
LEFT_EYE = 2,
|
|
||||||
LEFT_EYE_OUTER = 3,
|
|
||||||
RIGHT_EYE_INNER = 4,
|
|
||||||
RIGHT_EYE = 5,
|
|
||||||
RIGHT_EYE_OUTER = 6,
|
|
||||||
LEFT_EAR = 7,
|
|
||||||
RIGHT_EAR = 8,
|
|
||||||
MOUTH_LEFT = 9,
|
|
||||||
MOUTH_RIGHT = 10,
|
|
||||||
LEFT_SHOULDER = 11,
|
|
||||||
RIGHT_SHOULDER = 12,
|
|
||||||
LEFT_ELBOW = 13,
|
|
||||||
RIGHT_ELBOW = 14,
|
|
||||||
LEFT_WRIST = 15,
|
|
||||||
RIGHT_WRIST = 16,
|
|
||||||
LEFT_PINKY = 17,
|
|
||||||
RIGHT_PINKY = 18,
|
|
||||||
LEFT_INDEX = 19,
|
|
||||||
RIGHT_INDEX = 20,
|
|
||||||
LEFT_THUMB = 21,
|
|
||||||
RIGHT_THUMB = 22,
|
|
||||||
LEFT_HIP = 23,
|
|
||||||
RIGHT_HIP = 24,
|
|
||||||
LEFT_KNEE = 25,
|
|
||||||
RIGHT_KNEE = 26,
|
|
||||||
LEFT_ANKLE = 27,
|
|
||||||
RIGHT_ANKLE = 28,
|
|
||||||
LEFT_HEEL = 29,
|
|
||||||
RIGHT_HEEL = 30,
|
|
||||||
LEFT_FOOT_INDEX = 31,
|
|
||||||
RIGHT_FOOT_INDEX = 32,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PoseDetector {
|
|
||||||
graph: Detector,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PoseDetector {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let graph = Detector::new(
|
|
||||||
POSE_GRAPH_TYPE,
|
|
||||||
include_str!("graphs/pose_tracking_cpu.pbtxt"),
|
|
||||||
"pose_landmarks",
|
|
||||||
);
|
|
||||||
|
|
||||||
Self { graph }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Processes the input frame, returns a pose if detected.
|
|
||||||
pub fn process(&mut self, input: &Mat) -> Option<Pose> {
|
|
||||||
let landmarks = self.graph.process(input);
|
|
||||||
|
|
||||||
if landmarks.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut pose = Pose::default();
|
|
||||||
pose.data.copy_from_slice(landmarks);
|
|
||||||
Some(pose)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PoseDetector {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod face_mesh {
|
|
||||||
//! Face detection utilities.
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
pub struct FaceMeshDetector {
|
|
||||||
graph: Detector,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FaceMeshDetector {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let graph = Detector::new(
|
|
||||||
FACE_GRAPH_TYPE,
|
|
||||||
include_str!("graphs/face_mesh_desktop_live.pbtxt"),
|
|
||||||
"multi_face_landmarks",
|
|
||||||
);
|
|
||||||
|
|
||||||
Self { graph }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Processes the input frame, returns a face mesh if detected.
|
|
||||||
pub fn process(&mut self, input: &Mat) -> Option<FaceMesh> {
|
|
||||||
let landmarks = self.graph.process(input);
|
|
||||||
|
|
||||||
if landmarks.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut face_mesh = FaceMesh::default();
|
|
||||||
face_mesh.data.copy_from_slice(landmarks);
|
|
||||||
Some(face_mesh)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for FaceMeshDetector {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod hands {
|
|
||||||
//! Hand detection utilities.
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// Hand landmark indices.
|
|
||||||
pub enum HandLandmark {
|
|
||||||
WRIST = 0,
|
|
||||||
THUMB_CMC = 1,
|
|
||||||
THUMB_MCP = 2,
|
|
||||||
THUMB_IP = 3,
|
|
||||||
THUMB_TIP = 4,
|
|
||||||
INDEX_FINGER_MCP = 5,
|
|
||||||
INDEX_FINGER_PIP = 6,
|
|
||||||
INDEX_FINGER_DIP = 7,
|
|
||||||
INDEX_FINGER_TIP = 8,
|
|
||||||
MIDDLE_FINGER_MCP = 9,
|
|
||||||
MIDDLE_FINGER_PIP = 10,
|
|
||||||
MIDDLE_FINGER_DIP = 11,
|
|
||||||
MIDDLE_FINGER_TIP = 12,
|
|
||||||
RING_FINGER_MCP = 13,
|
|
||||||
RING_FINGER_PIP = 14,
|
|
||||||
RING_FINGER_DIP = 15,
|
|
||||||
RING_FINGER_TIP = 16,
|
|
||||||
PINKY_MCP = 17,
|
|
||||||
PINKY_PIP = 18,
|
|
||||||
PINKY_DIP = 19,
|
|
||||||
PINKY_TIP = 20,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct HandDetector {
|
|
||||||
graph: Detector,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HandDetector {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let graph = Detector::new(
|
|
||||||
HANDS_GRAPH_TYPE,
|
|
||||||
include_str!("graphs/hand_tracking_desktop_live.pbtxt"),
|
|
||||||
"hand_landmarks",
|
|
||||||
);
|
|
||||||
|
|
||||||
Self { graph }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Processes the input frame, returns a tuple of hands if detected.
|
|
||||||
pub fn process(&mut self, input: &Mat) -> Option<[Hand; 2]> {
|
|
||||||
let landmarks = self.graph.process(input);
|
|
||||||
|
|
||||||
if landmarks.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut lh = Hand::default();
|
|
||||||
let mut rh = Hand::default();
|
|
||||||
lh.data.copy_from_slice(&landmarks[0..21]);
|
|
||||||
rh.data.copy_from_slice(&landmarks[21..42]);
|
|
||||||
|
|
||||||
Some([lh, rh])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for HandDetector {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod segmentation {
|
|
||||||
//! Selfie segmentation utilities.
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
pub struct Segmentor {
|
|
||||||
graph: Effect,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Segmentor {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let graph = Effect::new(
|
|
||||||
include_str!("graphs/selfie_segmentation_cpu.pbtxt"),
|
|
||||||
"output_video",
|
|
||||||
);
|
|
||||||
|
|
||||||
Self { graph }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Processes the input frame, returns the output frame.
|
|
||||||
pub fn process(&mut self, input: &Mat) -> Mat {
|
|
||||||
self.graph.process(input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Segmentor {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
74
src/pose.rs
Normal file
74
src/pose.rs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
//! Pose detection utilities.
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Pose landmark indices.
|
||||||
|
pub enum PoseLandmark {
|
||||||
|
NOSE = 0,
|
||||||
|
LEFT_EYE_INNER = 1,
|
||||||
|
LEFT_EYE = 2,
|
||||||
|
LEFT_EYE_OUTER = 3,
|
||||||
|
RIGHT_EYE_INNER = 4,
|
||||||
|
RIGHT_EYE = 5,
|
||||||
|
RIGHT_EYE_OUTER = 6,
|
||||||
|
LEFT_EAR = 7,
|
||||||
|
RIGHT_EAR = 8,
|
||||||
|
MOUTH_LEFT = 9,
|
||||||
|
MOUTH_RIGHT = 10,
|
||||||
|
LEFT_SHOULDER = 11,
|
||||||
|
RIGHT_SHOULDER = 12,
|
||||||
|
LEFT_ELBOW = 13,
|
||||||
|
RIGHT_ELBOW = 14,
|
||||||
|
LEFT_WRIST = 15,
|
||||||
|
RIGHT_WRIST = 16,
|
||||||
|
LEFT_PINKY = 17,
|
||||||
|
RIGHT_PINKY = 18,
|
||||||
|
LEFT_INDEX = 19,
|
||||||
|
RIGHT_INDEX = 20,
|
||||||
|
LEFT_THUMB = 21,
|
||||||
|
RIGHT_THUMB = 22,
|
||||||
|
LEFT_HIP = 23,
|
||||||
|
RIGHT_HIP = 24,
|
||||||
|
LEFT_KNEE = 25,
|
||||||
|
RIGHT_KNEE = 26,
|
||||||
|
LEFT_ANKLE = 27,
|
||||||
|
RIGHT_ANKLE = 28,
|
||||||
|
LEFT_HEEL = 29,
|
||||||
|
RIGHT_HEEL = 30,
|
||||||
|
LEFT_FOOT_INDEX = 31,
|
||||||
|
RIGHT_FOOT_INDEX = 32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PoseDetector {
|
||||||
|
graph: Detector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PoseDetector {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let graph = Detector::new(
|
||||||
|
POSE_GRAPH_TYPE,
|
||||||
|
include_str!("graphs/pose_tracking_cpu.pbtxt"),
|
||||||
|
"pose_landmarks",
|
||||||
|
);
|
||||||
|
|
||||||
|
Self { graph }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Processes the input frame, returns a pose if detected.
|
||||||
|
pub fn process(&mut self, input: &Mat) -> Option<Pose> {
|
||||||
|
let landmarks = self.graph.process(input);
|
||||||
|
|
||||||
|
if landmarks.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut pose = Pose::default();
|
||||||
|
pose.data.copy_from_slice(landmarks);
|
||||||
|
Some(pose)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PoseDetector {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
28
src/segmentation.rs
Normal file
28
src/segmentation.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
//! Selfie segmentation utilities.
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub struct Segmentor {
|
||||||
|
graph: Effect,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Segmentor {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let graph = Effect::new(
|
||||||
|
include_str!("graphs/selfie_segmentation_cpu.pbtxt"),
|
||||||
|
"output_video",
|
||||||
|
);
|
||||||
|
|
||||||
|
Self { graph }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Processes the input frame, returns the output frame.
|
||||||
|
pub fn process(&mut self, input: &Mat) -> Mat {
|
||||||
|
self.graph.process(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Segmentor {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user