MCPcopy Create free account
hub / github.com/FastFlowLM/FastFlowLM / preprocess_image

Method preprocess_image

src/common/AutoModel/modeling_qwen3_5vl_image.cpp:161–248  ·  view source on GitHub ↗

@brief: preprocess the image for Qwen3_5VL model @note: Converts uint8 image to BF16 format, data is already in (3, H, W) CHW layout @param: image: the image to preprocess (already in CHW format) @return: the preprocessed image in BF16 format

Source from the content-addressed store, hash-verified

159///@param: image: the image to preprocess (already in CHW format)
160///@return: the preprocessed image in BF16 format
161void Qwen3_5VL::preprocess_image(qwen3_5vl_image_t& image, std::vector<bf16> &pixel_values) {
162 const int width = image.width;
163 const int height = image.height;
164 const int channels = 3; // RGB
165 int resized_height;
166 int resized_width;
167 // do the automatically resizing in here
168
169 qwen3_5vl_npu* lm_engine_qwen3_5_ptr = reinterpret_cast<qwen3_5vl_npu*>(this->lm_engine.get());
170 smart_resize(
171 height, width,
172 resized_height, resized_width,
173
174 lm_engine_qwen3_5_ptr->QWEN3_5_PATCH_SIZE * lm_engine_qwen3_5_ptr->QWEN3_5_IMAGE_MERGE_SIZE,
175 lm_engine_qwen3_5_ptr->QWEN3_5_SHORTEST_EDGE,
176 lm_engine_qwen3_5_ptr->QWEN3_5_LONGEST_EDGE
177 );
178 // std::cout << "resized_height "<< resized_height << " resized_width " << resized_width <<std::endl;
179
180 // Cache size calculations for efficiency
181 const uint32_t single_frame_size = resized_height * resized_width * channels;
182 const uint32_t total_patch_size = single_frame_size * lm_engine_qwen3_5_ptr->QWEN3_5_TEMPORAL_PATCH_SIZE;
183 const uint32_t grid_h = resized_height / lm_engine_qwen3_5_ptr->QWEN3_5_PATCH_SIZE;
184 const uint32_t grid_w = resized_width / lm_engine_qwen3_5_ptr->QWEN3_5_PATCH_SIZE;
185
186 // Pre-allocate final buffer to avoid reallocation
187 const uint32_t prev_pixel_values_size = pixel_values.size();
188 pixel_values.resize(prev_pixel_values_size + total_patch_size);
189
190 // Use non-optimized path for consistent results across platforms
191 auto resize_image = imgproc::avx512::resize_bicubic_antialias_rgb_planar_avx512(
192 image._data.data(), width, height, resized_width, resized_height, true
193 );
194
195 // Reuse scratch buffer across calls to avoid repeated allocations
196 static thread_local std::vector<float> patch_vector_scratch;
197 if (patch_vector_scratch.size() < total_patch_size) {
198 patch_vector_scratch.resize(total_patch_size);
199 }
200
201 // Apply rescale and normalization to first frame
202 imgproc::avx512::rescale_and_normalize_avx512(
203 resize_image.data(), patch_vector_scratch.data(),
204 resized_width, resized_height, channels,
205 true, lm_engine_qwen3_5_ptr->QWEN3_5_VISION_RESCALE_FACTOR,
206 true, lm_engine_qwen3_5_ptr->QWEN3_5_VISION_RESCALE_IMAGE_MEAN, lm_engine_qwen3_5_ptr->QWEN3_5_VISION_RESCALE_IMAGE_STD
207 );
208
209 // Replicate first frame for temporal patches (optimized for QWEN3_5_TEMPORAL_PATCH_SIZE = 2)
210 // This is more efficient than a loop for the common case
211 if (lm_engine_qwen3_5_ptr->QWEN3_5_TEMPORAL_PATCH_SIZE == 2) {
212 memcpy(
213 patch_vector_scratch.data() + single_frame_size,
214 patch_vector_scratch.data(),
215 single_frame_size * sizeof(float)
216 );
217 } else {
218 // Generic loop for other TEMPORAL_PATCH_SIZE values

Callers

nothing calls this directly

Calls 8

reorder_patches_inplaceFunction · 0.85
freeMethod · 0.80
getMethod · 0.45
sizeMethod · 0.45
resizeMethod · 0.45
dataMethod · 0.45

Tested by

no test coverage detected