@@ -1138,6 +1138,16 @@ struct clip_model_loader {
11381138 }
11391139 } break ;
11401140 case PROJECTOR_TYPE_INTERNVL :
1141+ {
1142+ // older version of internvl doesn't have min/max tiles, we need to provide default values for them to avoid issues
1143+ hparams.preproc_min_tiles = 1 ;
1144+ hparams.preproc_max_tiles = 12 ;
1145+ get_u32 (KEY_PROJ_SCALE_FACTOR , hparams.n_merge , false );
1146+ get_u32 (KEY_PREPROC_MIN_TILES , hparams.preproc_min_tiles , false );
1147+ get_u32 (KEY_PREPROC_MAX_TILES , hparams.preproc_max_tiles , false );
1148+ GGML_ASSERT (hparams.preproc_min_tiles <= hparams.preproc_max_tiles && hparams.preproc_max_tiles < INT32_MAX );
1149+ set_internvl_dhr_res_candidates (model);
1150+ } break ;
11411151 case PROJECTOR_TYPE_NEMOTRON_V2_VL :
11421152 {
11431153 get_u32 (KEY_PROJ_SCALE_FACTOR , hparams.n_merge , false );
@@ -2188,6 +2198,27 @@ struct clip_model_loader {
21882198 }
21892199 }
21902200 }
2201+
2202+ static void set_internvl_dhr_res_candidates (clip_model & model) {
2203+ auto & hparams = model.hparams ;
2204+ int min_num = hparams.preproc_min_tiles ;
2205+ int max_num = hparams.preproc_max_tiles ;
2206+ if (min_num < 1 ) {
2207+ return ; // avoid divide by 0
2208+ }
2209+ for (int a = min_num; a <= max_num; ++a) {
2210+ int b_lo = (min_num + a - 1 ) / a;
2211+ int b_hi = max_num / a;
2212+ b_lo = std::max (b_lo, min_num);
2213+ b_hi = std::min (b_hi, max_num);
2214+ for (int b = b_lo; b <= b_hi; ++b) {
2215+ hparams.image_res_candidates .push_back (clip_image_size {
2216+ a*hparams.image_size ,
2217+ b*hparams.image_size ,
2218+ });
2219+ }
2220+ }
2221+ }
21912222};
21922223
21932224struct clip_init_result clip_init (const char * fname, struct clip_context_params ctx_params) {
@@ -2734,17 +2765,22 @@ struct llava_uhd {
27342765 return res;
27352766 }
27362767
2737- static std::vector<clip_image_u8_ptr> slice_image (const clip_image_u8 * img, const slice_instructions & inst) {
2768+ static std::vector<clip_image_u8_ptr> slice_image (const clip_image_u8 * img, const slice_instructions & inst, bool overview_first = true ) {
27382769 std::vector<clip_image_u8_ptr> output;
27392770
27402771 // resize to overview size
27412772 clip_image_u8_ptr resized_img (clip_image_u8_init ());
27422773 img_tool::resize (*img, *resized_img, inst.overview_size , inst.interpolation_overview ,
27432774 inst.padding_overview , inst.pad_color_overview );
2744- output.push_back (std::move (resized_img));
2775+ if (overview_first) {
2776+ output.push_back (std::move (resized_img));
2777+ }
27452778
27462779 if (inst.slices .empty ()) {
27472780 // no slices, just return the resized image
2781+ if (!overview_first) {
2782+ output.push_back (std::move (resized_img));
2783+ }
27482784 return output;
27492785 }
27502786
@@ -2765,6 +2801,10 @@ struct llava_uhd {
27652801 output.push_back (std::move (img_slice));
27662802 }
27672803
2804+ if (!overview_first) {
2805+ output.push_back (std::move (resized_img));
2806+ }
2807+
27682808 return output;
27692809 }
27702810
@@ -3149,10 +3189,20 @@ bool clip_image_preprocess(struct clip_ctx * ctx, const clip_image_u8 * img, str
31493189 res_imgs->grid_x = instructions.grid_size .width ;
31503190 res_imgs->grid_y = instructions.grid_size .height ;
31513191 } break ;
3192+ case PROJECTOR_TYPE_INTERNVL : // support dynamic high-resolution
3193+ {
3194+ GGML_ASSERT (!params.image_res_candidates .empty ());
3195+ auto const inst = llava_uhd::get_slice_instructions (ctx, original_size);
3196+ std::vector<clip_image_u8_ptr> imgs = llava_uhd::slice_image (img, inst, false );
31523197
3198+ for (size_t i = 0 ; i < imgs.size (); ++i) {
3199+ clip_image_f32_ptr res (clip_image_f32_init ());
3200+ normalize_image_u8_to_f32 (*imgs[i], *res, params.image_mean , params.image_std );
3201+ res_imgs->entries .push_back (std::move (res));
3202+ }
3203+ } break ;
31533204 case PROJECTOR_TYPE_GLM_EDGE :
31543205 case PROJECTOR_TYPE_GEMMA3 :
3155- case PROJECTOR_TYPE_INTERNVL : // TODO @ngxson : support dynamic resolution
31563206 case PROJECTOR_TYPE_NEMOTRON_V2_VL :
31573207 {
31583208 clip_image_u8 resized_image;
0 commit comments