Реализация фильтра Собела в Java - нормализация значений

Я хочу реализовать Sobel Filter самостоятельно (на самом деле нет красивой реализации). Но после выполнения свертки я понятия не имею, как рассчитать значения RGB.

  • Предположение: серое масштабированное изображение

    double [][] sobel_x = 
    {
        { -1, 0, 1},
        { -2, 0, 2},
        { -1, 0, 1}
    };
    
    double [][]    sobel_y = 
    {
        { 1, 2, 1},
        { 0, 0, 0},
        {-1, -2, 1}
    };
    
    for(int y=1; y<image.getHeight()-1; y++)
    {
        for(int x=1; x<image.getWidth()-1; x++)
        {
           Color a = new Color(image.getRGB(x-1, y-1));
           Color b = new Color(image.getRGB(x, y-1));
           Color c = new Color(image.getRGB(x+1, y-1));
           Color d = new Color(image.getRGB(x-1, y));
           Color e = new Color(image.getRGB(x, y));
           Color f = new Color(image.getRGB(x+1, y));
           Color g = new Color(image.getRGB(x-1, y+1));
           Color h = new Color(image.getRGB(x, y+1));
           Color i = new Color(image.getRGB(x+1, y+1));
    
            double pixel_x =    (sobel_x[0][0] * a.getRed()) + (sobel_x[0][1] * b.getRed()) + (sobel_x[0][2] * c.getRed()) +
                                (sobel_x[1][0] * d.getRed())   + (sobel_x[1][1] * e.getRed())   + (sobel_x[1][2] * f.getRed()) +
                                (sobel_x[2][0] * g.getRed()) + (sobel_x[2][1] * h.getRed()) + (sobel_x[2][2] * i.getRed());
            double pixel_y = 
                                (sobel_y[0][0] * a.getRed()) + (sobel_x[0][1] * b.getRed()) + (sobel_x[0][2] * c.getRed()) +
                                (sobel_y[1][0] * d.getRed())   + (sobel_x[1][1] * e.getRed())   + (sobel_x[1][2] * f.getRed()) +
                                (sobel_y[2][0] * g.getRed()) + (sobel_x[2][1] * h.getRed()) + (sobel_x[2][2] * i.getRed());  
    
            //Here it is possible to get values between [-1020, 1020]       
    
            //How to going on
    
            //int rgb = (int) Math.sqrt(pixel_x*pixel_x+pixel_y*pixel_y);
    
            //int rgbAsInt = (int)(65536 * rgb + 256 * rgb + rgb);      
        }
    }   
    

2 ответа

Одна из моих идей - сделать линейное преобразование. Например, минимальное значение пикселя в полученном изображении было -998, а максимальное - 1000. Таким образом, вы можете соответствовать от -998 до 0 и от 1000 до 255, а затем получить соотношение между шкалой (-998,1000) и масштаб (0,255) и нормализовать все значения от [-998,1000] до [0,255].

Следующая область изображения имеет градиент оси X 1:

1 2 3
1 2 3
1 2 3

Применяя этот фильтр к нему -

-1 0 1
-2 0 2
-1 0 1

- дает результат 8. Таким образом, градиенты X и Y масштабируются по этому коэффициенту.

Вам нужно решить, какой максимальный градиент вы хотите представить в выходном изображении; назовите это "gr_max". Градиенты X и Y должны быть привязаны к этому значению:

float gr_x, gr_y, gr_max = 16;

gr_x /= (gr_max * 8);
gr_y /= (gr_max * 8);

if (gr_x > 1)
    gr_x = 1;
if (gr_x < -1)
    gr_x = -1;

if (gr_y > 1)
    gr_y = 1;
if (gr_y < -1)
    gr_y = -1;

Затем, если вы хотите, чтобы ваши выходные значения RGB были в диапазоне [0, 255] -

int pixel_x = lround((gr_x + 1) * 255/2),
    pixel_y = lround((gr_y + 1) * 255/2);
Другие вопросы по тегам