Image Processing - Median Filter

Example leverages OpenCL to apply a medan filter to an image pixel-by-pixel in parallel. AMD's OpenCL documentation was used in the making of this example.

www.github.com/shahzaibgill

License of this example:

Date:

10/08/2016

PyOpenCL version:

2016.1

OpenCL implementations (and versions) tried:

Intel,Nvidia

   1 import pyopencl as cl
   2 import numpy as np
   3 from scipy.misc import imread, imsave
   4 
   5 #Read in image
   6 img = imread('noisyImage.jpg', flatten=True).astype(np.float32)
   7 
   8 # Get platforms, both CPU and GPU
   9 plat = cl.get_platforms()
  10 CPU = plat[0].get_devices()
  11 try:
  12     GPU = plat[1].get_devices()
  13 except IndexError:
  14     GPU = "none"
  15 
  16 #Create context for GPU/CPU
  17 if GPU!= "none":
  18     ctx = cl.Context(GPU)
  19 else:
  20     ctx = cl.Context(CPU)
  21 
  22 # Create queue for each kernel execution
  23 queue = cl.CommandQueue(ctx)
  24 
  25 mf = cl.mem_flags
  26 
  27 # Kernel function
  28 src = '''
  29 void sort(int *a, int *b, int *c) {
  30    int swap;
  31    if(*a > *b) {
  32       swap = *a;
  33       *a = *b;
  34       *b = swap;
  35    }
  36    if(*a > *c) {
  37       swap = *a;
  38       *a = *c;
  39       *c = swap;
  40    }
  41    if(*b > *c) {
  42       swap = *b;
  43       *b = *c;
  44       *c = swap;
  45    }
  46 }
  47 __kernel void medianFilter(__global float *img, __global float *result, __global int *width, __global int *height)
  48 {
  49     int w = *width;
  50     int h = *height;
  51     int posx = get_global_id(1);
  52     int posy = get_global_id(0);
  53     int i = w*posy + posx;
  54     // Keeping the edge pixels the same
  55     if( posx == 0 || posy == 0 || posx == w-1 || posy == h-1 )
  56     {
  57         result[i] = img[i];
  58     }
  59     else
  60     {
  61         int pixel00, pixel01, pixel02, pixel10, pixel11, pixel12, pixel20, pixel21, pixel22;
  62         pixel00 = img[i - 1 - w];
  63         pixel01 = img[i- w];
  64         pixel02 = img[i + 1 - w];
  65         pixel10 = img[i - 1];
  66         pixel11 = img[i];
  67         pixel12 = img[i + 1];
  68         pixel20 = img[i - 1 + w];
  69         pixel21 = img[i + w];
  70         pixel22 = img[i + 1 + w];
  71         //sort the rows
  72         sort( &(pixel00), &(pixel01), &(pixel02) );
  73         sort( &(pixel10), &(pixel11), &(pixel12) );
  74         sort( &(pixel20), &(pixel21), &(pixel22) );
  75         //sort the columns
  76         sort( &(pixel00), &(pixel10), &(pixel20) );
  77         sort( &(pixel01), &(pixel11), &(pixel21) );
  78         sort( &(pixel02), &(pixel12), &(pixel22) );
  79         //sort the diagonal
  80         sort( &(pixel00), &(pixel11), &(pixel22) );
  81         // median is the the middle value of the diagonal
  82         result[i] = pixel11;
  83     }
  84 }
  85 '''
  86 
  87 #Kernel function instantiation
  88 prg = cl.Program(ctx, src).build()
  89 #Allocate memory for variables on the device
  90 img_g =  cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=img)
  91 result_g = cl.Buffer(ctx, mf.WRITE_ONLY, img.nbytes)
  92 width_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=np.int32(img.shape[1]))
  93 height_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=np.int32(img.shape[0]))
  94 # Call Kernel. Automatically takes care of block/grid distribution
  95 prg.medianFilter(queue, img.shape, None , img_g, result_g, width_g, height_g)
  96 result = np.empty_like(img)
  97 cl.enqueue_copy(queue, result, result_g)
  98 
  99 # Show the blurred image
 100 imsave('medianFilter-OpenCL.jpg',result)


CategoryPyOpenCl CategoryPyOpenCl

PyOpenCL/Examples/MedianFilter (last edited 2017-11-30 00:49:47 by 2601:186:201:720c:5d98:85d9:d5c1:d2ad)