【问题标题】:Edge Detection using PyOpenCL使用 PyOpenCL 进行边缘检测
【发布时间】:2020-05-28 16:35:08
【问题描述】:

我在编写 python 脚本以使用 PyOpenCl 检测边缘时遇到问题。我是 OpenCL 的新手,在尝试时遇到了一个问题,经过多次调整后,我无法解决。下面是python代码:

edge.py:

import numpy as np
import pyopencl as cl
from PIL import Image
from time import time


def getKernel(krnl):
    kernel = open(krnl).read()
    return kernel


def findedges(p,d,image):

    data = np.asarray(image).astype(np.uint8)

    platform = cl.get_platforms()[p]
    device = platform.get_devices()[d]
    cntx = cl.Context([device])
    queue = cl.CommandQueue(cntx)

    mf = cl.mem_flags
    im = cl.Buffer(cntx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=data)
    out = cl.Buffer(cntx,mf.WRITE_ONLY,data.nbytes)

    prgm = cl.Program(cntx,getKernel('edge.c')%(data.shape[1],data.shape[0])).build()

    prgm.detectedge(queue,data.shape,None,im,out)

    result = np.empty_like(data)

    cl.enqueue_copy(queue,result,out)
    result = result.astype(np.uint8)
    print(result)

    img = Image.fromarray(result)
    #img.show()
    img.save('coinsedge.png')


if __name__ == '__main__':

    image = Image.open('coins.png')
    #(1,0) is my platform 1, device 0 = "AMD gpu"  
    #(0,0) for intel processor 
    findedges(1,0,image)

还有我的内核文件:edge.c


__kernel void detectedge(__global int *im,__global int *out){
      int j = get_global_id(1);
      int i = get_global_id(0);
      int width = %d;
      int rown = %d;
      int value;


              value = -im[(i)*width + j] -  0* im[(i)*width + j+1] + im[(i)*width + j+2]
                      -2*im[(i+1)*width + j] +  0*im[(i+1)*width + j+1] + 2*im[(i+1)*width + j+2]
                      -im[(i+2)*width + j] -  0*im[(i+2)*width + j+1] + im[(i+2)*width + j+2];

              value = (value < 0   ? 0   : value);
              value = (value > 255 ? 255 : value);
              out[i*width + j] = value;

  }

现在没有运行时警告/错误,但输出是我没想到的。这是输入及其输出: 这是我的输入图像:

这是我的输出:

【问题讨论】:

  • 我根本不了解 OpenCL,但我相信您可能会将 8 位整数像素传递给 OpenCL,但告诉它它们是 32 位整数。它在 CPU 上产生与 GPU 相同的结果吗?
  • 是的...在所有平台上...结果都是一样的...我什至尝试将 uint8 更改为 int 并尝试 if 条件如下:if(i&lt;=row-2 &amp;&amp; j&lt;= width-2) 但结果是一样的!

标签: python image-processing python-imaging-library opencl pyopencl


【解决方案1】:

我认为问题在于您传递给内核的输入和输出缓冲区的大小。图像是每个像素一个uint8,您根据data.nbytes 调整缓冲区大小。内核正在读写 4 字节像素。

我只需要更改这一行就可以了:

data = np.asarray(image).astype(np.int32)

【讨论】:

  • 我明白了...非常感谢!虽然我设法从 OpenCL Parallel Programming Development Cookbook -- Chapter 6 重写了内核……但它显示了水平线……但是我想我应该坚持使用我自己的内核。
  • 只需将内核中的乘法系数旋转 90 度。
猜你喜欢
  • 1970-01-01
  • 2012-10-17
  • 2018-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-20
  • 2013-03-28
相关资源
最近更新 更多