395 lines
10 KiB
Rust
395 lines
10 KiB
Rust
|
#![allow(dead_code)]
|
||
|
#![allow(non_camel_case_types)]
|
||
|
#![allow(non_upper_case_globals)]
|
||
|
#![allow(non_snake_case)]
|
||
|
#![allow(improper_ctypes)]
|
||
|
#![allow(deref_nullptr)]
|
||
|
|
||
|
// -------------------------------------------------------------------------------------------------
|
||
|
// LINKING
|
||
|
// -------------------------------------------------------------------------------------------------
|
||
|
|
||
|
#[link(name = "mediagraph")]
|
||
|
extern "C" {}
|
||
|
|
||
|
use opencv::prelude::*;
|
||
|
use std::ffi::CString;
|
||
|
|
||
|
mod bindings;
|
||
|
|
||
|
pub use bindings::*;
|
||
|
|
||
|
impl Default for Landmark {
|
||
|
fn default() -> Self {
|
||
|
Self {
|
||
|
x: 0.0,
|
||
|
y: 0.0,
|
||
|
z: 0.0,
|
||
|
visibility: 0.0,
|
||
|
presence: 0.0,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Default for Pose {
|
||
|
fn default() -> Self {
|
||
|
Self {
|
||
|
data: [Landmark::default(); 33],
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Default for Hand {
|
||
|
fn default() -> Self {
|
||
|
Self {
|
||
|
data: [Landmark::default(); 21],
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Default for FaceMesh {
|
||
|
fn default() -> Self {
|
||
|
Self {
|
||
|
data: [Landmark::default(); 478],
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub mod pose {
|
||
|
use super::*;
|
||
|
|
||
|
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 {
|
||
|
pub mode: bool, // false
|
||
|
pub smooth: bool, // true,
|
||
|
pub detection_con: f32, // 0.5
|
||
|
pub track_con: f32, // 0.5
|
||
|
pub graph: PoseGraph,
|
||
|
}
|
||
|
|
||
|
impl PoseDetector {
|
||
|
pub fn new(mode: bool, smooth: bool, detection_con: f32, track_con: f32) -> Self {
|
||
|
let graph_config =
|
||
|
CString::new(include_str!("pose_tracking_cpu.txt")).expect("CString::new failed");
|
||
|
let output_node = CString::new("pose_landmarks").expect("CString::new failed");
|
||
|
|
||
|
let graph: PoseGraph =
|
||
|
unsafe { PoseGraph::new(graph_config.as_ptr(), output_node.as_ptr()) };
|
||
|
|
||
|
Self {
|
||
|
mode,
|
||
|
smooth,
|
||
|
detection_con,
|
||
|
track_con,
|
||
|
graph,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn process(&mut self, input: &Mat, pose: *mut Pose) -> bool {
|
||
|
unsafe {
|
||
|
let frame = input.as_raw() as *const cv_Mat;
|
||
|
self.graph.process(frame, pose)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// // draw true
|
||
|
// pub fn find_pose(&self, img: &[u8], draw: bool) {}
|
||
|
|
||
|
// // draw: true, bbox_with_hands: false
|
||
|
// pub fn find_position(&self, img: &[u8], draw: bool, bbox_with_hands: bool) {}
|
||
|
|
||
|
// // draw: true
|
||
|
// pub fn find_angle(
|
||
|
// &self,
|
||
|
// img: &[u8],
|
||
|
// p1: cgmath::Point2<f32>,
|
||
|
// p2: cgmath::Point2<f32>,
|
||
|
// draw: bool,
|
||
|
// ) {
|
||
|
// }
|
||
|
|
||
|
// pub fn find_distance(
|
||
|
// &self,
|
||
|
// p1: cgmath::Point2<f32>,
|
||
|
// p2: cgmath::Point2<f32>,
|
||
|
// img: Option<&[u8]>,
|
||
|
// r: f32,
|
||
|
// t: f32,
|
||
|
// ) {
|
||
|
// }
|
||
|
|
||
|
// pub fn anlge_check(&self, my_angle: f32, target_angle: f32, add_on: f32) {}
|
||
|
}
|
||
|
|
||
|
impl Default for PoseDetector {
|
||
|
fn default() -> Self {
|
||
|
Self::new(false, true, 0.5, 0.5)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub mod face_mesh {
|
||
|
use super::*;
|
||
|
|
||
|
pub struct FaceMeshDetector {
|
||
|
pub static_mode: bool, // false
|
||
|
pub max_faces: usize, // 2
|
||
|
pub min_detection_con: f32, // 0.5
|
||
|
pub min_track_con: f32, // 0.5
|
||
|
pub graph: FaceMeshGraph,
|
||
|
}
|
||
|
|
||
|
impl FaceMeshDetector {
|
||
|
pub fn new(
|
||
|
static_mode: bool,
|
||
|
max_faces: usize,
|
||
|
min_detection_con: f32,
|
||
|
min_track_con: f32,
|
||
|
) -> Self {
|
||
|
let graph_config = CString::new(include_str!("face_mesh_desktop_live.txt"))
|
||
|
.expect("CString::new failed");
|
||
|
let output_node = CString::new("multi_face_landmarks").expect("CString::new failed");
|
||
|
|
||
|
let graph: FaceMeshGraph =
|
||
|
unsafe { FaceMeshGraph::new(graph_config.as_ptr(), output_node.as_ptr()) };
|
||
|
Self {
|
||
|
static_mode,
|
||
|
max_faces,
|
||
|
min_detection_con,
|
||
|
min_track_con,
|
||
|
graph,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn process(&mut self, input: &Mat, mesh: *mut FaceMesh) -> bool {
|
||
|
unsafe {
|
||
|
let frame = input.as_raw() as *const cv_Mat;
|
||
|
self.graph.process(frame, mesh)
|
||
|
}
|
||
|
}
|
||
|
// // draw: true
|
||
|
// pub fn find_face_mesh(&self, img: &[u8], draw: bool) {}
|
||
|
|
||
|
// pub fn find_distance(
|
||
|
// &self,
|
||
|
// p1: cgmath::Point2<f32>,
|
||
|
// p2: cgmath::Point2<f32>,
|
||
|
// img: Option<&[u8]>,
|
||
|
// ) {
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
impl Default for FaceMeshDetector {
|
||
|
fn default() -> Self {
|
||
|
Self::new(false, 2, 0.5, 0.5)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// pub mod face_detection {
|
||
|
// pub enum FaceKeyPoint {
|
||
|
// RIGHT_EYE = 0,
|
||
|
// LEFT_EYE = 1,
|
||
|
// NOSE_TIP = 2,
|
||
|
// MOUTH_CENTER = 3,
|
||
|
// RIGHT_EAR_TRAGION = 4,
|
||
|
// LEFT_EAR_TRAGION = 5,
|
||
|
// }
|
||
|
// pub struct FaceDetection {}
|
||
|
|
||
|
// impl FaceDetection {
|
||
|
// pub fn process(&self /* image */) /*NamedTuple*/ {}
|
||
|
// }
|
||
|
|
||
|
// pub struct FaceDetector {
|
||
|
// pub min_detection_con: f32, // 0.5
|
||
|
// pub face_detection: FaceDetection,
|
||
|
// }
|
||
|
|
||
|
// impl FaceDetector {
|
||
|
// pub fn new(min_detection_con: f32) -> Self {
|
||
|
// Self {
|
||
|
// min_detection_con,
|
||
|
// face_detection: todo!(),
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
// // draw: true
|
||
|
// pub fn find_faces(&self, img: &[u8], draw: bool) {}
|
||
|
// }
|
||
|
|
||
|
// impl Default for FaceDetector {
|
||
|
// fn default() -> Self {
|
||
|
// Self::new(0.5)
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
pub mod hands {
|
||
|
use super::*;
|
||
|
// use mediapipe::*;
|
||
|
// use std::collections::HashMap;
|
||
|
|
||
|
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 {
|
||
|
pub mode: bool,
|
||
|
pub max_hands: usize,
|
||
|
pub detection_con: f32, // 0.5
|
||
|
pub min_track_con: f32, // 0.5
|
||
|
pub graph: HandsGraph,
|
||
|
}
|
||
|
|
||
|
impl HandDetector {
|
||
|
pub fn new(mode: bool, max_hands: usize, detection_con: f32, min_track_con: f32) -> Self {
|
||
|
// // ::std::vector<::mediapipe::NormalizedLandmarkList>
|
||
|
// let graph_config = CString::new(include_str!("face_mesh_desktop_live.txt")).expect("CString::new failed");
|
||
|
// let output_node = CString::new("multi_face_landmarks").expect("CString::new failed");
|
||
|
|
||
|
let graph_config = CString::new(include_str!("hand_tracking_desktop_live.txt"))
|
||
|
.expect("CString::new failed");
|
||
|
let output_node = CString::new("hand_landmarks").expect("CString::new failed");
|
||
|
|
||
|
let graph: HandsGraph =
|
||
|
unsafe { HandsGraph::new(graph_config.as_ptr(), output_node.as_ptr()) };
|
||
|
|
||
|
Self {
|
||
|
mode,
|
||
|
max_hands,
|
||
|
detection_con,
|
||
|
min_track_con,
|
||
|
graph,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn process(&mut self, input: &Mat, left: *mut Hand, right: *mut Hand) -> bool {
|
||
|
unsafe {
|
||
|
let frame = input.as_raw() as *const cv_Mat;
|
||
|
self.graph.process(frame, left, right)
|
||
|
}
|
||
|
}
|
||
|
// // draw: true, flip_type: tru
|
||
|
// pub fn find_hands(&self, img: &[u8], draw: bool, flip_type: bool) {}
|
||
|
|
||
|
// pub fn fingers_up(&self, my_hand: &HashMap<String, String>) /*List of which fingers are up*/
|
||
|
// {
|
||
|
// }
|
||
|
|
||
|
// pub fn find_distance(
|
||
|
// &self,
|
||
|
// p1: cgmath::Point2<f32>,
|
||
|
// p2: cgmath::Point2<f32>,
|
||
|
// img: Option<&[u8]>,
|
||
|
// ) {
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
impl Default for HandDetector {
|
||
|
fn default() -> Self {
|
||
|
Self::new(false, 2, 0.5, 0.5)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// pub mod objectron {
|
||
|
// pub struct Objectron {}
|
||
|
|
||
|
// impl Objectron {
|
||
|
// pub fn process(&self /* image */) /*NamedTuple*/ {}
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
// pub mod selfie_segmentation {
|
||
|
// pub struct SelfieSegmentation {}
|
||
|
|
||
|
// impl SelfieSegmentation {
|
||
|
// pub fn process(&self /* image */) /*NamedTuple*/ {}
|
||
|
// }
|
||
|
|
||
|
// pub struct SelfieSegmentationDetector {
|
||
|
// pub model: usize, // 0 is general 1 is landscape(faster)
|
||
|
// pub selfie_segmentation: SelfieSegmentation,
|
||
|
// }
|
||
|
|
||
|
// impl SelfieSegmentationDetector {
|
||
|
// pub fn new(model: usize) -> Self {
|
||
|
// todo!()
|
||
|
// }
|
||
|
|
||
|
// // threshold: 0.1
|
||
|
// pub fn remove_bg(&self, img: &[u8], img_bg: [u8; 3], threshold: f32) {}
|
||
|
// }
|
||
|
|
||
|
// impl Default for SelfieSegmentationDetector {
|
||
|
// fn default() -> Self {
|
||
|
// Self::new(1)
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
#[test]
|
||
|
fn it_works() {
|
||
|
let result = 2 + 2;
|
||
|
assert_eq!(result, 4);
|
||
|
}
|
||
|
}
|