123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- """
- Functions to quickly extract reduced information from image
- """
- from PIL import Image
- import random
- import cv2
- from skimage import transform, color
- import numpy as np
- import ipfml.metrics as metrics
- from ipfml import exceptions
- from scipy import signal
- def get_LAB_L_SVD(image):
- """Returns Singular values from LAB L Image information
- Args:
- image: PIL Image or Numpy array
- Returns:
- U, s, V information obtained from SVD compression using Lab
- Example:
- >>> from PIL import Image
- >>> from ipfml import processing
- >>> img = Image.open('./images/test_img.png')
- >>> U, s, V = processing.get_LAB_L_SVD(img)
- >>> U.shape
- (200, 200)
- >>> len(s)
- 200
- >>> V.shape
- (200, 200)
- """
- L = metrics.get_LAB_L(image)
- return metrics.get_SVD(L)
- def get_LAB_L_SVD_s(image):
- """Returns s (Singular values) SVD from L of LAB Image information
- Args:
- image: PIL Image or Numpy array
- Returns:
- vector of singular values
- Example:
- >>> from PIL import Image
- >>> from ipfml import processing
- >>> img = Image.open('./images/test_img.png')
- >>> s = processing.get_LAB_L_SVD_s(img)
- >>> len(s)
- 200
- """
- L = metrics.get_LAB_L(image)
- return metrics.get_SVD_s(L)
- def get_LAB_L_SVD_U(image):
- """Returns U SVD from L of LAB Image information
- Args:
- image: PIL Image or Numpy array
- Returns:
- U matrix of SVD compression
- Example:
- >>> from PIL import Image
- >>> from ipfml import processing
- >>> img = Image.open('./images/test_img.png')
- >>> U = processing.get_LAB_L_SVD_U(img)
- >>> U.shape
- (200, 200)
- """
- L = metrics.get_LAB_L(image)
- return metrics.get_SVD_U(L)
- def get_LAB_L_SVD_V(image):
- """Returns V SVD from L of LAB Image information
- Args:
- image: PIL Image or Numpy array
- Returns:
- V matrix of SVD compression
- Example:
- >>> from PIL import Image
- >>> from ipfml import processing
- >>> img = Image.open('./images/test_img.png')
- >>> V = processing.get_LAB_L_SVD_V(img)
- >>> V.shape
- (200, 200)
- """
- L = metrics.get_LAB_L(image)
- return metrics.get_SVD_V(L)
- def rgb_to_mscn(image):
- """Convert RGB Image into Mean Subtracted Contrast Normalized (MSCN)
- Args:
- image: 3D RGB image Numpy array or PIL RGB image
- Returns:
- 2D Numpy array with MSCN information
- Example:
- >>> from PIL import Image
- >>> from ipfml import processing
- >>> img = Image.open('./images/test_img.png')
- >>> img_mscn = processing.rgb_to_mscn(img)
- >>> img_mscn.shape
- (200, 200)
- """
- # check if PIL image or not
- img_arr = np.array(image)
- # convert rgb image to gray
- im = np.array(color.rgb2gray(img_arr) * 255, 'uint8')
- return metrics.gray_to_mscn(im)
- def rgb_to_grey_low_bits(image, nb_bits=4):
- """Convert RGB Image into grey image using only 4 low bits values
- Args:
- image: 3D RGB image Numpy array or PIL RGB image
- nb_bits: optional parameter which indicates the number of bits to keep (default 4)
- Returns:
- 2D Numpy array with low bits information kept
- Example:
- >>> from PIL import Image
- >>> from ipfml import processing
- >>> img = Image.open('./images/test_img.png')
- >>> low_bits_grey_img = processing.rgb_to_grey_low_bits(img, 5)
- >>> low_bits_grey_img.shape
- (200, 200)
- """
- img_arr = np.array(image)
- grey_block = np.array(color.rgb2gray(img_arr) * 255, 'uint8')
- return metrics.get_low_bits_img(grey_block, nb_bits)
- def rgb_to_LAB_L_low_bits(image, nb_bits=4):
- """Convert RGB Image into Lab L channel image using only 4 low bits values
- Args:
- image: 3D RGB image Numpy array or PIL RGB image
- nb_bits: optional parameter which indicates the number of bits to keep (default 4)
- Returns:
- 2D Numpy array with low bits information kept
- Example:
- >>> from PIL import Image
- >>> from ipfml import processing
- >>> img = Image.open('./images/test_img.png')
- >>> low_bits_Lab_l_img = processing.rgb_to_LAB_L_low_bits(img, 5)
- >>> low_bits_Lab_l_img.shape
- (200, 200)
- """
- L_block = np.asarray(metrics.get_LAB_L(image), 'uint8')
- return metrics.get_low_bits_img(L_block, nb_bits)
- def rgb_to_LAB_L_bits(image, interval):
- """Returns only bits from LAB L canal specified into the interval
- Args:
- image: image to convert using this interval of bits value to keep
- interval: (begin, end) of bits values
- Returns:
- 2D Numpy array with reduced values
- >>> from PIL import Image
- >>> from ipfml import processing
- >>> img = Image.open('./images/test_img.png')
- >>> bits_Lab_l_img = processing.rgb_to_LAB_L_bits(img, (2, 6))
- >>> bits_Lab_l_img.shape
- (200, 200)
- """
- L_block = np.asarray(metrics.get_LAB_L(image), 'uint8')
- return metrics.get_bits_img(L_block, interval)
- def divide_in_blocks(image, block_size, pil=True):
- '''Divide image into equal size blocks
- Args:
- image: PIL Image or Numpy array
- block: tuple (width, height) representing the size of each dimension of the block
- pil: block type returned as PIL Image (default True)
- Returns:
- list containing all 2D Numpy blocks (in RGB or not)
- Raises:
- ValueError: If `image_width` or `image_height` are not compatible to produce correct block sizes
- Example:
- >>> import numpy as np
- >>> from PIL import Image
- >>> from ipfml import processing
- >>> from ipfml import metrics
- >>> image_values = np.random.randint(255, size=(800, 800, 3))
- >>> blocks = divide_in_blocks(image_values, (20, 20))
- >>> len(blocks)
- 1600
- >>> blocks[0].width
- 20
- >>> blocks[0].height
- 20
- >>> img_l = Image.open('./images/test_img.png')
- >>> L = metrics.get_LAB_L(img_l)
- >>> blocks_L = divide_in_blocks(L, (100, 100))
- >>> len(blocks_L)
- 4
- >>> blocks_L[0].width
- 100
- '''
- blocks = []
- mode = 'RGB'
- # convert in Numpy array
- image_array = np.array(image)
- # check dimension of input image
- if image_array.ndim != 3:
- mode = 'L'
- image_width, image_height = image_array.shape
- else:
- image_width, image_height, _ = image_array.shape
- # check size compatibility
- width, height = block_size
- if (image_width % width != 0):
- raise ValueError("Width size issue, block size not compatible")
- if (image_height % height != 0):
- raise ValueError("Height size issue, block size not compatible")
- nb_block_width = image_width / width
- nb_block_height = image_height / height
- for i in range(int(nb_block_width)):
- begin_x = i * width
- for j in range(int(nb_block_height)):
- begin_y = j * height
- # getting sub block information
- current_block = image_array[begin_x:(begin_x + width), begin_y:(
- begin_y + height)]
- if pil:
- blocks.append(
- Image.fromarray(current_block.astype('uint8'), mode))
- else:
- blocks.append(current_block)
- return blocks
- def fusion_images(images, pil=True):
- '''Fusion array of images into single image
- Args:
- images: array of images (PIL Image or Numpy array)
- pil: block type returned as PIL Image (default True)
- Returns:
- merged image from array of images
- Raises:
- ValueError: if `images` is not an array or is empty
- NumpyShapeComparisonException: if `images` array contains images with different shapes
- Example:
- >>> import numpy as np
- >>> from ipfml import processing
- >>> image_values_1 = np.random.randint(255, size=(800, 800, 3))
- >>> image_values_2 = np.random.randint(255, size=(800, 800, 3))
- >>> merged_image = processing.fusion_images([image_values_1, image_values_2], pil=False)
- >>> merged_image.shape
- (800, 800, 3)
- '''
- mode = 'RGB'
- dim = 1
- if len(images) == 0:
- raise ValueError('Empty array of images provided...')
- # convert image in numpy array (perhaps not necessary)
- images = [np.asarray(img) for img in images]
- image_array = images[0]
- if image_array.ndim != 3:
- mode = 'L'
- width, height = image_array.shape
- else:
- width, height, dim = image_array.shape
- # raise exception if all images do not have same shape
- if not np.array([image_array.shape == a.shape for a in images]).all():
- raise NumpyShapeComparisonException()
- if dim == 1:
- image_mean = np.empty([width, height])
- else:
- image_mean = np.empty([width, height, dim])
- nb_images = len(images)
- # construction of mean image from rotation
- for i in range(width):
- for j in range(height):
- if dim == 1:
- grey_value = 0
- # for each image we merge pixel values
- for img in images:
- grey_value += img[i][j]
- image_mean[i][j] = grey_value / nb_images
- else:
- for k in range(dim):
- canal_value = 0
- # for each image we merge pixel values
- for img in images:
- canal_value += img[i][j][k]
- image_mean[i][j][k] = canal_value / nb_images
- image_mean = np.array(image_mean, 'uint8')
- if pil:
- return Image.fromarray(image_mean, mode)
- else:
- return image_mean
- def rotate_image(image, angle=90, pil=True):
- '''Rotate image using specific angle
- Args:
- image: PIL Image or Numpy array
- angle: Angle value of the rotation
- pil: block type returned as PIL Image (default True)
- Returns:
- Image with rotation applied
- Example:
- >>> import numpy as np
- >>> from ipfml import processing
- >>> image_values = np.random.randint(255, size=(800, 800, 3))
- >>> rotated_image = processing.rotate_image(image_values, 90, pil=False)
- >>> rotated_image.shape
- (800, 800, 3)
- '''
- mode = 'RGB'
- image_array = np.asarray(image)
- if image_array.ndim != 3:
- mode = 'L'
- rotated_image = np.array(transform.rotate(image_array, angle)*255, 'uint8')
- if pil:
- return Image.fromarray(rotated_image, mode)
- else:
- return rotated_image
|