繁体   English   中英

Canny的OpenCL内核

[英]OpenCL Kernel for Canny

我正在尝试以非常简单易用的方式使用OpenCL内核实现Canny Edge Detection

我正在使用原始的SobelFilter内核来执行非最大抑制和阈值化之类的步骤。

但是我迷失了到达像素并用以下方法对它们进行数学计算:

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

您能给我一些想法还是给我一些简单的例子来实现这一目标? 我们将不胜感激。 问候。

Sobel过滤器在内核执行中可以分为X和Y维。 因此,一个人只能在X或Y维度上扫描,或者在同一个内核循环中对这两个维度进行扫描,以实现边缘特征检测。

在此处使用azer89用户的形象: 图像处理-实现Sobel过滤器

我准备了这个内核:

__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;

}

索引在此处uchar 4,因为它们被解释为uchar数组作为内核参数。 uchar是OpenCL中的单个字节(至少对于我的系统而言)。

这是一个视频:

影片缩图
Sobel筛选器示例

如果它也对您azer89 ,您应该接受azer89的解决方案。 但这不是很优化,对于低端GPU可能需要1-2毫秒,而对于只有1024x1024图像的CPU则可能需要更多时间。 使用字节数组(C#语言)将图像数据发送到OpenCL缓冲区(不是图像缓冲区),内核启动选项为:

  • 全局范围= 1024 * 1024(每个像素处理1个线程)
  • 本地范围= 256(这并不重要)
  • 缓冲区副本大小1024 * 1024 * 4(用于rgba格式的字节)

这里的kernelx和kernely 2D数组也是float因此将它们设为char可以使其速度更快。 如果结果看起来比预期的颜色鲜艳得多,您也可以检查结果(钳位,划分等)。 主机端的表示/解释对于处理颜色的下溢和过低也很重要。

ARM计算库具有canny实现Canny CL内核

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM