returns the normalized float tensor for llava-1.5, for spatial_unpad with anyres processing for llava-1.6 it returns the normalized image patch tensors as a vector res_imgs memory is being allocated here, previous allocations will be freed if found
| 2810 | // returns the normalized float tensor for llava-1.5, for spatial_unpad with anyres processing for llava-1.6 it returns the normalized image patch tensors as a vector |
| 2811 | // res_imgs memory is being allocated here, previous allocations will be freed if found |
| 2812 | bool clip_image_preprocess(struct clip_ctx * ctx, const clip_image_u8 * img, struct clip_image_f32_batch * res_imgs) { |
| 2813 | clip_image_size original_size{img->nx, img->ny}; |
| 2814 | auto & params = ctx->model.hparams; |
| 2815 | |
| 2816 | switch (ctx->proj_type()) { |
| 2817 | case PROJECTOR_TYPE_MINICPMV: |
| 2818 | { |
| 2819 | auto const inst = llava_uhd::get_slice_instructions(ctx, original_size); |
| 2820 | std::vector<clip_image_u8_ptr> imgs = llava_uhd::slice_image(img, inst); |
| 2821 | |
| 2822 | for (size_t i = 0; i < imgs.size(); ++i) { |
| 2823 | // clip_image_save_to_bmp(*imgs[i], "slice_" + std::to_string(i) + ".bmp"); |
| 2824 | clip_image_f32_ptr res(clip_image_f32_init()); |
| 2825 | normalize_image_u8_to_f32(*imgs[i], *res, params.image_mean, params.image_std); |
| 2826 | res_imgs->entries.push_back(std::move(res)); |
| 2827 | } |
| 2828 | |
| 2829 | res_imgs->grid_x = inst.grid_size.width; |
| 2830 | res_imgs->grid_y = inst.grid_size.height; |
| 2831 | } break; |
| 2832 | |
| 2833 | case PROJECTOR_TYPE_QWEN2VL: |
| 2834 | case PROJECTOR_TYPE_QWEN25VL: |
| 2835 | case PROJECTOR_TYPE_QWEN3VL: |
| 2836 | case PROJECTOR_TYPE_GLM4V: |
| 2837 | { |
| 2838 | GGML_ASSERT(params.image_min_pixels > 0 && params.image_max_pixels > 0); |
| 2839 | clip_image_u8 resized; |
| 2840 | const clip_image_size new_size = img_tool::calc_size_preserved_ratio( |
| 2841 | original_size, |
| 2842 | params.patch_size * 2, |
| 2843 | params.image_min_pixels, |
| 2844 | params.image_max_pixels); |
| 2845 | img_tool::resize(*img, resized, new_size, img_tool::RESIZE_ALGO_BILINEAR, false); |
| 2846 | // clip_image_save_to_bmp(resized, "preproc.bmp"); |
| 2847 | clip_image_f32_ptr img_f32(clip_image_f32_init()); |
| 2848 | // clip_image_f32_ptr res(clip_image_f32_init()); |
| 2849 | normalize_image_u8_to_f32(resized, *img_f32, params.image_mean, params.image_std); |
| 2850 | // res_imgs->data[0] = *res; |
| 2851 | res_imgs->entries.push_back(std::move(img_f32)); |
| 2852 | } break; |
| 2853 | case PROJECTOR_TYPE_YOUTUVL: |
| 2854 | { |
| 2855 | const int patch_size = params.patch_size; // typically 16 |
| 2856 | const int merge_size = params.n_merge; // typically 2 |
| 2857 | const int align_size = patch_size * merge_size; // 32 |
| 2858 | |
| 2859 | const int max_num_patches = params.image_max_pixels > 0 ? |
| 2860 | params.image_max_pixels / (patch_size * patch_size) : 256; |
| 2861 | |
| 2862 | // Linear search for optimal scale to fit within max_num_patches |
| 2863 | float scale = 1.0f; |
| 2864 | int target_height = original_size.height; |
| 2865 | int target_width = original_size.width; |
| 2866 | |
| 2867 | auto get_scaled_image_size = [align_size](float scale, int size) -> int { |
| 2868 | float scaled_size = size * scale; |
| 2869 | // Round up to nearest multiple of align_size |
no test coverage detected