В этой статье я хочу затронуть проблемы построения алгоритмов масштабирования изображения.
Наверняка когда вы пытались найти алгоритмы масштабирования вы находили в первую очередь что-то вроде: Существуют несколько алгоритмов самое простое это алгоритм Ближайший соседа потом билинейная, бикубическая интерполяция и т.д.
И какие могут быть проблемы?
Первая проблема
Ну начнем с того, что по сути своей масштабирование реализует только алгоритм Ближайшего соседа, оставшиеся лишь реализуют сглаживание более пикселизированого и грубого изображения. Нет вы конечно можете реализовать другие алгоритмы и без Ближайшего соседа, только ваш алгоритмом будет встроен тот же принцип.
Вторая проблема
Прекрасно казалось бы всё мы используем алгоритм ближайшего соседа, поверх используем какую-нибудь интерполяцию, либо функцию Ланцоша и воля, у нас все хорошо. Хорошо до того момента как мы не уменьшим изображение.
Конечно после этого мы начнем искать решение проблемы. Будем использовать разные фильтры, несколько циклов поэтапного уменьшения, и всё рано получим тот же ужасный результат.
А почему? Да потому, что сам принцип алгоритма Ближайшего соседа, не является верным для уменьшения изображения.
Я приведу аналогию: Перед нами стоит яблоко так, что мы видим, что оно состоит из сочетания зеленого и красного цвета, мы отходим на значительное расстояние и видим, наше яблоко перестаёт быть зелено-красным, теперь оно жёлтое. Почему так произошло, да потому, что яблоко теперь в меньшом площади обозрения, и зелёный с красным смешались в один желтый цвет.
Как понимаете, алгоритм Ближайший сосед не способен объединять информацию, он лишь выборочно передаёт те или иные цвета. Как если бы в дали яблоко виделось бы нам только в зеленом или красном цвете. Из-за этого, при использование алгоритма, изображение оказывается рваным.
Если это так то как передать информацию полностью? Я думаю, что кто-то уже догадался. Мы можем все пиксели попадающие в одну ячейку массива, просто привести к среднему цвету.
Вот пример алгоритма на 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;
}
Результат
Как видите мы получили совершенно иной итог.
И хотелось ещё добавить что, при уменьшении мы можем применить те же заглаживающие алгоритмы.
Комментарии (9)
Kotofay
25.10.2022 18:10+20Перед нами стоит яблок ...
... при увеличение наша изображение ...
В пустой котомк поклав ржаное хлебо,
я выхожу туда где птичий трель!
(с) А. Иванов
victor30608
25.10.2022 20:31+1Попробуйте вычитать все несоответствия. У вас во многих места отсутствует согласование слов/падежей. Ощущение, что человек до этого не писал на русском языке.
И хотелось ещё добавить, что при увеличениИ нашЕГО изображениЯ, мы можем применить те же Сглаживающие алгоритмы.
PaulZi
26.10.2022 15:02+100500. Алгоритм ближайшего соседа используют только ради производительности. В остальных случаях всегда используется сглаживание по всем пикселям что попадают в новую сетку.
alexhott
26.10.2022 07:21+2Для обучения и саморазвития конечно хорошо. Но это давно уже сделано, и много чего еще получше, и защищено патентами.
AzIdeaL
26.10.2022 19:38Интересно -- на абстракцию выбросило: перестал искать отличия в енотах, в сочетаниях чёткая/мутная дева, в т.ч. их версиях. И, да, отошол подальше от данных объектов -- визуально слажились.
ЗЫ: по иному взглянул на алгоритмичное масштабирование ближайшим соседом
GCU
28.10.2022 11:13Добавьте пожалуйста пояснение что усреднение цвета должно проводиться в линейном цветовом пространстве. Это важно - просто брать закодированные значения каналов 0-255 и складывать без учёта sRGB нельзя!
Ritan
28.10.2022 12:55Только написанное это и есть билинейная фильтрация. Не стоит писать статьи, когда не понимаешь о чём пишешь
GeorgeIV
Это перевод?
Giperoglif
по-моему, это Амелия Понд