Lab03.md

图像旋转

源代码需要在clEnqueueNDRangeKernel函数执行之后注释掉

waitForEventAndRelease() //或者// 
clWaitForEvents(1,&ev)

因为wait函数在结束时释放了ev,而下一个函数cl的功能其实和wait类似,也要访问ev变量,所以如果两个函数串行执行,后执行的那个会找不到那个变量,相当于访问空指针,会报段错误。
实验结果:

Lab03.md_第1张图片
原图

CPU旋转的结果


Lab03.md_第2张图片
CPU

用OpenCL进行旋转的结果


Lab03.md_第3张图片
OpenCL

边缘检测

CPU

需要和旋转一样调用cv.h,方法是将编译语句-o命名和-lOpenCL中间加一个调用

`pkg-config --cflags --libs opencv`

然后方法是直接调用sobel函数,参数分别为
sobel(Mat类型输入,输出,输出图像深度,x方向差分阶数,y方向...,核大小,缩放因子,delta值,边界模式)
深度ddepth取CV_16S;核大小默认3可调,缩放因子默认1,delta默认0,边界模式默认BORDER_DEFAULT。
如果做x方向上的sobel运算,则x方向差分阶数=1,y方向=0.
反之亦然。
将两个反向的结果做近似处理,即调用addweighted()函数,指数设为0.5,作类似求勾股的操作。得到每个元素的梯度,输出即是被强化后的边缘。


Lab03.md_第4张图片
结果
Lab03.md_第5张图片
CPU效果图

OpenCL方面的运算我参考了https://software.intel.com/en-us/INDE-OpenCL-Sobel,这里的思路是:

__kernel void Sobel_v1_uchar (__global uchar *pSrcImage, __global uchar *pDstImage)

{

    uint dstYStride = get_global_size(0);

    uint dstIndex   = get_global_id(1) * dstYStride + get_global_id(0);

    uint srcYStride = dstYStride + 32;

    uint srcIndex   = get_global_id(1) * srcYStride + get_global_id(0) + 16;

    uint a,     b,      c;
    uint d, /*center*/  f;
    uint g,     h,      i;
 
    // Read data in
    a = pSrcImage[srcIndex-1];  b = pSrcImage[srcIndex];    c = pSrcImage[srcIndex+1];
    srcIndex += srcYStride;
    d = pSrcImage[srcIndex-1];  /*center*/                 f = pSrcImage[srcIndex+1];  
    srcIndex += srcYStride;
    g = pSrcImage[srcIndex-1];  h = pSrcImage[srcIndex];    i = pSrcImage[srcIndex+1]; 

    uint xVal =     a* 1 +          c*-1    +
            d* 2 +  /*center*/  f*-2    +
            g* 1 +              i*-1;             
    uint yVal = a* 1 + b* 2 + c* 1 +
               /*center*/   
            g*-1 + h*-2 + i*-1;
    // Write data out      
    pDstImage[dstIndex] =  min((uint)255, (uint)sqrt(xVal*xVal + yVal*yVal));  
}

仿照平时对图像处理的方法,一个workitem处理一个像素,对每一个像素周围的3x3区域的每个像素点进行两个方向上的卷积处理,然后再平方后求和开方。

你可能感兴趣的:(Lab03.md)