пороговый алгоритм алгоритма sobel (внешние библиотеки не используются)

Я пишу свою собственную реализацию обнаружения sobel egde. Интерфейс моей функции

void sobel_filter(volatile PIXEL * pixel_in, FLAG *EOL, volatile PIXEL * pixel_out, int rows, int cols)

(PIXEL — 8-битный пиксель в оттенках серого)
Для тестирования я изменил интерфейс на:

void sobel_filter (PIXEL пикселей_in [MAX_HEIGHT] [MAX_WIDTH], PIXEL
pix_out [MAX_HEIGHT] [MAX_WIDTH], int row, int cols);

Но, тем не менее, дело в том, что я получаю читать по одному пикселю за раз, что приводит меня к проблеме управления выходными значениями sobel, когда они больше 255 или меньше 0. Если бы у меня была вся картинка с самого начала, Я мог бы нормализовать все выходные значения sobel с их минимальными и максимальными значениями. Но это не возможно для меня.

Это мой код оператора sobel, ver1:

PIXEL sobel_op(PIXEL_CH window[KERNEL_SIZE][KERNEL_SIZE]){
const char x_op[KERNEL_SIZE][KERNEL_SIZE] = { {-1,0,1},
{-2,0,2},
{-1,0,1}};

const char y_op[KERNEL_SIZE][KERNEL_SIZE] = { {1,2,1},
{0,0,0},
{-1,-2,-1}};
short x_weight=0;
short y_weight=0;
PIXEL ans;
for (short i=0; i<KERNEL_SIZE; i++){
for(short j=0; j<KERNEL_SIZE; j++){
x_weight+=window[i][j]*x_op[i][j];
y_weight+=window[i][j]*y_op[i][j];
}
}
short val=ABS(x_weight)+ABS(y_weight);
//make sure the pixel value is between 0 and 255 and add thresholds
if(val>200)
val=255;
else if(val<100)
val=0;
ans=255-(unsigned char)(val);
return ans;

}

это версия 2, изменения вносятся только после суммирования весов:

short val=ABS(x_weight)+ABS(y_weight);
unsigned char char_val=(255-(unsigned char)(val));
//make sure the pixel value is between 0 and 255 and add thresholds
if(char_val>200)
char_val=255;
else if(char_val<100)
char_val=0;
ans=char_val;
return ans;

Теперь, для sobel 3×3 оба, кажется, дают хорошие результаты:
ver1;

ver2

Но когда я пытаюсь с 5×5 sobel

    const char x_op[KERNEL_SIZE][KERNEL_SIZE] = { {1,2,0,-2,-1},
{4,8,0,-8,-4},
{6,12,0,-12,-6},
{4,8,0,-8,-4},
{1,2,0,-2,-1}};

const char y_op[KERNEL_SIZE][KERNEL_SIZE] = { {-1,-4,-6,-4,-1},
{-2,-8,-12,-8,-2},
{0,0,0,0,0},
{2,8,12,8,2},
{1,4,6,4,1}};

это становится сложно:
ver1
вер

Как видите, для 5х5 результаты довольно плохие, и я не знаю, как нормализовать значения. Есть идеи?

3

Решение

Подумайте о диапазоне значений, которые могут принимать ваши отфильтрованные значения.

Для Sobel 3×3 самое высокое значение X / Y получается, когда пиксели с положительным коэффициентом являются белыми (255), а пиксели с отрицательным коэффициентом — черными (0), что дает в общей сложности 1020. Симметрично, самое низкое значение -1020. После принятия абсолютного значения диапазон составляет от 0 до 1020 = 4 х 255.

Для величины Abs (X) + Abs (Y) вычисление немного сложнее, так как два компонента не могут достичь 1020 одновременно. Если я прав, диапазон от 0 до 1530 = 6 х 255.

Аналогичные цифры для 5×5: 48 x 255 и 66 x 255.

Зная это, вы должны масштабировать значения в меньший диапазон (применить коэффициент уменьшения) и отрегулировать пороговые значения. Логично, что если вы примените коэффициент 3/66 к Собел 5×5, вы вернетесь к аналогичным условиям.

Все зависит от того эффекта, которого вы хотите добиться.

В любом случае, истинный вопрос заключается в следующем: как отфильтрованные значения статистически распределяются для типичных изображений? Потому что нет необходимости держать дальние хвосты дистрибутива.

3

Другие решения

Вы должны нормализовать результаты ваших вычислений. Для этого вы должны выяснить, насколько «большой» фильтр со всеми абсолютными значениями. Итак, я делаю это:

      for(int i = 0; i < mask.length; i++)
for(int j = 0; j < mask[i].length; j++)
size += Math.abs(mask[i][j]);

Где маска — мой трезвый фильтр каждого размера. Поэтому после применения вашего sobel-фильтра вы должны нормализовать значение в вашем коде, оно должно выглядеть так:

for (short i=0; i<KERNEL_SIZE; i++){
for(short j=0; j<KERNEL_SIZE; j++){
x_weight+=window[i][j]*x_op[i][j];
y_weight+=window[i][j]*y_op[i][j];
}
}
x_weight /= size;
y_weight /= size;

После этого для визуализации вам нужно сместить значения около 128. Просто сделайте это, если хотите визуализировать изображение. В противном случае вы получите проблемы с последующими вычислениями (например, градиент).

x_weight += 128;
y_weight += 128;

Надеюсь, что это работает и поможет.

3

По вопросам рекламы [email protected]