LINUX.ORG.RU

Размытие изображение, что делать с крайними пикселями

 ,


1

1

Сначала я хотел проверять х,у координату пикселя, и если это являлся пиксель которых выходит за границы делать равным координатам самого пикселя.

(То есть пиксель 0,0 в размытии будет среднем арифметическим себя, снова себя, нижнего пикселя, и правого пикселя.)

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

П.С. под алгоритмом размытие я имею в виду среднее арифметическое цветов соседних(четырех) пикселей.

П.С.С пишу на Qt


Ответ на: комментарий от knotri

Нет, не дольше. Просто у тебя будет два алгоритма — один быстрый, для внутренних пикселей, для которых есть гарантия наличия всех соседей. И второй — медленный, когда для каждого пикселя проверяется наличие соседей. Его нужно будет прогонять только по границам, это 2*width + 2*height пикселей. Можешь побольше сделать разных, для центра, для рёбер, для углов. Итого 9 блоков.

anonymous
()
Ответ на: комментарий от knotri

Для картинки N*N пикселей заполнить средние полосы это N*расходы на вызов memcpy, заполнить края это 4*N*ширину ядра свёртки фильтра, можно две горизонтальные полосы заполнить тоже с помощью memcpy, вырезать серёдку это N*расходы на вызов memcpy. Итого 2*N*memcopy price + 4*N*kernel width.

dn2010 ★★★★★
()
Ответ на: комментарий от anonymous

Так это не то что сказал первый. Я же предложил два способа. Или проверка соседей, или создание большей картинки.

Какой использовать?

knotri
() автор топика

По-моему, там применяется свёртка матриц. И никаких забот о границах.

anonymous
()
Ответ на: комментарий от knotri

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

gavlig ★★★
()

Дополнение изображения на границах бордюром по определенному алгоритму (константный, зеркальное отражение) перед применением фильтра есть нормальная практика.

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

Не подскажете как сделать? Использую Qt.

knotri
() автор топика

Есть целая куча статей на данную тему. В том числе и на хабре... Как вариант: брать пиксели с противоположной стороны.

Newlifer
()
Ответ на: комментарий от Newlifer

Луркать по тегам [свертка] и [фильтры изображений] :)

Newlifer
()
Ответ на: комментарий от Newlifer

Как вариант: брать пиксели с противоположной стороны.

это совсем не вариант в общем случае.

mashina ★★★★★
()

под алгоритмом размытие я имею в виду среднее арифметическое цветов соседних(четырех) пикселей.

Если взять нормальный алгоритм (т.е.Gaussian blur на FSM), то проблема граничных условий легко решается начальной иницилизацией состояния FSM.

mashina ★★★★★
()

Возьми OpenCV и не еби нам моск.

Pavval ★★★★★
()
Ответ на: комментарий от AIv

Нет. За счет предсказания ветвлений в данном случае if быстрее.

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

dn2010 ★★★★★
()
Ответ на: комментарий от dn2010

Не будет. Точнее будет только на границах области, время на обработку которых много меньше, чем на обработку внутренней части области. И где Вы там углядели сложный if O_O?

У Вас весьма устаревшие представления о том, как это работает.

AIv ★★★★★
()
Ответ на: комментарий от AIv

И какой ответ? Просто иногда бывает фильтры(как тоже размытие) с радиусом(или как это называется) больше 1 пикселя

knotri
() автор топика
Ответ на: комментарий от knotri

фильтры(как тоже размытие) с радиусом(или как это называется) больше 1 пикселя

Для линейного 2D фильтра можно построить алгоритм со сложностью O(N*R) вместо O(N*R*R).

AIv ★★★★★
()
Ответ на: комментарий от knotri

Просто иногда бывает фильтры(как тоже размытие) с радиусом(или как это называется) больше 1 пикселя

сложность работы не детсадовских алгоритмов размытия не зависит от радиуса.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Я не о том, в нем же должны учитываться например не только соседнее пиксели, но и соседи соседей, и так далее(радиус если я правильно понял).

Тогда что будет эффективней?

knotri
() автор топика
Ответ на: комментарий от knotri

клонирование изображения с паддингами не будет эффективнее специальной обработки граничных условий прямо в алгоритме

mashina ★★★★★
()
Ответ на: комментарий от mashina
for(int y=0; y<img->height(); y++){
        for(int x=0; x<img->width();x++){
            rr = rg = rb = ra = 0;
            pix2 = line2+stride2*y+4*x;

            for(int i=-1;i<2;i+=2){
                for(int j=-1;j<2;j+=2){
                    int yr,xr;
                    yr = std::max(0,std::min(HH-1,y+i));
                    xr = std::max(0,std::min(WW-1,x+j));
                    pix = line+stride*(yr)+4*(xr);
                    b = pix[0];
                    g = pix[1];
                    r = pix[2];
                    a = pix[3];

                    rr+=r;
                    rg+=g;
                    rb+=b;
                    ra+=a;
                }
            }

            pix2[0] = rb/4;
            pix2[1] = rg/4;
            pix2[2] = rr/4;
            pix2[3] = ra/4;
        }
    }
knotri
() автор топика
Ответ на: комментарий от mashina

Выше мой код, обработка условий правильно сделана?

knotri
() автор топика
Ответ на: комментарий от mashina

Можно, конечно, сразу хранить изображение с запасом для краёв. Но навряд ли от этого будет заметен эффект. Как уже ниже(выше) верно заметили, сложность обработки краёв ~ 2 * (N + M), а внутренности ~ N * M. Т.е. значительно большую часть времени алгоритм будет работать в «обычном» режиме.

И неплохрй пример с размытием. Не все алгоритмы с радиусом реализуются тупо именно через прямую обработку соседних точек в окрестности.

mashina ★★★★★
()

Ты вообще с дубу рухнул писать алгоритм для свертки изображений??? Возьми готовую либу! Начнем с того, что при размытии с гауссовским ядром, это самое ядро сепарабельно, то есть можно двумерную свертку заменить на две одномерных, что ОЧЕНЬ быстрее. Во-вторых, при большом размере ядра(не обязательно гауссовского) намного быстрее будет с помощью FFT перейти в частотное пространство и перемножить там, и потом отразить обратно, получив размытие. Я уж и говорить не буду, что у тебя не получится нормально многопоточно, с хорошей утилизацией кэша это все написать за несколько дней.

Но если тебе просто интересно, или такое задание дали, то варианта 3:

-заполнить полосы по краям граничными пикселями,

-зеркально отразить,

-начать заполнять тем, что было на противоположной стороне.

Возьми за пример матлабовскую имплементацию. http://www.mathworks.ch/ch/help/images/ref/imfilter.html

Вот опции свертки там есть какие:

Boundary Options

'symmetric'
Input array values outside the bounds of the array are computed by mirror-reflecting the array across the array border.

'replicate'
Input array values outside the bounds of the array are assumed to equal the nearest array border value.

'circular'
Input array values outside the bounds of the array are computed by implicitly assuming the input array is periodic.

maggotroot
()

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

Скорее всего тут речь идет о «коррекции» текстуры таким образом, что бы избавиться от черных и белых полос по краям при клампе.

andreyu ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.