diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..75c11dc Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 29f4b9f..9a67c43 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -#Pyblur -##Python image blurring routines. +# Pyblur +## Python image blurring routines. Pyblur is a collection of simple image blurring routines.
It supports Gaussian, Disk, Box, and Linear Motion Blur Kernels as well as the Point Spread Functions used in [Convolutional Neural Networks for Direct Text Deblurring](http://www.fit.vutbr.cz/~ihradis/CNN-Deblur/).
@@ -11,14 +11,14 @@ pypi: [https://pypi.python.org/pypi?:action=display&name=pyblur&version=0.2.3](h -##Installation +## Installation From Pip: `pip install pyblur`
-Or alternatively `git clone` this repo and run locally +Or alternatively `git clone` this repo and run `python3 setup.py install` to install. -##Usage +## Usage from pyblur import * -###Gaussian Blur +### Gaussian Blur Blurs image using a Gaussian Kernel blurred = GaussianBlur(img, bandwidth) @@ -27,7 +27,7 @@ Randomized kernel bandwidth (between 0.5 and 3.5) blurred = GaussianBlur_random(img) -###Defocus (Disk) Blur +### Defocus (Disk) Blur Blurs image using a Disk Kernel blurred = DefocusBlur(img, kernelsize) @@ -37,7 +37,7 @@ Randomized kernel size (between 3 and 9) blurred = DefocusBlur_random(img) -###Box Blur +### Box Blur Blurs image using a Box Kernel blurred = BoxBlur(img, kernelsize) @@ -47,12 +47,12 @@ Randomized kernel size (between 3 and 9) blurred = BoxBlur_random(img) -###Linear Motion Blur +### Linear Motion Blur Blurs image using a Line Kernel blurred = LinearMotionBlur(img, dim, angle, linetype) -####Parameters +#### Parameters * `dim` Kernel Size: {3,5,7,9}
* `angle` Angle of the line of motion. Will be floored to the closest one available for the given kernel size.
* `linetype = {left, right, full}` Controls whether the blur kernel will be applied in full or only the left/right halves of it.
@@ -67,7 +67,7 @@ Blurs image using one of the Point Spread Functions (Kernels) used in:
blurred = PsfBlur(img, psfid) -####Parameters +#### Parameters * `psfid` Id of the Point Spread Function to apply [0, 99]
@@ -76,7 +76,7 @@ Randomized kernel size, angle, and line type blurred = PsfBlur_random(img) -###Random Blur +### Random Blur Randomly applies one of the supported blur types, with a randomized bandwidth/strenght. - blurred = RandomizedBlur(img) \ No newline at end of file + blurred = RandomizedBlur(img) diff --git a/pyblur/BoxBlur.py b/pyblur/BoxBlur.py index 4b64cc9..da24ce9 100644 --- a/pyblur/BoxBlur.py +++ b/pyblur/BoxBlur.py @@ -2,23 +2,27 @@ from PIL import Image from scipy.signal import convolve2d -boxKernelDims = [3,5,7,9] +boxKernelDims = [3, 5, 7, 9] + def BoxBlur_random(img): - kernelidx = np.random.randint(0, len(boxKernelDims)) + kernelidx = np.random.randint(0, len(boxKernelDims)) kerneldim = boxKernelDims[kernelidx] return BoxBlur(img, kerneldim) + def BoxBlur(img, dim): imgarray = np.array(img, dtype="float32") kernel = BoxKernel(dim) - convolved = convolve2d(imgarray, kernel, mode='same', fillvalue=255.0).astype("uint8") + convolved = convolve2d(imgarray, kernel, mode='same', + fillvalue=255.0).astype("uint8") img = Image.fromarray(convolved) return img + def BoxKernel(dim): kernelwidth = dim - kernel = np.ones((kernelwidth, kernelwidth), dtype=np.float32) + kernel = np.ones((kernelwidth, kernelwidth), dtype=np.float32) normalizationFactor = np.count_nonzero(kernel) kernel = kernel / normalizationFactor - return kernel \ No newline at end of file + return kernel diff --git a/pyblur/DefocusBlur.py b/pyblur/DefocusBlur.py index 28f7aa6..d6fc0a5 100644 --- a/pyblur/DefocusBlur.py +++ b/pyblur/DefocusBlur.py @@ -4,17 +4,20 @@ from scipy.signal import convolve2d from skimage.draw import circle -defocusKernelDims = [3,5,7,9] +defocusKernelDims = [3, 5, 7, 9] + def DefocusBlur_random(img): - kernelidx = np.random.randint(0, len(defocusKernelDims)) + kernelidx = np.random.randint(0, len(defocusKernelDims)) kerneldim = defocusKernelDims[kernelidx] return DefocusBlur(img, kerneldim) + def DefocusBlur(img, dim): imgarray = np.array(img, dtype="float32") kernel = DiskKernel(dim) - convolved = convolve2d(imgarray, kernel, mode='same', fillvalue=255.0).astype("uint8") + convolved = convolve2d(imgarray, kernel, mode='same', + fillvalue=255.0).astype("uint8") img = Image.fromarray(convolved) return img @@ -23,21 +26,22 @@ def DiskKernel(dim): kernelwidth = dim kernel = np.zeros((kernelwidth, kernelwidth), dtype=np.float32) circleCenterCoord = dim / 2 - circleRadius = circleCenterCoord +1 - + circleRadius = circleCenterCoord + 1 + rr, cc = circle(circleCenterCoord, circleCenterCoord, circleRadius) - kernel[rr,cc]=1 - + kernel[rr, cc] = 1 + if(dim == 3 or dim == 5): kernel = Adjust(kernel, dim) - + normalizationFactor = np.count_nonzero(kernel) kernel = kernel / normalizationFactor return kernel + def Adjust(kernel, kernelwidth): - kernel[0,0] = 0 - kernel[0,kernelwidth-1]=0 - kernel[kernelwidth-1,0]=0 - kernel[kernelwidth-1, kernelwidth-1] =0 - return kernel \ No newline at end of file + kernel[0, 0] = 0 + kernel[0, kernelwidth-1] = 0 + kernel[kernelwidth-1, 0] = 0 + kernel[kernelwidth-1, kernelwidth-1] = 0 + return kernel diff --git a/pyblur/GaussianBlur.py b/pyblur/GaussianBlur.py index 6e39b93..5628f35 100644 --- a/pyblur/GaussianBlur.py +++ b/pyblur/GaussianBlur.py @@ -1,13 +1,14 @@ import numpy as np from PIL import ImageFilter -gaussianbandwidths = [0.5, 1, 1.5, 2, 2.5, 3, 3.5] +# gaussianbandwidths = [1, 1.5, 2] #, 2, 2.5, 3, 3.5] +gaussianbandwidths = np.random.choice([1, 1.5, 2], 1, p=[0.5, 0.3, 0.2])[0] + def GaussianBlur_random(img): - gaussianidx = np.random.randint(0, len(gaussianbandwidths)) - gaussianbandwidth = gaussianbandwidths[gaussianidx] - return GaussianBlur(img, gaussianbandwidth) + return GaussianBlur(img, np.random.choice([1, 1.5, 2], 1, p=[0.5, 0.3, 0.2])[0]) + def GaussianBlur(img, bandwidth): img = img.filter(ImageFilter.GaussianBlur(bandwidth)) - return img \ No newline at end of file + return img diff --git a/pyblur/LineDictionary.py b/pyblur/LineDictionary.py index a61d7dd..1f1c480 100644 --- a/pyblur/LineDictionary.py +++ b/pyblur/LineDictionary.py @@ -6,63 +6,63 @@ def __init__(self): self.Create7x7Lines() self.Create9x9Lines() return - + def Create3x3Lines(self): lines = {} - lines[0] = [1,0,1,2] - lines[45] = [2,0,0,2] - lines[90] = [0,1,2,1] - lines[135] = [0,0,2,2] + lines[0] = [1, 0, 1, 2] + lines[45] = [2, 0, 0, 2] + lines[90] = [0, 1, 2, 1] + lines[135] = [0, 0, 2, 2] self.lines[3] = lines return - + def Create5x5Lines(self): - lines = {} - lines[0] = [2,0,2,4] - lines[22.5] = [3,0,1,4] - lines[45] = [0,4,4,0] - lines[67.5] = [0,3,4,1] - lines[90] = [0,2,4,2] - lines[112.5] = [0,1,4,3] - lines[135] = [0,0,4,4] - lines[157.5]= [1,0,3,4] + lines = {} + lines[0] = [2, 0, 2, 4] + lines[22.5] = [3, 0, 1, 4] + lines[45] = [0, 4, 4, 0] + lines[67.5] = [0, 3, 4, 1] + lines[90] = [0, 2, 4, 2] + lines[112.5] = [0, 1, 4, 3] + lines[135] = [0, 0, 4, 4] + lines[157.5] = [1, 0, 3, 4] self.lines[5] = lines return - + def Create7x7Lines(self): lines = {} - lines[0] = [3,0,3,6] - lines[15] = [4,0,2,6] - lines[30] = [5,0,1,6] - lines[45] = [6,0,0,6] - lines[60] = [6,1,0,5] - lines[75] = [6,2,0,4] - lines[90] = [0,3,6,3] - lines[105] = [0,2,6,4] - lines[120] = [0,1,6,5] - lines[135] = [0,0,6,6] - lines[150] = [1,0,5,6] - lines[165] = [2,0,4,6] - self.lines[7] = lines + lines[0] = [3, 0, 3, 6] + lines[15] = [4, 0, 2, 6] + lines[30] = [5, 0, 1, 6] + lines[45] = [6, 0, 0, 6] + lines[60] = [6, 1, 0, 5] + lines[75] = [6, 2, 0, 4] + lines[90] = [0, 3, 6, 3] + lines[105] = [0, 2, 6, 4] + lines[120] = [0, 1, 6, 5] + lines[135] = [0, 0, 6, 6] + lines[150] = [1, 0, 5, 6] + lines[165] = [2, 0, 4, 6] + self.lines[7] = lines return - + def Create9x9Lines(self): lines = {} - lines[0] = [4,0,4,8] - lines[11.25] = [5,0,3,8] - lines[22.5] = [6,0,2,8] - lines[33.75] = [7,0,1,8] - lines[45] = [8,0,0,8] - lines[56.25] = [8,1,0,7] - lines[67.5] = [8,2,0,6] - lines[78.75] = [8,3,0,5] - lines[90] = [8,4,0,4] - lines[101.25] = [0,3,8,5] - lines[112.5] = [0,2,8,6] - lines[123.75] = [0,1,8,7] - lines[135] = [0,0,8,8] - lines[146.25] = [1,0,7,8] - lines[157.5] = [2,0,6,8] - lines[168.75] = [3,0,5,8] + lines[0] = [4, 0, 4, 8] + lines[11.25] = [5, 0, 3, 8] + lines[22.5] = [6, 0, 2, 8] + lines[33.75] = [7, 0, 1, 8] + lines[45] = [8, 0, 0, 8] + lines[56.25] = [8, 1, 0, 7] + lines[67.5] = [8, 2, 0, 6] + lines[78.75] = [8, 3, 0, 5] + lines[90] = [8, 4, 0, 4] + lines[101.25] = [0, 3, 8, 5] + lines[112.5] = [0, 2, 8, 6] + lines[123.75] = [0, 1, 8, 7] + lines[135] = [0, 0, 8, 8] + lines[146.25] = [1, 0, 7, 8] + lines[157.5] = [2, 0, 6, 8] + lines[168.75] = [3, 0, 5, 8] self.lines[9] = lines - return \ No newline at end of file + return diff --git a/pyblur/LinearMotionBlur.py b/pyblur/LinearMotionBlur.py index 48a29f3..22f3400 100644 --- a/pyblur/LinearMotionBlur.py +++ b/pyblur/LinearMotionBlur.py @@ -5,28 +5,32 @@ from scipy.signal import convolve2d from skimage.draw import line -from LineDictionary import LineDictionary +from .LineDictionary import LineDictionary -lineLengths =[3,5,7,9] +lineLengths = [3, 5, 7, 9] lineTypes = ["full", "right", "left"] lineDict = LineDictionary() + def LinearMotionBlur_random(img): lineLengthIdx = np.random.randint(0, len(lineLengths)) - lineTypeIdx = np.random.randint(0, len(lineTypes)) + lineTypeIdx = np.random.randint(0, len(lineTypes)) lineLength = lineLengths[lineLengthIdx] lineType = lineTypes[lineTypeIdx] lineAngle = randomAngle(lineLength) return LinearMotionBlur(img, lineLength, lineAngle, lineType) + def LinearMotionBlur(img, dim, angle, linetype): imgarray = np.array(img, dtype="float32") kernel = LineKernel(dim, angle, linetype) - convolved = convolve2d(imgarray, kernel, mode='same', fillvalue=255.0).astype("uint8") + convolved = convolve2d(imgarray, kernel, mode='same', + fillvalue=255.0).astype("uint8") img = Image.fromarray(convolved) return img + def LineKernel(dim, angle, linetype): kernelwidth = dim kernelCenter = int(math.floor(dim/2)) @@ -39,26 +43,30 @@ def LineKernel(dim, angle, linetype): if(linetype == 'left'): lineAnchors[2] = kernelCenter lineAnchors[3] = kernelCenter - rr,cc = line(lineAnchors[0], lineAnchors[1], lineAnchors[2], lineAnchors[3]) - kernel[rr,cc]=1 + rr, cc = line(lineAnchors[0], lineAnchors[1], + lineAnchors[2], lineAnchors[3]) + kernel[rr, cc] = 1 normalizationFactor = np.count_nonzero(kernel) - kernel = kernel / normalizationFactor + kernel = kernel / normalizationFactor return kernel + def SanitizeAngleValue(kernelCenter, angle): numDistinctLines = kernelCenter * 4 angle = math.fmod(angle, 180.0) - validLineAngles = np.linspace(0,180, numDistinctLines, endpoint = False) + validLineAngles = np.linspace(0, 180, numDistinctLines, endpoint=False) angle = nearestValue(angle, validLineAngles) return angle + def nearestValue(theta, validAngles): idx = (np.abs(validAngles-theta)).argmin() return validAngles[idx] + def randomAngle(kerneldim): kernelCenter = int(math.floor(kerneldim/2)) numDistinctLines = kernelCenter * 4 - validLineAngles = np.linspace(0,180, numDistinctLines, endpoint = False) + validLineAngles = np.linspace(0, 180, numDistinctLines, endpoint=False) angleIdx = np.random.randint(0, len(validLineAngles)) - return int(validLineAngles[angleIdx]) \ No newline at end of file + return int(validLineAngles[angleIdx]) diff --git a/pyblur/PsfBlur.py b/pyblur/PsfBlur.py index 48c9b70..cb6019e 100644 --- a/pyblur/PsfBlur.py +++ b/pyblur/PsfBlur.py @@ -5,21 +5,21 @@ from scipy.signal import convolve2d import os.path -pickledPsfFilename =os.path.join(os.path.dirname( __file__),"psf.pkl") +pickledPsfFilename = os.path.join(os.path.dirname(__file__), "psf.pkl") with open(pickledPsfFilename, 'rb') as pklfile: - psfDictionary = pickle.load(pklfile) + psfDictionary = pickle.load(pklfile, encoding='latin1') def PsfBlur(img, psfid): imgarray = np.array(img, dtype="float32") kernel = psfDictionary[psfid] - convolved = convolve2d(imgarray, kernel, mode='same', fillvalue=255.0).astype("uint8") + convolved = convolve2d(imgarray, kernel, mode='same', + fillvalue=255.0).astype("uint8") img = Image.fromarray(convolved) return img - + + def PsfBlur_random(img): psfid = np.random.randint(0, len(psfDictionary)) return PsfBlur(img, psfid) - - diff --git a/pyblur/RandomizedBlur.py b/pyblur/RandomizedBlur.py index ca5e7dd..0f99d80 100644 --- a/pyblur/RandomizedBlur.py +++ b/pyblur/RandomizedBlur.py @@ -1,12 +1,17 @@ import numpy as np -from BoxBlur import BoxBlur_random -from DefocusBlur import DefocusBlur_random -from GaussianBlur import GaussianBlur_random -from LinearMotionBlur import LinearMotionBlur_random -from PsfBlur import PsfBlur_random +from .BoxBlur import BoxBlur_random +from .DefocusBlur import DefocusBlur_random +from .GaussianBlur import GaussianBlur_random +from .LinearMotionBlur import LinearMotionBlur_random +from .PsfBlur import PsfBlur_random + + +blurFunctions = {"0": BoxBlur_random, "1": DefocusBlur_random, + "2": GaussianBlur_random, "3": LinearMotionBlur_random, "4": PsfBlur_random} -blurFunctions = {"0": BoxBlur_random, "1": DefocusBlur_random, "2": GaussianBlur_random, "3": LinearMotionBlur_random, "4": PsfBlur_random} def RandomizedBlur(img): - blurToApply = blurFunctions[str(np.random.randint(0, len(blurFunctions)))] - return blurToApply(img) \ No newline at end of file + choice = np.random.choice(len(blurFunctions), 1, p=[ + 0.00, 0.00, 0.3, 0.2, 0.5])[0] + blurToApply = blurFunctions[str(choice)] + return blurToApply(img) diff --git a/setup.py b/setup.py index 0470d47..5da96cc 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ long_description = f.read() setup(name='pyblur', - version = '0.2.3', + version = '0.2.4', description = 'Image blurring routines', long_description = long_description, keywords = 'blur', @@ -18,6 +18,7 @@ 'Intended Audience :: Developers', 'Intended Audience :: Science/Research', 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.6', 'Topic :: Multimedia :: Graphics'], url='http://github.com/lospooky/pyblur', author='lospooky', @@ -26,4 +27,4 @@ packages=find_packages(), include_package_data=True, install_requires = ['numpy', 'pillow', 'scikit-image', 'scipy'], - zip_safe = False) \ No newline at end of file + zip_safe = False)