-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from vinlemon/feat-face-landmark
Add face landmark task
- Loading branch information
Showing
14 changed files
with
3,797 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
fn parse_args() -> Result<(String, String, Option<String>), Box<dyn std::error::Error>> { | ||
let args: Vec<String> = std::env::args().collect(); | ||
if args.len() != 3 && args.len() != 4 { | ||
return Err(format!( | ||
"Usage {} model_path image_path [output image path]", | ||
args[0] | ||
) | ||
.into()); | ||
} | ||
Ok((args[1].clone(), args[2].clone(), args.get(3).cloned())) | ||
} | ||
|
||
use mediapipe_rs::tasks::vision::FaceLandmarkerBuilder; | ||
use mediapipe_rs::postprocess::utils::DrawLandmarksOptions; | ||
use mediapipe_rs::tasks::vision::FaceLandmarkConnections; | ||
|
||
fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
let (model_path, img_path, output_path) = parse_args()?; | ||
|
||
let mut input_img = image::open(img_path)?; | ||
let face_landmark_results = FaceLandmarkerBuilder::new() | ||
.num_faces(1) // set max number of faces to detect | ||
.min_face_detection_confidence(0.5) | ||
.min_face_presence_confidence(0.5) | ||
.min_tracking_confidence(0.5) | ||
.output_face_blendshapes(true) | ||
.build_from_file(model_path)? // create a face landmarker | ||
.detect(&input_img)?; // do inference and generate results | ||
|
||
// show formatted result message | ||
println!("{}", face_landmark_results); | ||
|
||
if let Some(output_path) = output_path { | ||
// draw face landmarks result to image | ||
let options = DrawLandmarksOptions::default() | ||
.connections(FaceLandmarkConnections::get_connections( | ||
&FaceLandmarkConnections::FacemeshTesselation, | ||
)) | ||
.landmark_radius_percent(0.003); | ||
|
||
for result in face_landmark_results.iter() { | ||
result.draw_with_options(&mut input_img, &options); | ||
} | ||
// save output image | ||
input_img.save(output_path)?; | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
#[derive(Clone)] | ||
pub(crate) struct FaceLandmarkOptions { | ||
/// The maximum number of faces can be detected by the FaceLandmarker. | ||
pub num_faces: i32, | ||
|
||
/// The minimum confidence score for the face detection to be considered successful. | ||
pub min_face_detection_confidence: f32, | ||
|
||
/// The minimum confidence score of face presence score in the face landmark detection. | ||
pub min_face_presence_confidence: f32, | ||
|
||
/// The minimum confidence score for the face tracking to be considered successful. | ||
pub min_tracking_confidence: f32, | ||
|
||
/// Whether Face Landmarker outputs face blendshapes. | ||
/// Face blendshapes are used for rendering the 3D face model. | ||
pub output_face_blendshapes: bool, | ||
|
||
/// Whether FaceLandmarker outputs the facial transformation matrix. | ||
/// FaceLandmarker uses the matrix to transform the face landmarks from a canonical face model | ||
/// to the detected face, so users can apply effects on the detected landmarks. | ||
pub output_facial_transformation_matrixes: bool, | ||
} | ||
|
||
impl Default for FaceLandmarkOptions { | ||
#[inline(always)] | ||
fn default() -> Self { | ||
Self { | ||
num_faces: 1, | ||
min_face_detection_confidence: 0.5, | ||
min_face_presence_confidence: 0.5, | ||
min_tracking_confidence: 0.5, | ||
output_face_blendshapes: false, | ||
output_facial_transformation_matrixes: false, | ||
} | ||
} | ||
} | ||
|
||
macro_rules! face_landmark_options_impl { | ||
() => { | ||
/// Set the maximum number of faces can be detected by the FaceLandmarker. | ||
#[inline(always)] | ||
pub fn num_faces(mut self, num_faces: i32) -> Self { | ||
self.face_landmark_options.num_faces = num_faces; | ||
self | ||
} | ||
|
||
/// Set the minimum confidence score for the face detection to be considered successful. | ||
#[inline(always)] | ||
pub fn min_face_detection_confidence(mut self, min_face_detection_confidence: f32) -> Self { | ||
self.face_landmark_options.min_face_detection_confidence = | ||
min_face_detection_confidence; | ||
self | ||
} | ||
|
||
/// Set the minimum confidence score of face presence score in the face landmark detection. | ||
#[inline(always)] | ||
pub fn min_face_presence_confidence(mut self, min_face_presence_confidence: f32) -> Self { | ||
self.face_landmark_options.min_face_presence_confidence = min_face_presence_confidence; | ||
self | ||
} | ||
|
||
/// Set the minimum confidence score for the face tracking to be considered successful. | ||
#[inline(always)] | ||
pub fn min_tracking_confidence(mut self, min_tracking_confidence: f32) -> Self { | ||
self.face_landmark_options.min_tracking_confidence = min_tracking_confidence; | ||
self | ||
} | ||
|
||
/// Set whether FaceLandmarker outputs face blendshapes. | ||
pub fn output_face_blendshapes(mut self, output_face_blendshapes: bool) -> Self { | ||
self.face_landmark_options.output_face_blendshapes = output_face_blendshapes; | ||
self | ||
} | ||
|
||
/// Set whether FaceLandmarker outputs the facial transformation matrix. | ||
pub fn output_facial_transformation_matrixes( | ||
mut self, | ||
output_facial_transformation_matrixes: bool, | ||
) -> Self { | ||
self.face_landmark_options.output_facial_transformation_matrixes = | ||
output_facial_transformation_matrixes; | ||
self | ||
} | ||
}; | ||
} | ||
|
||
macro_rules! face_landmark_options_check { | ||
( $self:ident ) => {{ | ||
if $self.face_landmark_options.num_faces == 0 { | ||
return Err(crate::Error::ArgumentError( | ||
"The number of max faces cannot be zero".into(), | ||
)); | ||
} | ||
if $self.face_landmark_options.min_face_presence_confidence < 0. | ||
|| $self.face_landmark_options.min_face_presence_confidence > 1. | ||
{ | ||
return Err(crate::Error::ArgumentError(format!( | ||
"The min_face_presence_confidence must in range [0.0, 1.0], but got `{}`", | ||
$self.face_landmark_options.min_face_presence_confidence | ||
))); | ||
} | ||
if $self.face_landmark_options.min_face_detection_confidence < 0. | ||
|| $self.face_landmark_options.min_face_detection_confidence > 1. | ||
{ | ||
return Err(crate::Error::ArgumentError(format!( | ||
"The min_face_detection_confidence must in range [0.0, 1.0], but got `{}`", | ||
$self.face_landmark_options.min_face_detection_confidence | ||
))); | ||
} | ||
}}; | ||
} | ||
|
||
macro_rules! face_landmark_options_get_impl { | ||
() => { | ||
/// Get the maximum number of faces can be detected by the FaceLandmarker. | ||
#[inline(always)] | ||
pub fn num_faces(&self) -> i32 { | ||
self.build_options.face_landmark_options.num_faces | ||
} | ||
|
||
/// Get the minimum confidence score for the face detection to be considered successful. | ||
#[inline(always)] | ||
pub fn min_face_detection_confidence(&self) -> f32 { | ||
self.build_options | ||
.face_landmark_options | ||
.min_face_detection_confidence | ||
} | ||
|
||
/// Get the minimum confidence score of face presence score in the face landmark detection. | ||
#[inline(always)] | ||
pub fn min_face_presence_confidence(&self) -> f32 { | ||
self.build_options | ||
.face_landmark_options | ||
.min_face_presence_confidence | ||
} | ||
|
||
/// Get the minimum confidence score for the face tracking to be considered successful. | ||
#[inline(always)] | ||
pub fn min_tracking_confidence(&self) -> f32 { | ||
self.build_options | ||
.face_landmark_options | ||
.min_tracking_confidence | ||
} | ||
|
||
/// Get whether FaceLandmarker outputs face blendshapes. | ||
pub fn output_face_blendshapes(&self) -> bool { | ||
self.build_options.face_landmark_options.output_face_blendshapes | ||
} | ||
|
||
/// Get whether FaceLandmarker outputs the facial transformation matrix. | ||
pub fn output_facial_transformation_matrixes(&self) -> bool { | ||
self.build_options | ||
.face_landmark_options | ||
.output_facial_transformation_matrixes | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.