2013-12-03 2 views
0

Я пытаюсь реализовать простой алгоритм размытия Gaussian для моей программы редактирования изображений. Тем не менее, я был возникли некоторые трудности, делая эту работу, и я думаю, что проблема заключается в ниже фрагменте кода:Gaussian blur не равно

 for(int j = 0; j < pow(kernel_size, 2); j++) 
     { 
      int idx = (i + kx + (ky * img.width)); 

      //Try and overload this whenever possible 
      valueR += (img.p_pixelArray[ idx ].r * kernel[ j ]); 
      valueG += (img.p_pixelArray[ idx ].g * kernel[ j ]); 
      valueB += (img.p_pixelArray[ idx ].b * kernel[ j ]); 

      if(kx == kernel_limit) 
      { 
       kx = -kernel_limit; 
       ky++; 
      } 

      else  
      { 
       kx++; 
      } 
     } 

     kx = -kernel_limit; 
     ky = -kernel_limit; 

Краткое объяснение приведенного выше кода: размер ядра является размер ядра (или матрица), порожденная формулой Гауссова размытия. kx и ky являются переменными, которые будут использоваться для итерации по ядру. i - это родительская петля, которая гнездится для этого и просматривает каждый пиксель изображения. Каждая переменная просто сохраняет значение R, G или B поплавка и затем используется для получения конечного результата. Значение if-else используется для увеличения kx и ky. idx используется для поиска правильного пикселя. предел ядра является переменной набор для

(*kernel size* - 1)/2 

Так что я могу иметь кх происходит от -1 (с ядром 3х3) +1, и то же самое с ку. Я думаю, проблема связана с линией

int idx = (i + kx + (ky * img.width)); 

Но я не уверен. Изображение я получаю:

Lenna

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

EDIT: Путь заполняю ядро ​​выглядит следующим образом:

for(int i = 0; i < pow(kernel_size, 2); i++) 
{ 
    // This. Is. Lisp. 
    kernel[i] = ((1/(2 * pi * pow(sigma, 2))) * pow (e, (-(((pow(kx, 2) + pow(ky, 2))/2 * pow(sigma, 2)))))); 

    if((kx + 1) == kernel_size) 
    { 
     kx = 0; 
     ky++; 
    } 

    else 
    { 
     kx++; 
    } 
} 
+0

Последние два заявления должны быть вне вашей петли, я думаю? В противном случае вы перезаписываете 'kx' и' ky' на каждой итерации, и вы всегда получите одинаковое значение для 'idx'. Кроме того, вы можете показать, как вы заполняете «ядро», может быть, это не так. – sgvd

+0

О, да, они все равно были вне цикла, я просто поставил их в неподходящее место ... – MKII

+0

@sgvd Отредактировал вопрос, чтобы включить вычисление ядра. – MKII

ответ

2

Несколько проблем:

Ваш Gaussian промахов скобки (даже если у вас уже есть много ..) вокруг 2 * pow(sigma, 2). Теперь вы умножаетесь на разницу вместо деления.

Но что ваша проблема в том, что ваш гауссовой сосредоточен на kx = ky = 0, как вы смочите от 0 к kernel_size, а не от -kernel_limit к kernel_limit. Это приводит к диагональному размытию. Нечто подобное должно работать лучше

kx = -kernel_limit; 
ky = -kernel_limit; 

int kernel_size_sq = kernel_size * kernel_size; 

for(int i = 0; i < kernel_size_sq; i++) 
{ 
    double sigma_sq = sigma * sigma; 
    double kx_sq = kx * kx; 
    double ky_sq = ky * ky; 
    kernel[i] = 1.0/(2 * pi * sigma_sq) * exp(-(kx_sq + ky_sq)/(2 * sigma_sq)); 

    if(kx == kernel_limit) 
    { 
    kx = -kernel_limit; 
    ky++; 
    } 
    else 
    { 
    kx++; 
    } 
} 

Кроме того, обратите внимание, как я избавилась от ваших LISP-Несс и некоторых улучшений: использовать некоторые промежуточные переменные для ясности (компилятор оптимизирует их прочь, если в любом случае вы попросите его); простое умножение происходит быстрее, чем pow(x, 2); pow(e, x) == exp(x).

+0

Большое спасибо. – MKII