OpenCL Kernel для Canny

Я пытаюсь добиться Canny Edge Detection с Ядро OpenCL очень упрощенным и простым способом.

Я использую оригинал SobelFilter ядро, чтобы сделать шаги, такие как не максимальное подавление и пороговое значение.

Но я заблудился о достижении пикселей и выполнении математических вычислений для них с помощью:

__kernel void sobel_filter(__global uchar4* inputImage, __global uchar4* outputImage)

Не могли бы вы дать мне идеи или показать простые примеры для достижения этой цели? Это будет высоко оценено.
С уважением.

1

Решение

Фильтр Собеля по своей сути разделяется на измерения X и Y при выполнении ядра. Таким образом, можно сканировать только по X или только по Y измерениям или обоим в одном и том же цикле ядра, чтобы добиться обнаружения краевых признаков.

Использование пользователя azer89Подпись здесь: Обработка изображений — внедрение фильтра Собела

Я подготовил это ядро:

__kernel void postProcess(__global uchar * input, __global uchar * output)
{
int resultImgSize=1024;
int pixelX=get_global_id(0)%resultImgSize; // 1-D id list to 2D workitems(each process a single pixel)
int pixelY=get_global_id(0)/resultImgSize;
int imgW=resultImgSize;
int imgH=resultImgSize;float kernelx[3][3] = {{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}};
float kernely[3][3] = {{-1, -2, -1},
{0,  0,  0},
{1,  2,  1}};

// also colors are separable
int magXr=0,magYr=0; // red
int magXg=0,magYg=0;
int magXb=0,magYb=0;

// Sobel filter
// this conditional leaves 10-pixel-wide edges out of processing
if( (pixelX<imgW-10) && (pixelY<imgH-10) && (pixelX>10) && (pixelY>10) )
{
for(int a = 0; a < 3; a++)
{
for(int b = 0; b < 3; b++)
{
int xn = pixelX + a - 1;
int yn = pixelY + b - 1;

int index = xn + yn * resultImgSize;
magXr += input[index*4] * kernelx[a][b];
magXg += input[index*4+1] * kernelx[a][b];
magXb += input[index*4+2] * kernelx[a][b];
magYr += input[index*4] * kernely[a][b];
magYg += input[index*4+1] * kernely[a][b];
magYb += input[index*4+2] * kernely[a][b];
}
}
}

// magnitude of x+y vector
output[(pixelX+pixelY*resultImgSize)*4]  =sqrt((float)(magXr*magXr + magYr*magYr)) ;
output[(pixelX+pixelY*resultImgSize)*4+1]=sqrt((float)(magXg*magXg + magYg*magYg)) ;
output[(pixelX+pixelY*resultImgSize)*4+2]=sqrt((float)(magXb*magXb + magYb*magYb)) ;
output[(pixelX+pixelY*resultImgSize)*4+3]=255;

}

Индексы были умножены на 4 здесь, потому что они были интерпретированы как uchar массив в качестве параметров ядра. uchar это один байт в OpenCL (по крайней мере, для моей системы).

Вот видео этого:

Миниатюра видео
Пример фильтра Собеля

если это работает и для вас, вы должны принять azer89решение. Но это не очень оптимизировано и может потребовать 1-2 миллисекунды для низкоуровневых графических процессоров и даже больше — только с процессором для изображения 1024×1024. Данные изображения отправляются в буфер OpenCL (не буфер изображения) с использованием байтового массива (на языке C #), а параметры запуска ядра:

  • Глобальный диапазон = 1024 * 1024 (1 поток на обработку пикселей)
  • Локальный диапазон = 256 (это не важно)
  • Размер буфера 1024 * 1024 * 4 (байт для формата rgba)

также kernelx и Kernely 2D-массивы здесь были float так что делает их char может сделать это быстрее. Также вы можете проверить результаты (зажим, деление, …), если результат выглядит намного более красочным, чем ожидалось. Представление / интерпретация на стороне хоста также важна для обработки недостаточного или недостаточного количества цветов.

1

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

Библиотека вычислений ARM имеет хитрую реализацию
Canny CL ядро

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector