123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- # main imports
- import os
- import numpy as np
- import random
- # 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 augmented_data_image(block, output_folder, prefix_image_name):
- rotations = [0, 90, 180, 270]
- img_flip_labels = ['original', 'horizontal', 'vertical', 'both']
- horizontal_img = block.transpose(Image.FLIP_LEFT_RIGHT)
- vertical_img = block.transpose(Image.FLIP_TOP_BOTTOM)
- both_img = block.transpose(Image.TRANSPOSE)
- flip_images = [block, horizontal_img, vertical_img, both_img]
- # rotate and flip image to increase dataset size
- for id, flip in enumerate(flip_images):
- for rotation in rotations:
- rotated_output_img = flip.rotate(rotation)
- output_reconstructed_filename = prefix_image_name + post_image_name_separator
- output_reconstructed_filename = output_reconstructed_filename + img_flip_labels[id] + '_' + str(rotation) + '.png'
- output_reconstructed_path = os.path.join(output_folder, output_reconstructed_filename)
- if not os.path.exists(output_reconstructed_path):
- rotated_output_img.save(output_reconstructed_path)
-
- 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
|