@brief: preprocess the image for gemma3 model @note: 1. Reorder: 896x896x3 -> 3x896x896 @param: image: the image to preprocess @return: the preprocessed image
| 58 | ///@param: image: the image to preprocess |
| 59 | ///@return: the preprocessed image |
| 60 | buffer<bf16> Gemma3::preprocess_image(bytes& image) { |
| 61 | buffer<bf16> result(3 * 896 * 896); |
| 62 | const int total_pixels = 896 * 896; |
| 63 | image_data_t input; |
| 64 | input.width = 896; |
| 65 | input.height = 896; |
| 66 | input.pixels = image; |
| 67 | |
| 68 | image_data_t chw; |
| 69 | if (!image_reader_.reorder_hwc_to_chw(input, chw) || chw.pixels.size() < static_cast<size_t>(total_pixels) * 3) { |
| 70 | image.release(); |
| 71 | return result; |
| 72 | } |
| 73 | |
| 74 | const uint8_t* src = chw.pixels.data(); |
| 75 | const float scale = 1.0f / 255.0f; |
| 76 | |
| 77 | for (int c = 0; c < 3; ++c) { |
| 78 | const size_t channel_offset = static_cast<size_t>(c) * total_pixels; |
| 79 | for (int i = 0; i < total_pixels; ++i) { |
| 80 | float normalized = (static_cast<float>(src[channel_offset + i]) * scale - 0.5f) * 2.0f; |
| 81 | result[channel_offset + i] = bf16(normalized); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | image_reader_.recycle(chw); |
| 86 | image.release(); |
| 87 | return result; |
| 88 | } |
nothing calls this directly
no test coverage detected