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

Method preprocess_image

src/common/AutoModel/modeling_qwen3vl_image.cpp:161–245  ·  view source on GitHub ↗

@brief: preprocess the image for Qwen3VL 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 Qwen3VL::preprocess_image(qwen3vl_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 smart_resize(
169 height, width,
170 resized_height, resized_width,
171 QWEN3_PATCH_SIZE * QWEN3_IMAGE_MERGE_SIZE,
172 QWEN3_SHORTEST_EDGE,
173 QWEN3_LONGEST_EDGE
174 );
175 // std::cout << "resized_height "<< resized_height << " resized_width " << resized_width <<std::endl;
176
177 // Cache size calculations for efficiency
178 const uint32_t single_frame_size = resized_height * resized_width * channels;
179 const uint32_t total_patch_size = single_frame_size * QWEN3_TEMPORAL_PATCH_SIZE;
180 const uint32_t grid_h = resized_height / QWEN3_PATCH_SIZE;
181 const uint32_t grid_w = resized_width / QWEN3_PATCH_SIZE;
182
183 // Pre-allocate final buffer to avoid reallocation
184 const uint32_t prev_pixel_values_size = pixel_values.size();
185 pixel_values.resize(prev_pixel_values_size + total_patch_size);
186
187 // Use non-optimized path for consistent results across platforms
188 auto resize_image = imgproc::avx512::resize_bicubic_antialias_rgb_planar_avx512(
189 image._data.data(), width, height, resized_width, resized_height, true
190 );
191
192 // Reuse scratch buffer across calls to avoid repeated allocations
193 static thread_local std::vector<float> patch_vector_scratch;
194 if (patch_vector_scratch.size() < total_patch_size) {
195 patch_vector_scratch.resize(total_patch_size);
196 }
197
198 // Apply rescale and normalization to first frame
199 imgproc::avx512::rescale_and_normalize_avx512(
200 resize_image.data(), patch_vector_scratch.data(),
201 resized_width, resized_height, channels,
202 true, QWEN3_VISION_RESCALE_FACTOR,
203 true, QWEN3_VISION_RESCALE_IMAGE_MEAN, QWEN3_VISION_RESCALE_IMAGE_STD
204 );
205
206 // Replicate first frame for temporal patches (optimized for QWEN3_TEMPORAL_PATCH_SIZE = 2)
207 // This is more efficient than a loop for the common case
208 if constexpr (QWEN3_TEMPORAL_PATCH_SIZE == 2) {
209 memcpy(
210 patch_vector_scratch.data() + single_frame_size,
211 patch_vector_scratch.data(),
212 single_frame_size * sizeof(float)
213 );
214 } else {
215 // Generic loop for other TEMPORAL_PATCH_SIZE values
216 for(unsigned l = 1; l < QWEN3_TEMPORAL_PATCH_SIZE; l++){
217 memcpy(
218 patch_vector_scratch.data() + l * single_frame_size,

Callers

nothing calls this directly

Calls 7

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

Tested by

no test coverage detected