Страницы

Поиск по вопросам

вторник, 16 октября 2018 г.

Алгоритм увеличения изображения, содержащего градиент

Стоит задача: увеличить изображение 100х100 с четырмя каналами, (красный, зелёный, синий, альфа-канал; содержит сильно размытое пятно), до размера 2500х2500, и вывести на заранее подготовленный графический контекст устройства. Фактически кисть, наподобии кистей в графическом редакторе Adobe Photoshop. Проблема состоит как раз в увеличении (ресайзе). Вот исходное изображение (или кисть; показываю только альфа канал, остальное не принципиально): Нарисовано стадартной кистью Photoshop. А вот, что получается после увеличения моим алгоритмом (ещё раз: не обращайте внимания на цвет: он устанавливается рандомом). Я использовал ленийное интерполирование. Вы тоже видите эти шероховатости? Так вот: вся проблема в них. Эти шерховатости находятся в альфа-канале, т.к. цвет у всей кисти однородный. Из-за них, при рисовании линии кистью, образуется страшная грязь. Чтобы понять природу этих неровностей, я решил нарисовать в Photoshop'е полоску шириной 1 пикс., представляющую собой плавный градиент от белого к синему, а потом снова к белому. Далее я увеличил по ширине каждую полоску сначала своим алгоритмом, потом в Photoshop'е: alt text http://plasmon.rghost.ru/38526229/image.png alt text http://rghost.ru/38526272/image.png На первом рисунке опять видно неровности. Вот почему, по моему мнению, возникают неровности:alt text http://rghost.ru/38526320/image.png Здесь по оси x - номер пикселя, y - цвет. Синие точки - исходные, красные - аппроксимированнные линейной интерполяцией. Синий график показывают идеальную интерполяцию сплайнами, но она слишком долго выполняется на компьтере. Так вот, видите ломаный чёрный график линейной интерполяци? Вот эти самые углы ломаной, мне кажется, образуют такие шероховатости.
В Photoshop'е в настройках стоит интерполяция "Bicubic (best for smooth gradients)", но "Linear" и "Bicubic" в Photoshop'е дают одинаковый с моим алгоритмом результат. Так что можно считать, что "Bicubic (best for smooth gradients)" в Photoshop'е изображение сначала увеличивается линейной интерполяцией а потом применяется банальный фильтр размытия.

Итак. Все фильтры размытия которые я нашёл в интернете работают крайне медленно (в т.ч. мой). Скорее всего, Photoshop использует графический ускоритель. Но возможно ли как-нибудь реализовать мою задачу только с помощью CPU? И чтобы работало максимум секунду. Жду ваших предложений.

//горизонтальная интерполяция между исходными пикселами for y:=1 to setedbrush.h_orig do for x := 1 to setedbrush.w_orig-1 do begin x_0:=round(x*k); x_x:=x_0+1; x_1:=round((x+1)*k); y_y:=round(y*k);
while(x_x<>x_1) do begin cl:=round((temp[x_1,y_y].r-temp[x_0,y_y].r)/(x_1-x_0))+temp[x_0,y_y].r; temp[x_x,y_y].r:=cl;
cl:=round((temp[x_1,y_y].g-temp[x_0,y_y].g)/(x_1-x_0))+temp[x_0,y_y].g; temp[x_x,y_y].g:=cl;
cl:=round((temp[x_1,y_y].b-temp[x_0,y_y].b)/(x_1-x_0))+temp[x_0,y_y].b; temp[x_x,y_y].b:=cl;
cl:=round((temp[x_1,y_y].a-temp[x_0,y_y].a)/(x_1-x_0))+temp[x_0,y_y].a; temp[x_x,y_y].a:=cl;
inc(x_0); inc(x_x); end; end;
Здесь x_0 - крайний известный левый пиксел, соответственно x_1 - правый; x_x - расчитываемый пиксел, y_y - текущая строчка. Формула на основании подобия прямоугольных треугольников.

Результат уже лучше, чем прежде. Но при рисовании линии - грязь. Чтож, придётся сглаживать... Хотя, может быть, дело в картинке. alt text http://rghost.ru/38553575/image.png


Ответ

Вы предполагаете почему они возникают, а вы постройте реальный график изменения яркости вдоль одной какой-нибудь линии.
Cледующий пиксел рассчитывается через предыдущий, так будет накапливаться ошибка. Попробуйте считать по формуле относительно крайних точек, понятно что так ещё одно умножение потребуется, но будет точнее. Сначала проверьте лучше ли станет интерполяция, если считать по формуле:
round((temp[x_1,y_y].a-temp[x_0,y_y].a)*(x_x-x_0)/(x_1-x_0)) + temp[x_0,y_y].a
и x_0 во внутреннем цикле не менять

Комментариев нет:

Отправить комментарий