В этой статье я хочу затронуть проблемы построения алгоритмов масштабирования изображения.

Наверняка когда вы пытались найти алгоритмы масштабирования вы находили в первую очередь что-то вроде: Существуют несколько алгоритмов самое простое это алгоритм Ближайший соседа потом билинейная, бикубическая интерполяция и т.д.

И какие могут быть проблемы?

Первая проблема

Ну начнем с того, что по сути своей масштабирование реализует только алгоритм Ближайшего соседа, оставшиеся лишь реализуют сглаживание более пикселизированого и грубого изображения. Нет вы конечно можете реализовать другие алгоритмы и без Ближайшего соседа, только ваш алгоритмом будет встроен тот же принцип.

1 Алгоритма Ближайший сосед. 2 Фильтр Ланцоша
1 Алгоритма Ближайший сосед. 2 Фильтр Ланцоша

Вторая проблема

Прекрасно казалось бы всё мы используем алгоритм ближайшего соседа, поверх используем какую-нибудь интерполяцию, либо функцию Ланцоша и воля, у нас все хорошо. Хорошо до того момента как мы не уменьшим изображение.

1.Исходное изображение, 2.Уменьшеное алгоритмом Ближайший сосед
1.Исходное изображение, 2.Уменьшеное алгоритмом Ближайший сосед

Конечно после этого мы начнем искать решение проблемы. Будем использовать разные фильтры, несколько циклов поэтапного уменьшения, и всё рано получим тот же ужасный результат.

А почему? Да потому, что сам принцип алгоритма Ближайшего соседа, не является верным для уменьшения изображения.

Я приведу аналогию: Перед нами стоит яблоко так, что мы видим, что оно состоит из сочетания зеленого и красного цвета, мы отходим на значительное расстояние и видим, наше яблоко перестаёт быть зелено-красным, теперь оно жёлтое. Почему так произошло, да потому, что яблоко теперь в меньшом площади обозрения, и зелёный с красным смешались в один желтый цвет.

Как понимаете, алгоритм Ближайший сосед не способен объединять информацию, он лишь выборочно передаёт те или иные цвета. Как если бы в дали яблоко виделось бы нам только в зеленом или красном цвете. Из-за этого, при использование алгоритма, изображение оказывается рваным.

Если это так то как передать информацию полностью? Я думаю, что кто-то уже догадался. Мы можем все пиксели попадающие в одну ячейку массива, просто привести к среднему цвету.

Вот пример алгоритма на C#

  public static Color[,] ConvertImage(Color[,] image, double percentageValue)
  {
      int width = (int)Math.Round(image.GetLength(0) * percentageValue);
      int height = (int)Math.Round(image.GetLength(1) * percentageValue);
  
      double[,,] valuesSum = new double[width, height, 4];
      int[,] quantities = new int[width, height];
  
  
      for (int y = 0; y < image.GetLength(0); y++)
      {
          int y2 = (int)Math.Ceiling(y * percentageValue);
  
          if (y2 >= width)
              y2 = width - 1;
  
          for (int x = 0; x < image.GetLength(1); x++)
          {
              int x2 = (int)Math.Ceiling(x * percentageValue);
  
              if (x2 >= height)
                  x2 = height - 1;
  
              valuesSum[y2, x2, 0] += image[y, x].A;
              valuesSum[y2, x2, 1] += image[y, x].R;
              valuesSum[y2, x2, 2] += image[y, x].G;
              valuesSum[y2, x2, 3] += image[y, x].B;
  
              quantities[y2, x2]++;
          }
      }
  
      Color[,] newImage = new Color[width, height];
  
      for (int y = 0; y < newImage.GetLength(0); y++)
      {
          for (int x = 0; x < newImage.GetLength(1); x++)
          {
              int A = (int)(valuesSum[y, x, 0] / quantities[y, x]);
              int R = (int)(valuesSum[y, x, 1] / quantities[y, x]);
              int G = (int)(valuesSum[y, x, 2] / quantities[y, x]);
              int B = (int)(valuesSum[y, x, 3] / quantities[y, x]);
  
              newImage[y, x] = Color.FromArgb(A, R, G, B);
          }
      }
  
      return newImage;
  }


Результат

Исходное изображение, 2.Уменьшеное новым алгоритмом
Исходное изображение, 2.Уменьшеное новым алгоритмом


Как видите мы получили совершенно иной итог.


И хотелось ещё добавить что, при уменьшении мы можем применить те же заглаживающие алгоритмы.

Комментарии (9)


  1. GeorgeIV
    25.10.2022 17:59
    +4

    Это перевод?


    1. Giperoglif
      26.10.2022 03:51
      +1

      по-моему, это Амелия Понд


  1. Kotofay
    25.10.2022 18:10
    +20

    Перед нами стоит яблок ...

    ... при увеличение наша изображение ...

    В пустой котомк поклав ржаное хлебо,

    я выхожу туда где птичий трель!

    (с) А. Иванов


  1. victor30608
    25.10.2022 20:31
    +1

    Попробуйте вычитать все несоответствия. У вас во многих места отсутствует согласование слов/падежей. Ощущение, что человек до этого не писал на русском языке.

    И хотелось ещё добавить, что при увеличениИ нашЕГО изображениЯ, мы можем применить те же Сглаживающие алгоритмы.


    1. PaulZi
      26.10.2022 15:02

      +100500. Алгоритм ближайшего соседа используют только ради производительности. В остальных случаях всегда используется сглаживание по всем пикселям что попадают в новую сетку.


  1. alexhott
    26.10.2022 07:21
    +2

    Для обучения и саморазвития конечно хорошо. Но это давно уже сделано, и много чего еще получше, и защищено патентами.


  1. AzIdeaL
    26.10.2022 19:38

    Интересно -- на абстракцию выбросило: перестал искать отличия в енотах, в сочетаниях чёткая/мутная дева, в т.ч. их версиях. И, да, отошол подальше от данных объектов -- визуально слажились.

    ЗЫ: по иному взглянул на алгоритмичное масштабирование ближайшим соседом


  1. GCU
    28.10.2022 11:13

    Добавьте пожалуйста пояснение что усреднение цвета должно проводиться в линейном цветовом пространстве. Это важно - просто брать закодированные значения каналов 0-255 и складывать без учёта sRGB нельзя!


  1. Ritan
    28.10.2022 12:55

    Только написанное это и есть билинейная фильтрация. Не стоит писать статьи, когда не понимаешь о чём пишешь