|
@@ -0,0 +1,278 @@
|
|
|
+# main imports
|
|
|
+import os
|
|
|
+import numpy as np
|
|
|
+
|
|
|
+# image processing imports
|
|
|
+from ipfml.processing import transform, compression
|
|
|
+from ipfml.processing import reconstruction
|
|
|
+from ipfml.filters import convolution, kernels
|
|
|
+from ipfml import utils
|
|
|
+import cv2
|
|
|
+from skimage.restoration import denoise_nl_means, estimate_sigma
|
|
|
+
|
|
|
+from PIL import Image
|
|
|
+
|
|
|
+
|
|
|
+def remove_pixel(img, limit):
|
|
|
+
|
|
|
+ width, height = img.shape
|
|
|
+
|
|
|
+ output = np.zeros((width, height))
|
|
|
+
|
|
|
+ for i in range(width):
|
|
|
+ for j in range(height):
|
|
|
+
|
|
|
+ if img[i,j] <= limit:
|
|
|
+ output[i,j] = img[i,j]
|
|
|
+
|
|
|
+ return output
|
|
|
+
|
|
|
+
|
|
|
+def get_random_value(distribution):
|
|
|
+ rand = random.uniform(0, 1)
|
|
|
+ prob_sum = 0.
|
|
|
+
|
|
|
+ for id, prob in enumerate(distribution):
|
|
|
+
|
|
|
+ prob_sum += prob
|
|
|
+
|
|
|
+ if prob_sum >= rand:
|
|
|
+ return id
|
|
|
+
|
|
|
+ return len(distribution) - 1
|
|
|
+
|
|
|
+
|
|
|
+def distribution_from_data(data):
|
|
|
+
|
|
|
+ occurences = np.array([data.count(x) for x in set(data)])
|
|
|
+ max_occurences = sum(occurences)
|
|
|
+
|
|
|
+ return occurences / max_occurences
|
|
|
+
|
|
|
+
|
|
|
+def fill_image_with_rand_value(img, func, value_to_replace):
|
|
|
+
|
|
|
+ width, height = img.shape
|
|
|
+
|
|
|
+ output = np.zeros((width, height))
|
|
|
+
|
|
|
+ for i in range(width):
|
|
|
+ for j in range(height):
|
|
|
+
|
|
|
+ if img[i,j] == value_to_replace:
|
|
|
+ output[i, j] = func()
|
|
|
+ else:
|
|
|
+ output[i, j] = img[i, j]
|
|
|
+
|
|
|
+ return output
|
|
|
+
|
|
|
+def _compute_relative_error(ref_sv, k_sv):
|
|
|
+ ref = np.sqrt(np.sum(np.square(ref_sv)))
|
|
|
+ k = np.sqrt(np.sum(np.square(k_sv)))
|
|
|
+
|
|
|
+ return k / ref
|
|
|
+
|
|
|
+def _find_n_components(block, e=0.1):
|
|
|
+
|
|
|
+ s = transform.get_LAB_L_SVD_s(block)
|
|
|
+
|
|
|
+ errors = []
|
|
|
+ found = False
|
|
|
+ k_components = None
|
|
|
+
|
|
|
+ for i in range(len(s)):
|
|
|
+
|
|
|
+ #Ak = reconstruction.svd(img, [0, i])
|
|
|
+ #error = compute_relative_error_matrix(A, Ak)
|
|
|
+ error = _compute_relative_error(s, s[i:])
|
|
|
+ errors.append(error)
|
|
|
+
|
|
|
+ if error < e and not found:
|
|
|
+ k_components = (i + 1)
|
|
|
+ found = True
|
|
|
+
|
|
|
+ return (k_components, errors)
|
|
|
+
|
|
|
+# Transformation class to store transformation method of image and get usefull information
|
|
|
+class Transformation():
|
|
|
+
|
|
|
+ def __init__(self, _transformation, _param, _size):
|
|
|
+ self.transformation = _transformation
|
|
|
+ self.param = _param
|
|
|
+ self.size = _size
|
|
|
+
|
|
|
+ def getTransformedImage(self, img):
|
|
|
+
|
|
|
+ if self.transformation == 'svd_reconstruction':
|
|
|
+ begin, end = list(map(int, self.param.split(',')))
|
|
|
+ h, w = list(map(int, self.size.split(',')))
|
|
|
+ img_reconstructed = reconstruction.svd(img, [begin, end])
|
|
|
+ data_array = np.array(img_reconstructed, 'uint8')
|
|
|
+
|
|
|
+ img_array = Image.fromarray(data_array)
|
|
|
+ img_array.thumbnail((h, w))
|
|
|
+
|
|
|
+ data = np.array(img_array)
|
|
|
+
|
|
|
+ if self.transformation == 'svd_reconstruction':
|
|
|
+ begin, end = list(map(int, self.param.split(',')))
|
|
|
+ h, w = list(map(int, self.size.split(',')))
|
|
|
+ img_reconstructed = reconstruction.svd(img, [begin, end])
|
|
|
+ data_array = np.array(img_reconstructed, 'uint8')
|
|
|
+
|
|
|
+ img_array = Image.fromarray(data_array)
|
|
|
+ img_array.thumbnail((h, w))
|
|
|
+
|
|
|
+ data = np.array(img_array)
|
|
|
+
|
|
|
+ if self.transformation == 'ipca_reconstruction':
|
|
|
+ n_components, batch_size = list(map(int, self.param.split(',')))
|
|
|
+ h, w = list(map(int, self.size.split(',')))
|
|
|
+ img_reconstructed = reconstruction.ipca(img, n_components, batch_size)
|
|
|
+ data_array = np.array(img_reconstructed, 'uint8')
|
|
|
+
|
|
|
+ img_array = Image.fromarray(data_array)
|
|
|
+ img_array.thumbnail((h, w))
|
|
|
+
|
|
|
+ data = np.array(img_array)
|
|
|
+
|
|
|
+ if self.transformation == 'fast_ica_reconstruction':
|
|
|
+ n_components = self.param
|
|
|
+ h, w = list(map(int, self.size.split(',')))
|
|
|
+ img_reconstructed = reconstruction.fast_ica(img, n_components)
|
|
|
+ data_array = np.array(img_reconstructed, 'uint8')
|
|
|
+
|
|
|
+ img_array = Image.fromarray(data_array)
|
|
|
+ img_array.thumbnail((h, w))
|
|
|
+
|
|
|
+ data = np.array(img_array)
|
|
|
+
|
|
|
+ if self.transformation == 'gini_map':
|
|
|
+ # kernel size
|
|
|
+ k_w, k_h = list(map(int, self.param.split(',')))
|
|
|
+ h, w = list(map(int, self.size.split(',')))
|
|
|
+
|
|
|
+ lab_img = transform.get_LAB_L(img)
|
|
|
+ img_mask = convolution.convolution2D(lab_img, kernels.gini, (k_w, k_h))
|
|
|
+
|
|
|
+ # renormalize data
|
|
|
+ data_array = np.array(img_mask * 255, 'uint8')
|
|
|
+
|
|
|
+ img_array = Image.fromarray(data_array)
|
|
|
+ img_array.thumbnail((h, w))
|
|
|
+
|
|
|
+ data = np.array(img_array)
|
|
|
+
|
|
|
+ if self.transformation == 'sobel_based_filter':
|
|
|
+ k_size, p_limit = list(map(int, self.param.split(',')))
|
|
|
+ h, w = list(map(int, self.size.split(',')))
|
|
|
+
|
|
|
+ lab_img = transform.get_LAB_L(img)
|
|
|
+
|
|
|
+ weight, height = lab_img.shape
|
|
|
+
|
|
|
+ sobelx = cv2.Sobel(lab_img, cv2.CV_64F, 1, 0, ksize=k_size)
|
|
|
+ sobely = cv2.Sobel(lab_img, cv2.CV_64F, 0, 1,ksize=k_size)
|
|
|
+
|
|
|
+ sobel_mag = np.array(np.hypot(sobelx, sobely), 'uint8') # magnitude
|
|
|
+ sobel_mag_limit = remove_pixel(sobel_mag, p_limit)
|
|
|
+
|
|
|
+ # use distribution value of pixel to fill `0` values
|
|
|
+ sobel_mag_limit_without_0 = [x for x in sobel_mag_limit.reshape((weight*height)) if x != 0]
|
|
|
+ distribution = distribution_from_data(sobel_mag_limit_without_0)
|
|
|
+ min_value = int(min(sobel_mag_limit_without_0))
|
|
|
+ l = lambda: get_random_value(distribution) + min_value
|
|
|
+ img_reconstructed = fill_image_with_rand_value(sobel_mag_limit, l, 0)
|
|
|
+
|
|
|
+ img_reconstructed_norm = utils.normalize_2D_arr(img_reconstructed)
|
|
|
+ img_reconstructed_norm = np.array(img_reconstructed_norm*255, 'uint8')
|
|
|
+ sobel_reconstructed = Image.fromarray(img_reconstructed_norm)
|
|
|
+ sobel_reconstructed.thumbnail((h, w))
|
|
|
+
|
|
|
+ data = np.array(sobel_reconstructed)
|
|
|
+
|
|
|
+ if self.transformation == 'nl_mean_noise_mask':
|
|
|
+ patch_size, patch_distance = list(map(int, self.param.split(',')))
|
|
|
+ h, w = list(map(int, self.size.split(',')))
|
|
|
+
|
|
|
+ img = np.array(img)
|
|
|
+ sigma_est = np.mean(estimate_sigma(img, multichannel=True))
|
|
|
+
|
|
|
+ patch_kw = dict(patch_size=patch_size, # 5x5 patches
|
|
|
+ patch_distance=patch_distance, # 13x13 search area
|
|
|
+ multichannel=True)
|
|
|
+
|
|
|
+ # slow algorithm
|
|
|
+ denoise = denoise_nl_means(img, h=0.8 * sigma_est, sigma=sigma_est,
|
|
|
+ fast_mode=False,
|
|
|
+ **patch_kw)
|
|
|
+
|
|
|
+ denoise = np.array(denoise, 'uint8')
|
|
|
+ noise_mask = np.abs(denoise - img)
|
|
|
+
|
|
|
+ data_array = np.array(noise_mask, 'uint8')
|
|
|
+
|
|
|
+ img_array = Image.fromarray(data_array)
|
|
|
+ img_array.thumbnail((h, w))
|
|
|
+
|
|
|
+ data = np.array(img_array)
|
|
|
+
|
|
|
+ if self.transformation == 'static':
|
|
|
+ # static content, we keep input as it is
|
|
|
+ data = img
|
|
|
+
|
|
|
+ return data
|
|
|
+
|
|
|
+ def getTransformationPath(self):
|
|
|
+
|
|
|
+ path = self.transformation
|
|
|
+
|
|
|
+ if self.transformation == 'svd_reconstruction':
|
|
|
+ begin, end = list(map(int, self.param.split(',')))
|
|
|
+ w, h = list(map(int, self.size.split(',')))
|
|
|
+ path = os.path.join(path, str(begin) + '_' + str(end) + '_S_' + str(w) + '_' + str(h))
|
|
|
+
|
|
|
+ if self.transformation == 'gini_map':
|
|
|
+ k_w, k_h = list(map(int, self.param.split(',')))
|
|
|
+ w, h = list(map(int, self.size.split(',')))
|
|
|
+ path = os.path.join(path, str(k_w) + '_' + str(k_h) + '_S_' + str(w) + '_' + str(h))
|
|
|
+
|
|
|
+ if self.transformation == 'ipca_reconstruction':
|
|
|
+ n_components, batch_size = list(map(int, self.param.split(',')))
|
|
|
+ w, h = list(map(int, self.size.split(',')))
|
|
|
+ path = os.path.join(path, 'N' + str(n_components) + '_' + str(batch_size) + '_S_' + str(w) + '_' + str(h))
|
|
|
+
|
|
|
+ if self.transformation == 'fast_ica_reconstruction':
|
|
|
+ n_components = self.param
|
|
|
+ w, h = list(map(int, self.size.split(',')))
|
|
|
+ path = os.path.join(path, 'N' + str(n_components) + '_S_' + str(w) + '_' + str(h))
|
|
|
+
|
|
|
+ if self.transformation == 'min_diff_filter':
|
|
|
+ w_size, h_size, stride = list(map(int, self.param.split(',')))
|
|
|
+ w, h = list(map(int, self.size.split(',')))
|
|
|
+ path = os.path.join(path, 'W_' + str(w_size) + '_' + str(h_size) + '_Stride_' + str(stride) + '_S_' + str(w) + '_' + str(h))
|
|
|
+
|
|
|
+ if self.transformation == 'sobel_based_filter':
|
|
|
+ k_size, p_limit = list(map(int, self.param.split(',')))
|
|
|
+ h, w = list(map(int, self.size.split(',')))
|
|
|
+ path = os.path.join(path, 'K_' + str(k_size) + '_L' + str(p_limit) + '_S_' + str(w) + '_' + str(h))
|
|
|
+
|
|
|
+ if self.transformation == 'nl_mean_noise_mask':
|
|
|
+ patch_size, patch_distance = list(map(int, self.param.split(',')))
|
|
|
+ h, w = list(map(int, self.size.split(',')))
|
|
|
+ path = os.path.join(path, 'S' + str(patch_size) + '_D' + str(patch_distance) + '_S_' + str(w) + '_' + str(h))
|
|
|
+
|
|
|
+ if self.transformation == 'static':
|
|
|
+ # param contains image name to find for each scene
|
|
|
+ path = self.param
|
|
|
+
|
|
|
+ return path
|
|
|
+
|
|
|
+ def getName(self):
|
|
|
+ return self.transformation
|
|
|
+
|
|
|
+ def getParam(self):
|
|
|
+ return self.param
|
|
|
+
|
|
|
+ def __str__( self ):
|
|
|
+ return self.transformation + ' transformation with parameter : ' + self.param
|