Changes

Jump to: navigation, search

PIL Cuda

3,295 bytes added, 15:08, 10 December 2014
Progress
== Team Members ==
# [mailto:gcastrolondono@senecacollege.ca?subject=gpu610 Gabriel Castro]
== Progress Pillow and Guassian Blur in CUDA == === Pillow === [https://python-pillow.github.io/ Pillow] is an imaging processing is a a library written in python with much of the processing done in C.Pillow has many filters that can be applied to an image to change or distort it.For this project I chose to optimize the Gaussian Blur filter,because after some profiling I determined that it is the single filter with the highest run time. ==== sample ====  #!/usr/bin/env python from PIL import Image, ImageFilter im = Image.open("test.png") filtered = im.filter(ImageFilter.GaussianBlur(5)) filtered.save("out.png") ===The Gaussian Blur=== The Gaussian Blur filter is an algorithm applied to images to make them blurry and/or reducing noise.The algorithm works on every pixel and colour channel (RGBA) in the image individually.For any given pixel (x,y) take the weighted average of all the pixels in a given radius (r). Given an image of size `x * y` with `c` channels and a blur radius of `r` pixels. There are `x * y * c * (r * r + 1)` floating point operations. This means a change in any dimension will result in an exponential increase. ex. a 800x600 RGB image with a 5px blur radius will have 600*800*3*(5*5+1) = 37,440,000 floating point ops ====optimization 1==== We can actually reduce the number of radius based operations by process sing the image in 2 steps. 1. Blur every pixel but only along the `x` axis, and store in a temporary buffer. 2. Blur every pixel in the temporary buffer along the `y` axis, store in result buffer.    ===CUDA with Python setup tools=== Since Pillow is a python library that uses [http://cython.org/ cython] built via setup tools we need to find a way to inject the nvcc compiler for CUDA. I was able to get everything working by modifying a script I found online, see the final version [https://github.com/GabrielCastro/Pillow/blob/master/setup_cuda.py here] and adding the this code to the existing build script   _LIB_IMAGING_CUDA = ["UnsharpMaskCuda"] have_cuda = False CUDA = None try: import setup_cuda CUDA = setup_cuda.CUDA have_cuda = True except EnvironmentError as e: print('CUDA not found') print(e) if have_cuda: defs.append(("HAVE_CUDA", 1)) setup_cuda.customize_compiler_for_nvcc(self.compiler) for f in _LIB_IMAGING_CUDA: files.append('libImaging/' + f + '.cu') libs.append('cudart') libs.append('stdc++') _add_directory(self.compiler.include_dirs, 'libImaging/')   NOTE. This requires $CUDAHOME to be set to /usr/local/cuda or appropriate and PATH to include $CUDAHOME/bin and LD_LIBRARY_PATH to include $CUDAHOME/lib64 * tested on Ubuntu 14.04 with CUDA 6.5  ===Pillow C Api=== The Pillow library has a C api that can for the purposes of this post be described with the following code.  struct _Imaing { int xsize; int ysize; // y-sized array of pointers to x-sized arrays of (UINT8) pixel data UINT8** image8; } typedef _Imaging* Imaging; Imaging gblur(Imaging im, Imaging imOut, float floatRadius);  This is rather simplified, as the `Imaging` struct contains many more properties and we're taking advantage of the fact that the library separates an incoming image into separate `Imaging` structs for each colour channel.

Navigation menu