@@ -61,7 +61,6 @@ use ahnlich_types::db::query::DropPredIndex as DbDropPredIndex;
6161use ahnlich_types:: db:: query:: GetPred as DbGetPred ;
6262use ahnlich_types:: db:: query:: GetSimN as DbGetSimN ;
6363use ahnlich_types:: db:: server:: Set as DbSet ;
64- use ahnlich_types:: keyval;
6564use ahnlich_types:: keyval:: StoreName ;
6665use ahnlich_types:: keyval:: StoreValue ;
6766use ahnlich_types:: metadata:: MetadataValue ;
@@ -95,6 +94,28 @@ use utils::server::ServerUtilsConfig;
9594
9695use ahnlich_client_rs:: db:: DbClient ;
9796
97+ /// Extract original image dimensions from store inputs and inject into model_params.
98+ /// This allows face detection models (Buffalo-L, SFace-Yunet) to normalize bounding boxes
99+ /// correctly by accounting for letterboxing and aspect ratio transformations.
100+ ///
101+ /// For each image input, adds `orig_width_{idx}` and `orig_height_{idx}` to model_params.
102+ fn extract_and_inject_image_dimensions (
103+ inputs : & [ ahnlich_types:: keyval:: StoreInput ] ,
104+ model_params : & mut std:: collections:: HashMap < String , String > ,
105+ ) {
106+ for ( idx, store_input) in inputs. iter ( ) . enumerate ( ) {
107+ if let Some ( ahnlich_types:: keyval:: store_input:: Value :: Image ( image_bytes) ) =
108+ & store_input. value
109+ && let Ok ( img_array) =
110+ crate :: engine:: ai:: models:: ImageArray :: try_from ( image_bytes. as_slice ( ) )
111+ {
112+ let ( width, height) = img_array. dimensions ( ) ;
113+ model_params. insert ( format ! ( "orig_width_{}" , idx) , width. to_string ( ) ) ;
114+ model_params. insert ( format ! ( "orig_height_{}" , idx) , height. to_string ( ) ) ;
115+ }
116+ }
117+ }
118+
98119const SERVICE_NAME : & str = "ahnlich-ai" ;
99120
100121#[ derive( Debug ) ]
@@ -399,7 +420,10 @@ impl AiService for AIProxyServer {
399420 let search_input = params
400421 . search_input
401422 . ok_or_else ( || AIProxyError :: InputNotSpecified ( "Search" . to_string ( ) ) ) ?;
402- let model_params = params. model_params ;
423+ let mut model_params = params. model_params ;
424+
425+ // Extract image dimensions for face detection models to properly normalize bboxes
426+ extract_and_inject_image_dimensions ( std:: slice:: from_ref ( & search_input) , & mut model_params) ;
403427 let search_input = self
404428 . store_handler
405429 . get_ndarray_repr_for_store (
@@ -462,7 +486,16 @@ impl AiService for AIProxyServer {
462486 ) -> Result < tonic:: Response < server:: Set > , tonic:: Status > {
463487 let params = request. into_inner ( ) ;
464488 let model_manager = & self . model_manager ;
465- let model_params = params. model_params ;
489+ let mut model_params = params. model_params ;
490+
491+ // Extract image dimensions for face detection models to properly normalize bboxes
492+ let store_inputs: Vec < _ > = params
493+ . inputs
494+ . iter ( )
495+ . filter_map ( |input| input. key . clone ( ) )
496+ . collect ( ) ;
497+ extract_and_inject_image_dimensions ( & store_inputs, & mut model_params) ;
498+
466499 let parent_id = tracer:: span_to_trace_parent ( tracing:: Span :: current ( ) ) ;
467500 let ( db_inputs, delete_hashset) = self
468501 . store_handler
@@ -801,29 +834,8 @@ impl AiService for AIProxyServer {
801834 let input_len = inputs. len ( ) ;
802835 let mut model_params = params. model_params ;
803836
804- // Extract original image dimensions and inject into model_params
805- // This allows face detection models (Buffalo-L, SFace) to normalize
806- // bounding boxes correctly accounting for aspect ratio
807- for ( idx, store_input) in inputs. iter ( ) . enumerate ( ) {
808- if let Some ( keyval:: store_input:: Value :: Image ( image_bytes) ) = & store_input. value {
809- // Try to decode image and get dimensions
810- if let Ok ( img_array) =
811- crate :: engine:: ai:: models:: ImageArray :: try_from ( image_bytes. as_slice ( ) )
812- {
813- let ( width, height) = img_array. dimensions ( ) ;
814- tracing:: info!(
815- "📐 Captured original dimensions for image {}: {}x{}" ,
816- idx,
817- width,
818- height
819- ) ;
820- model_params. insert ( format ! ( "orig_width_{}" , idx) , width. to_string ( ) ) ;
821- model_params. insert ( format ! ( "orig_height_{}" , idx) , height. to_string ( ) ) ;
822- } else {
823- tracing:: warn!( "❌ Failed to decode image {} for dimension extraction" , idx) ;
824- }
825- }
826- }
837+ // Extract image dimensions for face detection models to properly normalize bboxes
838+ extract_and_inject_image_dimensions ( & inputs, & mut model_params) ;
827839
828840 let store_keys = ModelManager :: handle_request (
829841 & self . model_manager ,
0 commit comments