Created
June 8, 2026 04:29
-
-
Save romancone/936b10f9f0541c526f4f16b1dfd6da86 to your computer and use it in GitHub Desktop.
Smart resize for backend
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "errors" | |
| "image" | |
| "math" | |
| // Используем стандартный пакет для качественного и быстрого ресайза | |
| "golang.org/x/image/draw" | |
| ) | |
| const PatchSize = 16 | |
| // ResizeOptions содержит параметры для оптимизации изображения | |
| type ResizeOptions struct { | |
| TokenBudget int // Например: 70, 140, 280, 560, 1120 | |
| } | |
| // SmartResizeVision принимает исходное изображение и подгоняет его под бюджет токенов Gemma 4, | |
| // строго сохраняя пропорции кадра и кратность сторон 16 пикселям. | |
| func SmartResizeVision(img image.Image, opts ResizeOptions) (image.Image, error) { | |
| if opts.TokenBudget <= 0 { | |
| return nil, errors.New("token budget must be greater than 0") | |
| } | |
| bounds := img.Bounds() | |
| origW := bounds.Dx() | |
| origH := bounds.Dy() | |
| if origW == 0 || origH == 0 { | |
| return nil, errors.New("invalid image dimensions") | |
| } | |
| // 1. Вычисляем оптимальную сетку патчей (gridW и gridH) | |
| targetW, targetH := calculateOptimalDimensions(origW, origH, opts.TokenBudget) | |
| // 2. Если изображение уже совпадает с целевым размером, возвращаем его | |
| if origW == targetW && origH == targetH { | |
| return img, nil | |
| } | |
| // 3. Выполняем ресайз с использованием высококачественного интерполятора BiLinear | |
| // (BiLinear — оптимальный баланс скорости и качества деталей для нейросетей) | |
| rect := image.Rect(0, 0, targetW, targetH) | |
| dst := image.NewRGBA(rect) | |
| draw.BiLinear.Scale(dst, rect, img, bounds, draw.Over, nil) | |
| return dst, nil | |
| } | |
| // calculateOptimalDimensions подбирает размеры сторон кратными PatchSize, | |
| // минимизируя искажение Aspect Ratio и не превышая TokenBudget. | |
| func calculateOptimalDimensions(origW, grandchildrenH int, budget int) (int, int) { | |
| origRatio := float64(origW) / float64(grandchildrenH) | |
| bestGridW := 1 | |
| bestGridH := 1 | |
| minRatioDiff := math.MaxFloat64 | |
| maxTokensUsed := 0 | |
| // Ограничиваем область поиска физическим пределом по сетке | |
| maxDim := int(math.Ceil(math.Sqrt(float64(budget)))) * 2 | |
| for gridW := 1; gridW <= maxDim; gridW++ { | |
| for gridH := 1; gridH <= maxDim; gridH++ { | |
| tokens := gridW * gridH | |
| // Нас интересуют только комбинации, проходящие в лимит токенов | |
| if tokens <= budget { | |
| currentRatio := float64(gridW) / float64(gridH) | |
| ratioDiff := math.Abs(currentRatio - origRatio) | |
| // Шаг 1: Ищем минимальное искажение пропорций | |
| // Шаг 2: При одинаковом качестве пропорций максимизируем утилизацию токенов (детализацию) | |
| if ratioDiff < minRatioDiff || (math.Abs(ratioDiff-minRatioDiff) < 1e-4 && tokens > maxTokensUsed) { | |
| minRatioDiff = ratioDiff | |
| bestGridW = gridW | |
| bestGridH = gridH | |
| maxTokensUsed = tokens | |
| } | |
| } | |
| } | |
| } | |
| // Переводим сетку патчей обратно в пиксели | |
| return bestGridW * PatchSize, bestGridH * PatchSize | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment