From 3fb20706cee65169d01a62a5db530ad57b4f80f1 Mon Sep 17 00:00:00 2001 From: Praveen Date: Mon, 24 Feb 2020 02:21:19 +0530 Subject: [PATCH 1/8] Added Bilateral filter --- .../filters/bilateral_filter.py | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 digital_image_processing/filters/bilateral_filter.py diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py new file mode 100644 index 000000000000..592db11730f3 --- /dev/null +++ b/digital_image_processing/filters/bilateral_filter.py @@ -0,0 +1,78 @@ +''' +Implementation of Bilateral filter + +Inputs: + img: A 2d image with values in between 0 and 1 + varS: variance in space dimension. + varI: variance in Intensity. + N: Kernel size(Must be an odd number) +Output: + img:A 2d zero padded image with values in between 0 and 1 +''' + +import cv2 +import numpy as np +import math +import sys + +def vec_gaussian(img, var): + # For applying gaussian function for each element in matrix. + sigma = math.sqrt(var) + cons = 1/(sigma*math.sqrt(2*math.pi)) + fImg = cons*np.exp(-((img/sigma)**2)*0.5) + return fImg + +def getSlice(img,x,y, N): + return img[x-N//2:x+N//2+1,y-N//2:y+N//2+1] + +def getGaussKernel(N, varS): + # Creates a gaussian kernel of given dimension. + arr = np.zeros((N,N)) + for i in range(0,N): + for j in range(0,N): + arr[i,j] = math.sqrt(abs(i-N//2)**2 + abs(j-N//2)**2) + arr = vec_gaussian(arr,varS) + return arr + +def bilateral_filter(img, varS, varI, N): + img2 = np.zeros(img.shape) + gaussKer = getGaussKernel(N,varS) + sizeX,sizeY = img.shape + for i in range(N//2, sizeX-N//2): + for j in range(N//2, sizeY-N//2): + + imgS = getSlice(img,i,j,N) + imgI = imgS-imgS[N//2,N//2] + imgIG = vec_gaussian(imgI, varI) + weights = np.multiply(gaussKer,imgIG) + vals = np.multiply(imgS,weights) + val = np.sum(vals)/np.sum(weights) + img2[i,j] = val + return img2 + +if __name__ == '__main__': + filename = '../image_data/lena.jpg' + varS = 1 + varI = 1 + N = 5 + if(len(sys.argv) >= 2): + filename = sys.argv[1] + if(len(sys.argv) >= 3): + varS = float(sys.argv[2]) + if(len(sys.argv) >= 4): + varI = float(sys.argv[3]) + if(len(sys.argv) >= 5): + N = int(sys.argv[4]) + N = N + abs(N%2-1) + + img = cv2.imread(filename,0) + cv2.imshow('input image',img) + + out = img/255 + out = out.astype('float32') + out = bilateral_filter(out, varS, varI, N) + out = out*255 + out = np.uint8(out) + cv2.imshow('gray output',out) + cv2.waitKey(0) + cv2.destroyAllWindows() \ No newline at end of file From 7d4733a480e8b61ef399a5162edf299c6dbdb811 Mon Sep 17 00:00:00 2001 From: Praveen Date: Mon, 24 Feb 2020 02:22:32 +0530 Subject: [PATCH 2/8] Added Bilateral filter --- digital_image_processing/filters/bilateral_filter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py index 592db11730f3..79dd734e0de2 100644 --- a/digital_image_processing/filters/bilateral_filter.py +++ b/digital_image_processing/filters/bilateral_filter.py @@ -73,6 +73,6 @@ def bilateral_filter(img, varS, varI, N): out = bilateral_filter(out, varS, varI, N) out = out*255 out = np.uint8(out) - cv2.imshow('gray output',out) + cv2.imshow('output image',out) cv2.waitKey(0) cv2.destroyAllWindows() \ No newline at end of file From 2cbc17fbcb757724ca356c4ed376b59f9cfb57a6 Mon Sep 17 00:00:00 2001 From: Praveen Date: Mon, 24 Feb 2020 04:01:01 +0530 Subject: [PATCH 3/8] changed types of varS and varI --- digital_image_processing/filters/bilateral_filter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py index 79dd734e0de2..f7d26e6df2bf 100644 --- a/digital_image_processing/filters/bilateral_filter.py +++ b/digital_image_processing/filters/bilateral_filter.py @@ -52,8 +52,8 @@ def bilateral_filter(img, varS, varI, N): if __name__ == '__main__': filename = '../image_data/lena.jpg' - varS = 1 - varI = 1 + varS = 1.0 + varI = 1.0 N = 5 if(len(sys.argv) >= 2): filename = sys.argv[1] From 49890fedc887c82915f9479d8eba46f3e0b066e3 Mon Sep 17 00:00:00 2001 From: Praveen Date: Mon, 24 Feb 2020 04:32:33 +0530 Subject: [PATCH 4/8] formatted with black --- .../filters/bilateral_filter.py | 79 ++++++++++--------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py index f7d26e6df2bf..a92137f17d1f 100644 --- a/digital_image_processing/filters/bilateral_filter.py +++ b/digital_image_processing/filters/bilateral_filter.py @@ -1,4 +1,4 @@ -''' +""" Implementation of Bilateral filter Inputs: @@ -8,71 +8,76 @@ N: Kernel size(Must be an odd number) Output: img:A 2d zero padded image with values in between 0 and 1 -''' +""" import cv2 import numpy as np import math import sys + def vec_gaussian(img, var): # For applying gaussian function for each element in matrix. sigma = math.sqrt(var) - cons = 1/(sigma*math.sqrt(2*math.pi)) - fImg = cons*np.exp(-((img/sigma)**2)*0.5) + cons = 1 / (sigma * math.sqrt(2 * math.pi)) + fImg = cons * np.exp(-((img / sigma) ** 2) * 0.5) return fImg -def getSlice(img,x,y, N): - return img[x-N//2:x+N//2+1,y-N//2:y+N//2+1] + +def getSlice(img, x, y, N): + return img[x - N // 2 : x + N // 2 + 1, y - N // 2 : y + N // 2 + 1] + def getGaussKernel(N, varS): # Creates a gaussian kernel of given dimension. - arr = np.zeros((N,N)) - for i in range(0,N): - for j in range(0,N): - arr[i,j] = math.sqrt(abs(i-N//2)**2 + abs(j-N//2)**2) - arr = vec_gaussian(arr,varS) + arr = np.zeros((N, N)) + for i in range(0, N): + for j in range(0, N): + arr[i, j] = math.sqrt(abs(i - N // 2) ** 2 + abs(j - N // 2) ** 2) + arr = vec_gaussian(arr, varS) return arr + def bilateral_filter(img, varS, varI, N): img2 = np.zeros(img.shape) - gaussKer = getGaussKernel(N,varS) - sizeX,sizeY = img.shape - for i in range(N//2, sizeX-N//2): - for j in range(N//2, sizeY-N//2): - - imgS = getSlice(img,i,j,N) - imgI = imgS-imgS[N//2,N//2] + gaussKer = getGaussKernel(N, varS) + sizeX, sizeY = img.shape + for i in range(N // 2, sizeX - N // 2): + for j in range(N // 2, sizeY - N // 2): + + imgS = getSlice(img, i, j, N) + imgI = imgS - imgS[N // 2, N // 2] imgIG = vec_gaussian(imgI, varI) - weights = np.multiply(gaussKer,imgIG) - vals = np.multiply(imgS,weights) - val = np.sum(vals)/np.sum(weights) - img2[i,j] = val + weights = np.multiply(gaussKer, imgIG) + vals = np.multiply(imgS, weights) + val = np.sum(vals) / np.sum(weights) + img2[i, j] = val return img2 -if __name__ == '__main__': - filename = '../image_data/lena.jpg' + +if __name__ == "__main__": + filename = "../image_data/lena.jpg" varS = 1.0 varI = 1.0 N = 5 - if(len(sys.argv) >= 2): + if len(sys.argv) >= 2: filename = sys.argv[1] - if(len(sys.argv) >= 3): + if len(sys.argv) >= 3: varS = float(sys.argv[2]) - if(len(sys.argv) >= 4): + if len(sys.argv) >= 4: varI = float(sys.argv[3]) - if(len(sys.argv) >= 5): + if len(sys.argv) >= 5: N = int(sys.argv[4]) - N = N + abs(N%2-1) + N = N + abs(N % 2 - 1) + + img = cv2.imread(filename, 0) + cv2.imshow("input image", img) - img = cv2.imread(filename,0) - cv2.imshow('input image',img) - - out = img/255 - out = out.astype('float32') + out = img / 255 + out = out.astype("float32") out = bilateral_filter(out, varS, varI, N) - out = out*255 + out = out * 255 out = np.uint8(out) - cv2.imshow('output image',out) + cv2.imshow("output image", out) cv2.waitKey(0) - cv2.destroyAllWindows() \ No newline at end of file + cv2.destroyAllWindows() From db24381aa8223faa132bd14c85fdf333bde383c8 Mon Sep 17 00:00:00 2001 From: Praveen Date: Mon, 24 Feb 2020 04:53:04 +0530 Subject: [PATCH 5/8] added type hints --- digital_image_processing/filters/bilateral_filter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py index a92137f17d1f..5d36c9c7d65b 100644 --- a/digital_image_processing/filters/bilateral_filter.py +++ b/digital_image_processing/filters/bilateral_filter.py @@ -16,7 +16,7 @@ import sys -def vec_gaussian(img, var): +def vec_gaussian(img: np.ndarray, var: float) -> np.ndarray: # For applying gaussian function for each element in matrix. sigma = math.sqrt(var) cons = 1 / (sigma * math.sqrt(2 * math.pi)) @@ -24,11 +24,11 @@ def vec_gaussian(img, var): return fImg -def getSlice(img, x, y, N): +def getSlice(img: np.ndarray, x: int, y: int, N: int) -> np.ndarray: return img[x - N // 2 : x + N // 2 + 1, y - N // 2 : y + N // 2 + 1] -def getGaussKernel(N, varS): +def getGaussKernel(N: int, varS: float) -> np.ndarray: # Creates a gaussian kernel of given dimension. arr = np.zeros((N, N)) for i in range(0, N): @@ -38,7 +38,7 @@ def getGaussKernel(N, varS): return arr -def bilateral_filter(img, varS, varI, N): +def bilateral_filter(img: np.ndarray, varS: float, varI: float, N: int) -> np.ndarray: img2 = np.zeros(img.shape) gaussKer = getGaussKernel(N, varS) sizeX, sizeY = img.shape From f96ba4522daf2cee569211dca7e0e0a136a61aba Mon Sep 17 00:00:00 2001 From: Praveen Date: Mon, 24 Feb 2020 08:13:51 +0530 Subject: [PATCH 6/8] changed variable names --- .../filters/bilateral_filter.py | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py index 5d36c9c7d65b..13650e5df526 100644 --- a/digital_image_processing/filters/bilateral_filter.py +++ b/digital_image_processing/filters/bilateral_filter.py @@ -16,38 +16,48 @@ import sys -def vec_gaussian(img: np.ndarray, var: float) -> np.ndarray: +def vec_gaussian(img: np.ndarray, variance: float) -> np.ndarray: # For applying gaussian function for each element in matrix. - sigma = math.sqrt(var) + sigma = math.sqrt(variance) cons = 1 / (sigma * math.sqrt(2 * math.pi)) fImg = cons * np.exp(-((img / sigma) ** 2) * 0.5) return fImg -def getSlice(img: np.ndarray, x: int, y: int, N: int) -> np.ndarray: - return img[x - N // 2 : x + N // 2 + 1, y - N // 2 : y + N // 2 + 1] +def getSlice(img: np.ndarray, x: int, y: int, kernel_size: int) -> np.ndarray: + return img[ + x - kernel_size // 2 : x + kernel_size // 2 + 1, + y - kernel_size // 2 : y + kernel_size // 2 + 1, + ] -def getGaussKernel(N: int, varS: float) -> np.ndarray: +def getGaussKernel(kernel_size: int, spatial_variance: float) -> np.ndarray: # Creates a gaussian kernel of given dimension. - arr = np.zeros((N, N)) - for i in range(0, N): - for j in range(0, N): - arr[i, j] = math.sqrt(abs(i - N // 2) ** 2 + abs(j - N // 2) ** 2) - arr = vec_gaussian(arr, varS) + arr = np.zeros((kernel_size, kernel_size)) + for i in range(0, kernel_size): + for j in range(0, kernel_size): + arr[i, j] = math.sqrt( + abs(i - kernel_size // 2) ** 2 + abs(j - kernel_size // 2) ** 2 + ) + arr = vec_gaussian(arr, spatial_variance) return arr -def bilateral_filter(img: np.ndarray, varS: float, varI: float, N: int) -> np.ndarray: +def bilateral_filter( + img: np.ndarray, + spatial_variance: float, + intensity_variance: float, + kernel_size: int, +) -> np.ndarray: img2 = np.zeros(img.shape) - gaussKer = getGaussKernel(N, varS) + gaussKer = getGaussKernel(kernel_size, spatial_variance) sizeX, sizeY = img.shape - for i in range(N // 2, sizeX - N // 2): - for j in range(N // 2, sizeY - N // 2): + for i in range(kernel_size // 2, sizeX - kernel_size // 2): + for j in range(kernel_size // 2, sizeY - kernel_size // 2): - imgS = getSlice(img, i, j, N) - imgI = imgS - imgS[N // 2, N // 2] - imgIG = vec_gaussian(imgI, varI) + imgS = getSlice(img, i, j, kernel_size) + imgI = imgS - imgS[kernel_size // 2, kernel_size // 2] + imgIG = vec_gaussian(imgI, intensity_variance) weights = np.multiply(gaussKer, imgIG) vals = np.multiply(imgS, weights) val = np.sum(vals) / np.sum(weights) @@ -57,25 +67,25 @@ def bilateral_filter(img: np.ndarray, varS: float, varI: float, N: int) -> np.nd if __name__ == "__main__": filename = "../image_data/lena.jpg" - varS = 1.0 - varI = 1.0 - N = 5 + spatial_variance = 1.0 + intensity_variance = 1.0 + kernel_size = 5 if len(sys.argv) >= 2: filename = sys.argv[1] if len(sys.argv) >= 3: - varS = float(sys.argv[2]) + spatial_variance = float(sys.argv[2]) if len(sys.argv) >= 4: - varI = float(sys.argv[3]) + intensity_variance = float(sys.argv[3]) if len(sys.argv) >= 5: - N = int(sys.argv[4]) - N = N + abs(N % 2 - 1) + kernel_size = int(sys.argv[4]) + kernel_size = kernel_size + abs(kernel_size % 2 - 1) img = cv2.imread(filename, 0) cv2.imshow("input image", img) out = img / 255 out = out.astype("float32") - out = bilateral_filter(out, varS, varI, N) + out = bilateral_filter(out, spatial_variance, intensity_variance, kernel_size) out = out * 255 out = np.uint8(out) cv2.imshow("output image", out) From 0fbce232d77ec9f8f41be1d3cc03a0c0ece041fb Mon Sep 17 00:00:00 2001 From: vinayak Date: Mon, 24 Feb 2020 22:06:05 +0530 Subject: [PATCH 7/8] Update bilateral_filter.py --- digital_image_processing/filters/bilateral_filter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py index 13650e5df526..98e98d6d1b40 100644 --- a/digital_image_processing/filters/bilateral_filter.py +++ b/digital_image_processing/filters/bilateral_filter.py @@ -24,14 +24,14 @@ def vec_gaussian(img: np.ndarray, variance: float) -> np.ndarray: return fImg -def getSlice(img: np.ndarray, x: int, y: int, kernel_size: int) -> np.ndarray: +def get_slice(img: np.ndarray, x: int, y: int, kernel_size: int) -> np.ndarray: return img[ x - kernel_size // 2 : x + kernel_size // 2 + 1, y - kernel_size // 2 : y + kernel_size // 2 + 1, ] -def getGaussKernel(kernel_size: int, spatial_variance: float) -> np.ndarray: +def get_gauss_kernel(kernel_size: int, spatial_variance: float) -> np.ndarray: # Creates a gaussian kernel of given dimension. arr = np.zeros((kernel_size, kernel_size)) for i in range(0, kernel_size): @@ -50,12 +50,12 @@ def bilateral_filter( kernel_size: int, ) -> np.ndarray: img2 = np.zeros(img.shape) - gaussKer = getGaussKernel(kernel_size, spatial_variance) + gaussKer = get_gauss_kernel(kernel_size, spatial_variance) sizeX, sizeY = img.shape for i in range(kernel_size // 2, sizeX - kernel_size // 2): for j in range(kernel_size // 2, sizeY - kernel_size // 2): - imgS = getSlice(img, i, j, kernel_size) + imgS = get_slice(img, i, j, kernel_size) imgI = imgS - imgS[kernel_size // 2, kernel_size // 2] imgIG = vec_gaussian(imgI, intensity_variance) weights = np.multiply(gaussKer, imgIG) From bb3dc9ddf8e8b66321358e77848eb6638efd42c9 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 26 Feb 2020 07:54:30 +0100 Subject: [PATCH 8/8] Drop transitory variables, add parse_args() --- .../filters/bilateral_filter.py | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py index 98e98d6d1b40..753d6ddb7a3f 100644 --- a/digital_image_processing/filters/bilateral_filter.py +++ b/digital_image_processing/filters/bilateral_filter.py @@ -20,15 +20,12 @@ def vec_gaussian(img: np.ndarray, variance: float) -> np.ndarray: # For applying gaussian function for each element in matrix. sigma = math.sqrt(variance) cons = 1 / (sigma * math.sqrt(2 * math.pi)) - fImg = cons * np.exp(-((img / sigma) ** 2) * 0.5) - return fImg + return cons * np.exp(-((img / sigma) ** 2) * 0.5) def get_slice(img: np.ndarray, x: int, y: int, kernel_size: int) -> np.ndarray: - return img[ - x - kernel_size // 2 : x + kernel_size // 2 + 1, - y - kernel_size // 2 : y + kernel_size // 2 + 1, - ] + half = kernel_size // 2 + return img[x - half : x + half + 1, y - half : y + half + 1] def get_gauss_kernel(kernel_size: int, spatial_variance: float) -> np.ndarray: @@ -39,8 +36,7 @@ def get_gauss_kernel(kernel_size: int, spatial_variance: float) -> np.ndarray: arr[i, j] = math.sqrt( abs(i - kernel_size // 2) ** 2 + abs(j - kernel_size // 2) ** 2 ) - arr = vec_gaussian(arr, spatial_variance) - return arr + return vec_gaussian(arr, spatial_variance) def bilateral_filter( @@ -65,21 +61,20 @@ def bilateral_filter( return img2 -if __name__ == "__main__": - filename = "../image_data/lena.jpg" - spatial_variance = 1.0 - intensity_variance = 1.0 - kernel_size = 5 - if len(sys.argv) >= 2: - filename = sys.argv[1] - if len(sys.argv) >= 3: - spatial_variance = float(sys.argv[2]) - if len(sys.argv) >= 4: - intensity_variance = float(sys.argv[3]) - if len(sys.argv) >= 5: - kernel_size = int(sys.argv[4]) +def parse_args(args: list) -> tuple: + filename = args[1] if args[1:] else "../image_data/lena.jpg" + spatial_variance = float(args[2]) if args[2:] else 1.0 + intensity_variance = float(args[3]) if args[3:] else 1.0 + if args[4:]: + kernel_size = int(args[4]) kernel_size = kernel_size + abs(kernel_size % 2 - 1) + else: + kernel_size = 5 + return filename, spatial_variance, intensity_variance, kernel_size + +if __name__ == "__main__": + filename, spatial_variance, intensity_variance, kernel_size = parse_args(sys.argv) img = cv2.imread(filename, 0) cv2.imshow("input image", img)