feat(gui): add face ROIs to comparison results and update image size
This commit is contained in:
@@ -76,6 +76,8 @@ pub enum ComparisonResult {
|
|||||||
Success {
|
Success {
|
||||||
image1_faces: usize,
|
image1_faces: usize,
|
||||||
image2_faces: usize,
|
image2_faces: usize,
|
||||||
|
image1_face_rois: Vec<ndarray::Array3<u8>>,
|
||||||
|
image2_face_rois: Vec<ndarray::Array3<u8>>,
|
||||||
best_similarity: f32,
|
best_similarity: f32,
|
||||||
processing_time: f64,
|
processing_time: f64,
|
||||||
},
|
},
|
||||||
@@ -765,6 +767,8 @@ impl FaceDetectorApp {
|
|||||||
ComparisonResult::Success {
|
ComparisonResult::Success {
|
||||||
image1_faces,
|
image1_faces,
|
||||||
image2_faces,
|
image2_faces,
|
||||||
|
image1_face_rois: _,
|
||||||
|
image2_face_rois: _,
|
||||||
best_similarity,
|
best_similarity,
|
||||||
processing_time,
|
processing_time,
|
||||||
} => {
|
} => {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use crate::facedet::{FaceDetectionConfig, FaceDetector, retinaface};
|
use crate::facedet::{FaceDetectionConfig, FaceDetector, retinaface};
|
||||||
use crate::faceembed::{FaceNetEmbedder, facenet};
|
use crate::faceembed::facenet;
|
||||||
use crate::gui::app::{ComparisonResult, DetectionResult, ExecutorType};
|
use crate::gui::app::{ComparisonResult, DetectionResult, ExecutorType};
|
||||||
use bounding_box::Aabb2;
|
use bounding_box::Aabb2;
|
||||||
use bounding_box::roi::MultiRoi as _;
|
use bounding_box::roi::MultiRoi as _;
|
||||||
@@ -70,11 +70,19 @@ impl FaceDetectionBridge {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok((image1_faces, image2_faces, best_similarity)) => {
|
Ok((
|
||||||
|
image1_faces,
|
||||||
|
image2_faces,
|
||||||
|
image1_face_rois,
|
||||||
|
image2_face_rois,
|
||||||
|
best_similarity,
|
||||||
|
)) => {
|
||||||
let processing_time = start_time.elapsed().as_secs_f64();
|
let processing_time = start_time.elapsed().as_secs_f64();
|
||||||
ComparisonResult::Success {
|
ComparisonResult::Success {
|
||||||
image1_faces,
|
image1_faces,
|
||||||
image2_faces,
|
image2_faces,
|
||||||
|
image1_face_rois,
|
||||||
|
image2_face_rois,
|
||||||
best_similarity,
|
best_similarity,
|
||||||
processing_time,
|
processing_time,
|
||||||
}
|
}
|
||||||
@@ -180,53 +188,75 @@ impl FaceDetectionBridge {
|
|||||||
threshold: f32,
|
threshold: f32,
|
||||||
nms_threshold: f32,
|
nms_threshold: f32,
|
||||||
executor_type: ExecutorType,
|
executor_type: ExecutorType,
|
||||||
) -> Result<(usize, usize, f32), Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<
|
||||||
|
(usize, usize, Vec<Array3<u8>>, Vec<Array3<u8>>, f32),
|
||||||
|
Box<dyn std::error::Error + Send + Sync>,
|
||||||
|
> {
|
||||||
// Create detector and embedder, detect faces and generate embeddings
|
// Create detector and embedder, detect faces and generate embeddings
|
||||||
let (faces1, faces2, best_similarity) = match executor_type {
|
let (image1_faces, image2_faces, image1_rois, image2_rois, best_similarity) =
|
||||||
ExecutorType::MnnCpu | ExecutorType::MnnMetal | ExecutorType::MnnCoreML => {
|
match executor_type {
|
||||||
let forward_type = match executor_type {
|
ExecutorType::MnnCpu | ExecutorType::MnnMetal | ExecutorType::MnnCoreML => {
|
||||||
ExecutorType::MnnCpu => mnn::ForwardType::CPU,
|
let forward_type = match executor_type {
|
||||||
ExecutorType::MnnMetal => mnn::ForwardType::Metal,
|
ExecutorType::MnnCpu => mnn::ForwardType::CPU,
|
||||||
ExecutorType::MnnCoreML => mnn::ForwardType::CoreML,
|
ExecutorType::MnnMetal => mnn::ForwardType::Metal,
|
||||||
_ => unreachable!(),
|
ExecutorType::MnnCoreML => mnn::ForwardType::CoreML,
|
||||||
};
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut detector = retinaface::mnn::FaceDetection::builder(RETINAFACE_MODEL_MNN)
|
let mut detector =
|
||||||
.map_err(|e| format!("Failed to create MNN detector: {}", e))?
|
retinaface::mnn::FaceDetection::builder(RETINAFACE_MODEL_MNN)
|
||||||
.with_forward_type(forward_type.clone())
|
.map_err(|e| format!("Failed to create MNN detector: {}", e))?
|
||||||
.build()
|
.with_forward_type(forward_type.clone())
|
||||||
.map_err(|e| format!("Failed to build MNN detector: {}", e))?;
|
.build()
|
||||||
|
.map_err(|e| format!("Failed to build MNN detector: {}", e))?;
|
||||||
|
|
||||||
let mut embedder = facenet::mnn::EmbeddingGenerator::builder(FACENET_MODEL_MNN)
|
let mut embedder = facenet::mnn::EmbeddingGenerator::builder(FACENET_MODEL_MNN)
|
||||||
.map_err(|e| format!("Failed to create MNN embedder: {}", e))?
|
.map_err(|e| format!("Failed to create MNN embedder: {}", e))?
|
||||||
.with_forward_type(forward_type)
|
.with_forward_type(forward_type)
|
||||||
.build()
|
.build()
|
||||||
.map_err(|e| format!("Failed to build MNN embedder: {}", e))?;
|
.map_err(|e| format!("Failed to build MNN embedder: {}", e))?;
|
||||||
|
|
||||||
let img_1 = run_detection(
|
let img_1 = run_detection(
|
||||||
image1_path,
|
image1_path,
|
||||||
&mut detector,
|
&mut detector,
|
||||||
&mut embedder,
|
&mut embedder,
|
||||||
threshold,
|
threshold,
|
||||||
nms_threshold,
|
nms_threshold,
|
||||||
2,
|
2,
|
||||||
)?;
|
)?;
|
||||||
let img_2 = run_detection(
|
let img_2 = run_detection(
|
||||||
image2_path,
|
image2_path,
|
||||||
&mut detector,
|
&mut detector,
|
||||||
&mut embedder,
|
&mut embedder,
|
||||||
threshold,
|
threshold,
|
||||||
nms_threshold,
|
nms_threshold,
|
||||||
2,
|
2,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let best_similarity = compare_faces(&img_1.embeddings, &img_2.embeddings)?;
|
let image1_rois = img_1.rois;
|
||||||
(img_1, img_2, best_similarity)
|
let image2_rois = img_2.rois;
|
||||||
}
|
let image1_bbox_len = img_1.bbox.len();
|
||||||
ExecutorType::OnnxCpu => unimplemented!(),
|
let image2_bbox_len = img_2.bbox.len();
|
||||||
};
|
let best_similarity = compare_faces(&img_1.embeddings, &img_2.embeddings)?;
|
||||||
|
|
||||||
Ok((faces1.bbox.len(), faces2.bbox.len(), best_similarity))
|
(
|
||||||
|
image1_bbox_len,
|
||||||
|
image2_bbox_len,
|
||||||
|
image1_rois,
|
||||||
|
image2_rois,
|
||||||
|
best_similarity,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ExecutorType::OnnxCpu => unimplemented!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
image1_faces,
|
||||||
|
image2_faces,
|
||||||
|
image1_rois,
|
||||||
|
image2_rois,
|
||||||
|
best_similarity,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +338,7 @@ where
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|roi| {
|
.map(|roi| {
|
||||||
roi.as_standard_layout()
|
roi.as_standard_layout()
|
||||||
.fast_resize(320, 320, &ResizeOptions::default())
|
.fast_resize(224, 224, &ResizeOptions::default())
|
||||||
.change_context(Error)
|
.change_context(Error)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
@@ -322,7 +352,7 @@ where
|
|||||||
let og_size = chunk.len();
|
let og_size = chunk.len();
|
||||||
if chunk.len() < chunk_size {
|
if chunk.len() < chunk_size {
|
||||||
tracing::warn!("Chunk size is less than 8, padding with zeros");
|
tracing::warn!("Chunk size is less than 8, padding with zeros");
|
||||||
let zeros = Array3::zeros((320, 320, 3));
|
let zeros = Array3::zeros((224, 224, 3));
|
||||||
let chunk: Vec<_> = chunk
|
let chunk: Vec<_> = chunk
|
||||||
.iter()
|
.iter()
|
||||||
.map(|arr| arr.reborrow())
|
.map(|arr| arr.reborrow())
|
||||||
|
|||||||
Reference in New Issue
Block a user