Страницы

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

вторник, 24 декабря 2019 г.

Низкочастотная фильтрация изображений (книга Гонсалеса “Цифровая обработка изображений”)

#java #изображения


Я пытаюсь реализовать на java низкочастотную фильтрацию изображений.

Реализую по книге Гонсалеса "Цифровая обработка изображений" следущие пункты (стр.
245):  


Исходное изображение умножается на "(-1)^(x+y)", чтобы его фурье-преобразование оказалось
центрированным;  
Вычисляется прямое ДПФ F(u,v) изображения, полученного после шага 1;  
Ф-ция F(u,v) умножается на ф-цию фильтра H(u,v);  
Вычисляется обратное ДПФ от результата шага 3;  
Вычисляется вещественная часть результата шага 4;  
Результат шага 5 умножается на (-1)^(x+y) 


Чисто для примера, решила реализовать "Идеальный фильтр низких частот" (стр.257).
Как я понимаю, результат получается неправильным с самого первого шага.

Что я делаю не так?

Прикладываю код каждого шага и результаты обработки на каждом шаге.

Моя реализация шагов:

1)

double funcXY;
Complex[][] arrOnStepOne = new Complex[bufferedImage.getWidth()][bufferedImage.getHeight()];
for (int x = 0; x < bufferedImage.getWidth(); x++) {
    for (int y = 0; y < bufferedImage.getHeight(); y++) {
        funcXY = (Math.pow(-1.0, (x + y))) * bufferedImage.getRGB(x, y);
        Complex complexFuncXY = new Complex(funcXY, 0);
        arrOnStepOne[x][y] = complexFuncXY;
    }
}


2)

int width = arrOnStepOne.length;
int height = arrOnStepOne[0].length;
Complex sumByX = new Complex(0, 0);
Complex sumByY = new Complex(0, 0);
Complex[][] complexFurje = new Complex[width][height];
for (int u=0; u <= width-1; u++) {
    for (int v = 0; v <= height-1; v++) {
        sumByX = new Complex(0, 0);
        for (int x = 0; x <= width - 1; x++) {
            sumByY = new Complex(0, 0);
            for (int y = 0; y <= height - 1; y++) {
                Double teta = -2 * Math.PI * ((u * x / (double) width) + (v * y /
(double) height));
                Complex complexE = new Complex(Math.cos(teta), Math.sin(teta));
                sumByY = sumByY.Add(arrOnStepOne[x][y].Mult(complexE));
            }
            sumByX = sumByX.Add(sumByY);
        }
        complexFurje[u][v] = sumByX.Div(new Complex(width*height, 0));
    }
}


3)

int d0;
int nPow = 2;
double d;
double filtrD;
double filtrH;
Complex[][] complexFiltr = new Complex[width][height];

for (int u=0;u <= width-1; u++) {
    for (int v = 0; v <= height-1; v++) {
        d = Math.pow((u - width / 2.), 2) + Math.pow((v - height / 2.), 2);
        filtrD = Math.pow(d, 1. / 2); //D(u,v)
        d0 = 80;
        filtrH = 1 / (1 + Math.pow(filtrD / d0, 2. * nPow));
        complexFiltr[u][v] = new Complex(filtrH, 0).Mult(complexFurje[u][v]);
    }
}


4)

for (int x = 0; x <= width-1 ; x++) {
    System.out.println("X = " + x +" / " + (width-1) + ".");
    for (int y = 0; y <= height-1 ; y++) {
        sumByU = new Complex(0, 0);

        for (int u = 0; u <= width-1; u++) {
            sumByV = new Complex(0, 0);
            for (int v = 0; v <= height - 1; v++) {
                Double teta = 2 * Math.PI * (x * u / (double) width + y * v / (double)
height);
                Complex complexE = new Complex(Math.cos(teta), Math.sin(teta));
                sumByV = sumByV.Add(complexE.Mult(complexFiltr[u][v]));
            }
            sumByU = sumByU.Add(sumByV);
        }
        funcStep4XY[x][y]=sumByU;
    }
}


5,6)

for (int x = 0; x <= width-1; x++) {
    for (int y = 0; y <= height-1; y++) {
        funcStep5XY[x][y] = funcStep4XY[x][y].getdReal();
        funcStep5XY[x][y] *= Math.pow(-1.0,x+y);
    }
}



Ссылка на саму книгу здесь
    


Ответы

Ответ 1



Судя по артефактам на step1.jpg, вычисления производятся в целых числах. При этом происходит переполнение вместо сатурации, из-за чего вместо "засветки" белым цветом можно увидеть чёрные пиксели. В результате ДПФ step2.jpg вместо белой "звезды" на чёрном фоне выглядит как случайный шум, образованный всё теми же искажениями переполнения. Ну, и в итоге после ОДПФ получается сильно зашумленное изображение step56.jpg. Просто не хватает разрядности при вычислениях. Например, нужно 35 бит, а используется 32 бита.

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

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