使用 PyOpenCL 进行边缘检测
Edge Detection using PyOpenCL
我在编写 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;
}
现在没有 运行 时间 warnings/errors 但输出是我没有预料到的。这是输入及其输出:
这是我的输入图像:
这是我的输出:
我认为问题在于您传递给内核的输入和输出缓冲区的大小。该图像每个像素 uint8
,您根据 data.nbytes
调整缓冲区大小。内核正在读写4字节像素。
我只需要更改这一行就可以了:
data = np.asarray(image).astype(np.int32)
我在编写 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;
}
现在没有 运行 时间 warnings/errors 但输出是我没有预料到的。这是输入及其输出: 这是我的输入图像:
这是我的输出:
我认为问题在于您传递给内核的输入和输出缓冲区的大小。该图像每个像素 uint8
,您根据 data.nbytes
调整缓冲区大小。内核正在读写4字节像素。
我只需要更改这一行就可以了:
data = np.asarray(image).astype(np.int32)