Removed unused filters and their parameters from config parser.
This commit is contained in:
@ -77,6 +77,9 @@ def parse_conf(preset_name, filters, params, config_file):
|
|||||||
Store filters and their parameters.
|
Store filters and their parameters.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
if not exists(config_file):
|
||||||
|
log.error_exit("Config file not found")
|
||||||
|
|
||||||
config = json.load(open(config_file))
|
config = json.load(open(config_file))
|
||||||
|
|
||||||
# Find preset in config file
|
# Find preset in config file
|
||||||
@ -96,7 +99,7 @@ def parse_conf(preset_name, filters, params, config_file):
|
|||||||
log.print_message("Loaded preset:", preset_name,
|
log.print_message("Loaded preset:", preset_name,
|
||||||
"from file:", config_file)
|
"from file:", config_file)
|
||||||
else:
|
else:
|
||||||
log.print_message("Warning: Preset not found in config file")
|
log.error_exit("Preset not found in config file")
|
||||||
|
|
||||||
|
|
||||||
def parse_params(params):
|
def parse_params(params):
|
||||||
@ -107,12 +110,13 @@ def parse_params(params):
|
|||||||
|
|
||||||
# TODO: possibly too bloated, sending all possible params to each filter
|
# TODO: possibly too bloated, sending all possible params to each filter
|
||||||
# TODO: remove unnecessary params
|
# TODO: remove unnecessary params
|
||||||
possible_params = {"h", "searchWindowSize", "templateWindowSize",
|
possible_params = {"sigma", "ksize", "kernel",
|
||||||
"ksize", "kernel", "angle",
|
"diameter", "sigmaColor", "sigmaSpace",
|
||||||
"sigmaColor", "sigmaSpace", "diameter", "anchor", "iterations",
|
"patch_size", "patch_distance", "weight",
|
||||||
"op", "strength", "amount", "radius", "weight", "channelAxis",
|
"amount", "radius", "percent",
|
||||||
"theta", "sigma", "lambd", "gamma", "psi", "shape", "percent",
|
"threshold",
|
||||||
"threshold", "maxval", "type", "margin", "color", "truncate", "patch_size", "patch_distance"}
|
"margin", "color"
|
||||||
|
}
|
||||||
|
|
||||||
for key in possible_params:
|
for key in possible_params:
|
||||||
if params.get(key) is None:
|
if params.get(key) is None:
|
||||||
|
243
src/filters.py
243
src/filters.py
@ -8,13 +8,11 @@ import cv2 as cv
|
|||||||
from skimage import filters as skiflt
|
from skimage import filters as skiflt
|
||||||
from skimage import restoration as skirest
|
from skimage import restoration as skirest
|
||||||
from skimage import morphology as skimorph
|
from skimage import morphology as skimorph
|
||||||
from scipy import ndimage
|
|
||||||
from PIL import Image, ImageFilter
|
from PIL import Image, ImageFilter
|
||||||
import bm3d
|
import bm3d
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
|
|
||||||
|
|
||||||
class filter:
|
class img_filter:
|
||||||
''' Parent class for all the filters.
|
''' Parent class for all the filters.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -28,7 +26,7 @@ class filter:
|
|||||||
# --------------------- DENOISING FILTERS ---------------------#
|
# --------------------- DENOISING FILTERS ---------------------#
|
||||||
|
|
||||||
|
|
||||||
class gaussian(filter):
|
class gaussian(img_filter):
|
||||||
'''Gaussian blur filter from scikit-image.
|
'''Gaussian blur filter from scikit-image.
|
||||||
Easier to use than opencv version.
|
Easier to use than opencv version.
|
||||||
'''
|
'''
|
||||||
@ -45,7 +43,7 @@ class gaussian(filter):
|
|||||||
self.img, sigma=sigma, preserve_range=True)
|
self.img, sigma=sigma, preserve_range=True)
|
||||||
|
|
||||||
|
|
||||||
class median(filter):
|
class median(img_filter):
|
||||||
''' Median blur filter from scikit-image.
|
''' Median blur filter from scikit-image.
|
||||||
Using this over opencv version as that one is limited to 5x5 kernel.
|
Using this over opencv version as that one is limited to 5x5 kernel.
|
||||||
'''
|
'''
|
||||||
@ -61,7 +59,7 @@ class median(filter):
|
|||||||
self.img = skiflt.median(self.img, footprint=skimorph.disk(ksize))
|
self.img = skiflt.median(self.img, footprint=skimorph.disk(ksize))
|
||||||
|
|
||||||
|
|
||||||
class bilateral(filter):
|
class bilateral(img_filter):
|
||||||
''' Bilateral filter from opencv.
|
''' Bilateral filter from opencv.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -87,7 +85,7 @@ class bilateral(filter):
|
|||||||
self.img, diameter, sigmaColor, sigmaSpace)
|
self.img, diameter, sigmaColor, sigmaSpace)
|
||||||
|
|
||||||
|
|
||||||
class bilateral_scikit(filter):
|
class bilateral_scikit(img_filter):
|
||||||
''' Skimage denoise_bilateral filter.
|
''' Skimage denoise_bilateral filter.
|
||||||
Averages pixels based on their distance and color similarity.
|
Averages pixels based on their distance and color similarity.
|
||||||
Preserves edges while removing unwanted noise.
|
Preserves edges while removing unwanted noise.
|
||||||
@ -116,7 +114,7 @@ class bilateral_scikit(filter):
|
|||||||
self.img = np.uint8(self.img * 255.0) # converting back to uint8
|
self.img = np.uint8(self.img * 255.0) # converting back to uint8
|
||||||
|
|
||||||
|
|
||||||
class nlmeans(filter):
|
class nlmeans(img_filter):
|
||||||
''' Non-local means filter from scikit-image.
|
''' Non-local means filter from scikit-image.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -143,7 +141,7 @@ class nlmeans(filter):
|
|||||||
self.img = np.uint8(self.img * 255.0) # converting back to uint8
|
self.img = np.uint8(self.img * 255.0) # converting back to uint8
|
||||||
|
|
||||||
|
|
||||||
class total_variation(filter):
|
class total_variation(img_filter):
|
||||||
''' Scikit image denoise_tv_chambolle filter from scikit-image.
|
''' Scikit image denoise_tv_chambolle filter from scikit-image.
|
||||||
|
|
||||||
Performs total variation denoising technique based on original Chambolle paper.
|
Performs total variation denoising technique based on original Chambolle paper.
|
||||||
@ -163,7 +161,7 @@ class total_variation(filter):
|
|||||||
self.img = np.uint8(self.img * 255.0) # converting back to uint8
|
self.img = np.uint8(self.img * 255.0) # converting back to uint8
|
||||||
|
|
||||||
|
|
||||||
class block_match(filter):
|
class block_match(img_filter):
|
||||||
'''Block matching filter from bm3d.
|
'''Block matching filter from bm3d.
|
||||||
|
|
||||||
This filter is very slow and should be used only on small images
|
This filter is very slow and should be used only on small images
|
||||||
@ -179,7 +177,7 @@ class block_match(filter):
|
|||||||
stage_arg=bm3d.BM3DStages.ALL_STAGES)
|
stage_arg=bm3d.BM3DStages.ALL_STAGES)
|
||||||
|
|
||||||
|
|
||||||
class unsharp_mask_scikit(filter):
|
class unsharp_mask_scikit(img_filter):
|
||||||
''' Unsharp mask filter from scikit.
|
''' Unsharp mask filter from scikit.
|
||||||
|
|
||||||
Apply blurring using gaussian filter, then subtract the blurred image from the original image.
|
Apply blurring using gaussian filter, then subtract the blurred image from the original image.
|
||||||
@ -204,7 +202,7 @@ class unsharp_mask_scikit(filter):
|
|||||||
# ------------------- EDGE DETECTION FILTERS -------------------#
|
# ------------------- EDGE DETECTION FILTERS -------------------#
|
||||||
|
|
||||||
|
|
||||||
class farid(filter):
|
class farid(img_filter):
|
||||||
''' Farid filter from filters.
|
''' Farid filter from filters.
|
||||||
Not sure what this might be used for yet.
|
Not sure what this might be used for yet.
|
||||||
'''
|
'''
|
||||||
@ -212,27 +210,27 @@ class farid(filter):
|
|||||||
def __init__(self, img):
|
def __init__(self, img):
|
||||||
super().__init__(img)
|
super().__init__(img)
|
||||||
|
|
||||||
def apply(self, params):
|
def apply(self, _):
|
||||||
|
|
||||||
self.img = skiflt.farid(self.img)
|
self.img = skiflt.farid(self.img)
|
||||||
|
|
||||||
# ------------------ RIDGE EXTRACTION FILTERS ------------------#
|
# ------------------ RIDGE EXTRACTION FILTERS ------------------#
|
||||||
|
|
||||||
|
|
||||||
class meijering(filter):
|
class meijering(img_filter):
|
||||||
''' Meijering filter from scikit-image filters.
|
''' Meijering filter from scikit-image filters.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, img):
|
def __init__(self, img):
|
||||||
super().__init__(img)
|
super().__init__(img)
|
||||||
|
|
||||||
def apply(self, params):
|
def apply(self, _):
|
||||||
|
|
||||||
self.img = skiflt.meijering(self.img)
|
self.img = skiflt.meijering(self.img)
|
||||||
self.img = np.uint8(self.img * 255.0)
|
self.img = np.uint8(self.img * 255.0)
|
||||||
|
|
||||||
|
|
||||||
class sato(filter):
|
class sato(img_filter):
|
||||||
''' Meijering filter from scikit-image filters.
|
''' Meijering filter from scikit-image filters.
|
||||||
Exctracts black ridges.
|
Exctracts black ridges.
|
||||||
'''
|
'''
|
||||||
@ -240,13 +238,13 @@ class sato(filter):
|
|||||||
def __init__(self, img):
|
def __init__(self, img):
|
||||||
super().__init__(img)
|
super().__init__(img)
|
||||||
|
|
||||||
def apply(self, params):
|
def apply(self, _):
|
||||||
|
|
||||||
self.img = skiflt.sato(self.img)
|
self.img = skiflt.sato(self.img)
|
||||||
self.img = np.uint8(self.img * 255.0)
|
self.img = np.uint8(self.img * 255.0)
|
||||||
|
|
||||||
|
|
||||||
class hessian(filter):
|
class hessian(img_filter):
|
||||||
''' Hessian filter from scikit-image filters.
|
''' Hessian filter from scikit-image filters.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -263,18 +261,18 @@ class hessian(filter):
|
|||||||
# ------------------- MISCELLANEOUS FILTERS -------------------#
|
# ------------------- MISCELLANEOUS FILTERS -------------------#
|
||||||
|
|
||||||
|
|
||||||
class invert(filter):
|
class invert(img_filter):
|
||||||
''' Invert the image using bitwise_not from opencv.
|
''' Invert the image using bitwise_not from opencv.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, img):
|
def __init__(self, img):
|
||||||
super().__init__(img)
|
super().__init__(img)
|
||||||
|
|
||||||
def apply(self, params):
|
def apply(self, _):
|
||||||
self.img = cv.bitwise_not(self.img)
|
self.img = cv.bitwise_not(self.img)
|
||||||
|
|
||||||
|
|
||||||
class scale_values(filter):
|
class scale_values(img_filter):
|
||||||
''' Scale values of the image to use the entire range of data type.
|
''' Scale values of the image to use the entire range of data type.
|
||||||
This should remove the line height issues.
|
This should remove the line height issues.
|
||||||
'''
|
'''
|
||||||
@ -294,19 +292,17 @@ class scale_values(filter):
|
|||||||
tmp = tmp * coef
|
tmp = tmp * coef
|
||||||
|
|
||||||
|
|
||||||
class binarize(filter):
|
class binarize(img_filter):
|
||||||
def init(self, img):
|
def init(self, img):
|
||||||
super().__init__(img)
|
super().__init__(img)
|
||||||
|
|
||||||
def apply(self, params):
|
def apply(self, params):
|
||||||
threshold = int(params["threshold"]) if params["threshold"] else 128
|
threshold = int(params["threshold"]) if params["threshold"] else 128
|
||||||
maxval = int(params["maxval"]) if params["maxval"] else 255
|
|
||||||
type = int(params["type"]) if params["type"] else 0
|
|
||||||
|
|
||||||
self.img = cv.threshold(self.img, threshold, maxval, type)[1]
|
self.img = cv.threshold(self.img, threshold, 255, cv.THRESH_BINARY)[1]
|
||||||
|
|
||||||
|
|
||||||
class binarize_otsu(filter):
|
class binarize_otsu(img_filter):
|
||||||
''' Otsu binarization filter from opencv.
|
''' Otsu binarization filter from opencv.
|
||||||
'''
|
'''
|
||||||
def init(self, img):
|
def init(self, img):
|
||||||
@ -316,7 +312,7 @@ class binarize_otsu(filter):
|
|||||||
self.img = cv.threshold(self.img, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)[1]
|
self.img = cv.threshold(self.img, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)[1]
|
||||||
|
|
||||||
|
|
||||||
class add_margin(filter):
|
class add_margin(img_filter):
|
||||||
def init(self, img):
|
def init(self, img):
|
||||||
super().__init__(img)
|
super().__init__(img)
|
||||||
|
|
||||||
@ -330,95 +326,52 @@ class add_margin(filter):
|
|||||||
self.img, margin, margin, margin, margin, cv.BORDER_CONSTANT, value=color)
|
self.img, margin, margin, margin, margin, cv.BORDER_CONSTANT, value=color)
|
||||||
self.height, self.width = self.img.shape
|
self.height, self.width = self.img.shape
|
||||||
|
|
||||||
|
# ---------------------- MORPHOLOGICAL OPS --------------------------#
|
||||||
|
|
||||||
|
class erode(img_filter):
|
||||||
|
''' General morphological operations from OpenCV.
|
||||||
|
|
||||||
|
Can be used with MORPH_OPEN, MORPH_CLOSE, MORPH_DILATE, MORPH_ERODE and more as 'op'.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, img):
|
||||||
|
super().__init__(img)
|
||||||
|
|
||||||
|
def apply(self, params):
|
||||||
|
|
||||||
|
# get an ellipse kernel
|
||||||
|
kernel = np.matrix(params["kernel"]) if params["kernel"] else cv.getStructuringElement(
|
||||||
|
cv.MORPH_ELLIPSE, (3, 3))
|
||||||
|
|
||||||
|
self.img = cv.morphologyEx(
|
||||||
|
np.uint8(self.img), op=cv.MORPH_ERODE, kernel=kernel)
|
||||||
|
|
||||||
|
class dilate(img_filter):
|
||||||
|
''' General morphological operations from OpenCV.
|
||||||
|
|
||||||
|
Can be used with MORPH_OPEN, MORPH_CLOSE, MORPH_DILATE, MORPH_ERODE and more as 'op'.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, img):
|
||||||
|
super().__init__(img)
|
||||||
|
|
||||||
|
def apply(self, params):
|
||||||
|
|
||||||
|
# get an ellipse kernel
|
||||||
|
kernel = np.matrix(params["kernel"]) if params["kernel"] else cv.getStructuringElement(
|
||||||
|
cv.MORPH_ELLIPSE, (3, 3))
|
||||||
|
|
||||||
|
self.img = cv.morphologyEx(
|
||||||
|
np.uint8(self.img), op=cv.MORPH_DILATE, kernel=kernel)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------- OLD --------------------------#
|
# ---------------------- OLD --------------------------#
|
||||||
|
|
||||||
|
|
||||||
# TODO: REVISE, REMOVE unused filters
|
# TODO: REVISE, REMOVE unused filters
|
||||||
|
|
||||||
|
class unsharp_mask_pil(img_filter):
|
||||||
class convolve(filter):
|
|
||||||
''' Convolve with custom kernel using opencv.
|
|
||||||
If no kernel is given, use default 3x3 kernel for averaging.
|
|
||||||
Possibly useful for custom filters.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, img):
|
|
||||||
super().__init__(img)
|
|
||||||
|
|
||||||
def apply(self, params):
|
|
||||||
kernel = np.array(params["kernel"]) if params["kernel"] else np.ones(
|
|
||||||
(3, 3), np.float32) / 9
|
|
||||||
|
|
||||||
self.img = cv.filter2D(self.img, -1, kernel)
|
|
||||||
|
|
||||||
|
|
||||||
class blur(filter):
|
|
||||||
''' Blur filter from opencv.
|
|
||||||
Performs averaging of the image.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, img):
|
|
||||||
super().__init__(img)
|
|
||||||
|
|
||||||
def apply(self, params):
|
|
||||||
ksize = int(params["ksize"]) if params["ksize"] else 3
|
|
||||||
|
|
||||||
self.img = cv.blur(self.img, ksize=(ksize, ksize))
|
|
||||||
|
|
||||||
|
|
||||||
class denoise(filter):
|
|
||||||
def __init__(self, img):
|
|
||||||
super().__init__(img)
|
|
||||||
|
|
||||||
def apply(self, params):
|
|
||||||
h = int(params["h"]) if params["h"] else 10
|
|
||||||
tWS = int(params["templateWindowSize"]
|
|
||||||
) if params["templateWindowSize"] else 7
|
|
||||||
sWS = int(params["searchWindowSize"]
|
|
||||||
) if params["searchWindowSize"] else 21
|
|
||||||
|
|
||||||
self.img = np.uint8(self.img)
|
|
||||||
self.img = cv.fastNlMeansDenoising(
|
|
||||||
self.img, h, tWS, sWS)
|
|
||||||
|
|
||||||
|
|
||||||
class sharpen(filter):
|
|
||||||
''' Convolution with a sharpening kernel using opencv.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, img):
|
|
||||||
super().__init__(img)
|
|
||||||
|
|
||||||
def apply(self, params):
|
|
||||||
kernel = np.matrix(params["kernel"]) if params["kernel"] else np.array(
|
|
||||||
[[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
|
|
||||||
|
|
||||||
self.img = cv.filter2D(self.img, ddepth=-1, kernel=kernel)
|
|
||||||
|
|
||||||
|
|
||||||
class unsharp_mask(filter):
|
|
||||||
''' Unsharp mask filter from opencv.
|
|
||||||
|
|
||||||
First blur the image a little bit, then calculate Laplacian of the image to get the edges.
|
|
||||||
Scale the Laplacian and subtract it from the original image.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, img):
|
|
||||||
super().__init__(img)
|
|
||||||
|
|
||||||
def apply(self, params):
|
|
||||||
strength = float(params["strength"]) if params["strength"] else 1.0
|
|
||||||
ksize = int(params["ksize"]) if params["ksize"] else 3
|
|
||||||
|
|
||||||
blurred = cv.medianBlur(self.img, ksize)
|
|
||||||
lap = cv.Laplacian(blurred, cv.CV_32F)
|
|
||||||
|
|
||||||
self.img = blurred - strength*lap
|
|
||||||
|
|
||||||
|
|
||||||
class unsharp_mask_pil(filter):
|
|
||||||
''' Unsharp mask filter from PIL.
|
''' Unsharp mask filter from PIL.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, img):
|
def __init__(self, img):
|
||||||
@ -439,73 +392,3 @@ class unsharp_mask_pil(filter):
|
|||||||
tmp = Image.fromarray(self.img)
|
tmp = Image.fromarray(self.img)
|
||||||
tmp = tmp.filter(ImageFilter.UnsharpMask(radius, percent, threshold))
|
tmp = tmp.filter(ImageFilter.UnsharpMask(radius, percent, threshold))
|
||||||
self.img = np.asarray(tmp)
|
self.img = np.asarray(tmp)
|
||||||
|
|
||||||
|
|
||||||
class erode(filter):
|
|
||||||
''' General morphological operations from OpenCV.
|
|
||||||
|
|
||||||
Can be used with MORPH_OPEN, MORPH_CLOSE, MORPH_DILATE, MORPH_ERODE and more as 'op'.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, img):
|
|
||||||
super().__init__(img)
|
|
||||||
|
|
||||||
def apply(self, params):
|
|
||||||
|
|
||||||
# get an ellipse kernel
|
|
||||||
kernel = np.matrix(params["kernel"]) if params["kernel"] else cv.getStructuringElement(
|
|
||||||
cv.MORPH_ELLIPSE, (3, 3))
|
|
||||||
|
|
||||||
self.img = cv.morphologyEx(
|
|
||||||
np.uint8(self.img), op=cv.MORPH_ERODE, kernel=kernel)
|
|
||||||
|
|
||||||
|
|
||||||
class dilate(filter):
|
|
||||||
''' General morphological operations from OpenCV.
|
|
||||||
|
|
||||||
Can be used with MORPH_OPEN, MORPH_CLOSE, MORPH_DILATE, MORPH_ERODE and more as 'op'.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, img):
|
|
||||||
super().__init__(img)
|
|
||||||
|
|
||||||
def apply(self, params):
|
|
||||||
|
|
||||||
# get an ellipse kernel
|
|
||||||
kernel = np.matrix(params["kernel"]) if params["kernel"] else cv.getStructuringElement(
|
|
||||||
cv.MORPH_ELLIPSE, (3, 3))
|
|
||||||
|
|
||||||
self.img = cv.morphologyEx(
|
|
||||||
np.uint8(self.img), op=cv.MORPH_DILATE, kernel=kernel)
|
|
||||||
|
|
||||||
|
|
||||||
class gabor(filter):
|
|
||||||
''' Gabor filter from OpenCV.
|
|
||||||
|
|
||||||
Performs Gabor filtering on the image.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, img):
|
|
||||||
super().__init__(img)
|
|
||||||
|
|
||||||
def apply(self, params):
|
|
||||||
ksize = int(params["ksize"]) if params["ksize"] else 31
|
|
||||||
sigma = float(params["sigma"]) if params["sigma"] else 10.0
|
|
||||||
theta = params["theta"] if params["theta"] else [
|
|
||||||
0, np.pi/16, np.pi-np.pi/16]
|
|
||||||
lambd = float(params["lambd"]) if params["lambd"] else 10.0
|
|
||||||
gamma = float(params["gamma"]) if params["gamma"] else 0.02
|
|
||||||
psi = float(params["psi"]) if params["psi"] else 0.0
|
|
||||||
|
|
||||||
filters = []
|
|
||||||
|
|
||||||
for i in range(len(theta)):
|
|
||||||
g_kernel = cv.getGaborKernel(ksize=(
|
|
||||||
ksize, ksize), sigma=sigma, theta=theta[i], lambd=lambd, gamma=gamma, psi=psi)
|
|
||||||
g_kernel = g_kernel / 1.5 * g_kernel.sum()
|
|
||||||
filters.append(g_kernel)
|
|
||||||
|
|
||||||
tmp = np.zeros_like(self.img)
|
|
||||||
for i in range(len(filters)):
|
|
||||||
tmp = cv.filter2D(self.img, -1, kernel=filters[i])
|
|
||||||
self.img += np.maximum(self.img, tmp)
|
|
||||||
|
Reference in New Issue
Block a user