@@ -95,6 +95,30 @@ use utils::server::ServerUtilsConfig;
9595
9696use ahnlich_client_rs:: db:: DbClient ;
9797
98+ /// Extract original image dimensions from store inputs and inject into model_params.
99+ /// This allows face detection models (Buffalo-L, SFace-Yunet) to normalize bounding boxes
100+ /// correctly by accounting for letterboxing and aspect ratio transformations.
101+ ///
102+ /// For each image input, adds `orig_width_{idx}` and `orig_height_{idx}` to model_params.
103+ fn extract_and_inject_image_dimensions (
104+ inputs : & [ ahnlich_types:: keyval:: StoreInput ] ,
105+ model_params : & mut std:: collections:: HashMap < String , String > ,
106+ ) {
107+ for ( idx, store_input) in inputs. iter ( ) . enumerate ( ) {
108+ if let Some ( ahnlich_types:: keyval:: store_input:: Value :: Image ( image_bytes) ) =
109+ & store_input. value
110+ {
111+ if let Ok ( img_array) =
112+ crate :: engine:: ai:: models:: ImageArray :: try_from ( image_bytes. as_slice ( ) )
113+ {
114+ let ( width, height) = img_array. dimensions ( ) ;
115+ model_params. insert ( format ! ( "orig_width_{}" , idx) , width. to_string ( ) ) ;
116+ model_params. insert ( format ! ( "orig_height_{}" , idx) , height. to_string ( ) ) ;
117+ }
118+ }
119+ }
120+ }
121+
98122const SERVICE_NAME : & str = "ahnlich-ai" ;
99123
100124#[ derive( Debug ) ]
@@ -399,7 +423,10 @@ impl AiService for AIProxyServer {
399423 let search_input = params
400424 . search_input
401425 . ok_or_else ( || AIProxyError :: InputNotSpecified ( "Search" . to_string ( ) ) ) ?;
402- let model_params = params. model_params ;
426+ let mut model_params = params. model_params ;
427+
428+ // Extract image dimensions for face detection models to properly normalize bboxes
429+ extract_and_inject_image_dimensions ( std:: slice:: from_ref ( & search_input) , & mut model_params) ;
403430 let search_input = self
404431 . store_handler
405432 . get_ndarray_repr_for_store (
@@ -462,7 +489,16 @@ impl AiService for AIProxyServer {
462489 ) -> Result < tonic:: Response < server:: Set > , tonic:: Status > {
463490 let params = request. into_inner ( ) ;
464491 let model_manager = & self . model_manager ;
465- let model_params = params. model_params ;
492+ let mut model_params = params. model_params ;
493+
494+ // Extract image dimensions for face detection models to properly normalize bboxes
495+ let store_inputs: Vec < _ > = params
496+ . inputs
497+ . iter ( )
498+ . filter_map ( |input| input. key . clone ( ) )
499+ . collect ( ) ;
500+ extract_and_inject_image_dimensions ( & store_inputs, & mut model_params) ;
501+
466502 let parent_id = tracer:: span_to_trace_parent ( tracing:: Span :: current ( ) ) ;
467503 let ( db_inputs, delete_hashset) = self
468504 . store_handler
@@ -801,29 +837,8 @@ impl AiService for AIProxyServer {
801837 let input_len = inputs. len ( ) ;
802838 let mut model_params = params. model_params ;
803839
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- }
840+ // Extract image dimensions for face detection models to properly normalize bboxes
841+ extract_and_inject_image_dimensions ( & inputs, & mut model_params) ;
827842
828843 let store_keys = ModelManager :: handle_request (
829844 & self . model_manager ,
0 commit comments