有许多pyopencl的教程脚本实现了一个内核掩码宽度为3的中值过滤器。我想扩展这段代码以允许改变过滤器的掩码宽度
我有两个测试实现,使用我可以编写的最简单的暴力排序算法。下面我共享的第一个文件是一个工作过程脚本。后者是从该脚本创建的函数。程序脚本在我可以访问的各种机器上最新版本的pyopencl(2019.1)上工作。该函数返回(大部分)零的数组
注1:中值滤波器的这种实现方式计算图像内部像素的中值,仅保留边界附近的像素。这个细节显示在问题中,因为显示在边界附近的线程只返回原始图像的像素值而没有问题。是靠近内部的线返回0
注2:您会注意到,我将源字符串分解为一个硬编码整数,将其传递到中值滤波器的掩码大小中(过程脚本中的第41行)。我了解到,我不允许在函数中简单地“创建”一个可以动态调整大小的数组。不过,用整数硬编码似乎效果不错(如果有人有什么建议,我会很高兴读到。我很清楚它看起来有多粗糙。)
注3:如果运行这些代码,可能需要操作设备的索引。当然,任何可以被scipy读取的光栅图形都可以正常工作
#procedural_median_filter.py
import pyopencl as cl
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import imread, imsave
filter_radius = 5
img = imread('test.jpg',flatten=True).astype(np.float32)
plat = cl.get_platforms()
devices = plat[0].get_devices()
CPU = [devices[0]]
try:
GPU = [devices[2]]
except IndexError:
GPU = "none"
if GPU!= "none":
ctx = cl.Context(GPU)
else:
ctx = cl.Context(CPU)
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags
src = """
__kernel void medianFilter(__global float *img, __global float *result, __global int *width, __global int *height, __global int *filter_radius)
{
int w = *width;
int h = *height;
int rad = *filter_radius;
int mask_size = (2*rad + 1)*(2*rad+1);
int median_index = mask_size / 2;
int posx = get_global_id(1);
int posy = get_global_id(0);
int i = w*posy + posx;
// Keeping the edge pixels the same
if( posx < rad || posy < rad || posx > w-rad || posy > h-rad){
result[i] = img[i];
}
else{
int mask[""" + str(int((2*filter_radius+1)**2)) + """];
int mask_index = 0;
int mask_position;
for(int maski = -rad; maski < rad+1; maski++){
for(int maskj = -rad; maskj < rad+1; maskj++){
mask_position = w*(posy - maskj) + (posx - maski);
mask[mask_index] = img[mask_position];
mask_index = mask_index +1;
}
}
int keyval;
int maskj;
for(int maski = 1; maski< mask_size; maski++){
for(maskj=maski+1; maskj< mask_size; maskj++){
if(mask[maskj]<mask[maski]){
keyval = mask[maski];
mask[maski] = mask[maskj];
mask[maskj] = keyval;
}
}
}
result[i] = mask[median_index];
}
}
"""
prg = cl.Program(ctx, src).build()
img_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=img)
result_g = cl.Buffer(ctx, mf.WRITE_ONLY, img.nbytes)
width_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=np.int32(img.shape[1]))
height_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=np.int32(img.shape[0]))
radius_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf = np.int32(filter_radius))
prg.medianFilter(queue, img.shape, None , img_g, result_g, width_g, height_g, radius_g)
result = np.empty_like(img)
cl.enqueue_copy(queue, result, result_g)
plt.imsave('medianFilter-OpenCL.jpg',result,cmap='gray')
下面的函数将返回一个图像,其中边界像素(直到过滤半径的宽度)与原始图像相同,但内部将返回零
#median_filter_function.py
import pyopencl as cl
import numpy as np
def gpu_median_filtering(img,filter_radius):
plat = cl.get_platforms()
devices = plat[0].get_devices()
CPU = [devices[0]]
try:
GPU = [devices[2]]
except IndexError:
GPU = "none"
if GPU!= "none":
ctx = cl.Context(GPU)
else:
ctx = cl.Context(CPU)
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags
src = """
__kernel void medianFilter(__global float *img, __global float *result, __global int *width, __global int *height, __global int *filter_radius)
{
int w = *width;
int h = *height;
int rad = *filter_radius;
int mask_size = (2*rad + 1)*(2*rad+1);
int median_index = mask_size / 2;
int posx = get_global_id(1);
int posy = get_global_id(0);
int i = w*posy + posx;
// Keeping the edge pixels the same
if( posx < rad || posy < rad || posx > w-rad || posy > h-rad){
result[i] = img[i];
}
else{
int mask[""" + str(int((2*filter_radius+1)**2)) + """];
int mask_index = 0;
int mask_position;
for(int maski = -rad; maski < rad+1; maski++){
for(int maskj = -rad; maskj < rad+1; maskj++){
mask_position = w*(posy - maskj) + (posx - maski);
mask[mask_index] = img[mask_position];
mask_index = mask_index +1;
}
}
int keyval;
int maskj;
for(int maski = 1; maski< mask_size; maski++){
for(maskj=maski+1; maskj< mask_size; maskj++){
if(mask[maskj]<mask[maski]){
keyval = mask[maski];
mask[maski] = mask[maskj];
mask[maskj] = keyval;
}
}
}
result[i] = mask[median_index];
}
}
"""
prg = cl.Program(ctx, src).build()
img_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=img)
result_g = cl.Buffer(ctx, mf.WRITE_ONLY, img.nbytes)
width_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=np.int32(img.shape[1]))
height_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=np.int32(img.shape[0]))
radius_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf = np.int32(filter_radius))
prg.medianFilter(queue, img.shape, None , img_g, result_g, width_g, height_g, radius_g)
result = np.empty_like(img)
cl.enqueue_copy(queue, result, result_g)
return result
谢谢你的时间
目前没有回答
相关问题 更多 >
编程相关推荐