Source code for forensicfit.utils.image_tools

# -*- coding: utf-8 -*-

from skimage.color import rgb2gray
import cv2
import numpy as np
import matplotlib.pylab as plt
from skimage import exposure, filters
from pathlib import Path


IMAGE_EXTENSIONS = ['.png', '.bmp', '.dib', '.jpeg',
                    '.jpg', '.jpe', '.jp2', '.webp',
                    '.pbm', '.pgm', '.ppm', '.pxm',
                    '.pnm', '.sr', '.ras', '.tiff',
                    '.tif', '.exr', '.hdr', '.pic']


[docs]def rotate_image(image, angle): """ Rotates the image by angle degrees Parameters ---------- angle : float Angle of rotation. Returns ------- None. """ image_center = tuple(np.array(image.shape[1::-1]) / 2) rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0) image = cv2.warpAffine( image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR) return image
[docs]def gaussian_blur(image, window=(15, 15)): """ This method applies Gaussian Blur filter to the image. Parameters ---------- window : tuple int, optional The window in which the gaussian blur is going to be applied. The default is (15,15). Returns ------- None. """ image = cv2.GaussianBlur(image, window, 0) return image
[docs]def split_v(image, pixel_index=None, pick_side='L', flip=True): """ This method splits the image in 2 images based on the fraction that is given in pixel_index Parameters ---------- pixel_index : float, optional fraction in which the image is going to be split. The value should be a number between zero and one. The default is 0.5. pick_side : str, optional The side in which will over write the image in the class. The default is 'L'. Returns ------- None. """ width = image.shape[1] if pixel_index is None: pixel_index = width//2 if pixel_index < 1: pixel_index = int(width*pixel_index) if pick_side == 'L': image = image[:, 0:pixel_index] else: if flip: image = np.fliplr(image[:, pixel_index:width]) else: image = image[:, pixel_index:width] return image
[docs]def to_gray(image: np.ndarray, mode='SD') -> np.ndarray: """Gray Scale image of the input image. modes: 'BT.470' and 'BT.709' SD 'BT.470' : Y = 0.299 R + 0.587 G + 0.114 B HD 'BT.709' : Y = 0.2125 R + 0.7154 G + 0.0721 B Returns ------- gray_scale : cv2 object Gray Scale image of the input image. """ if len(image.shape) == 2: return image elif len(image.shape) == 3: if image.shape[2] == 1: return image elif image.shape[2] == 3: if mode == 'SD': return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) elif mode == 'HD': return rgb2gray(image)
[docs]def to_rbg(image): if len(image.shape) == 3 and image.shape[2] == 3: return image else: return cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
[docs]def flip(image): return cv2.flip(image, 0)
[docs]def contours(image, mask_threshold=60): """ A list of pixels that create the contours in the image Returns ------- contours : list A list of pixels that create the contours in the image """ masked = get_masked(image, mask_threshold) contours, _ = cv2.findContours( masked, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) return contours
[docs]def largest_contour(contours): """ A list of pixels forming the contour with the largest area Returns ------- contour_max_area : list A list of pixels forming the contour with the largest area """ max_con = 0 max_con_arg = 0 for ic in range(len(contours)): if cv2.contourArea(contours[ic]) > max_con: max_con = cv2.contourArea(contours[ic]) max_con_arg = ic contour_max_area = contours[max_con_arg] return contour_max_area
[docs]def remove_background(image: np.array, contour: np.array, outside: bool = True, pixel_value: int = 0): """Removes the background outside or inside the contour Parameters ---------- image : np.array _description_ contour : np.array _description_ outside : bool, optional _description_, by default True pixel_value : int, optional _description_, by default 0 """ bkg = np.ones_like(image)*pixel_value bkg = cv2.fillPoly(bkg, [contour], (255, 255, 255)) image = cv2.bitwise_and(image, bkg) return image
[docs]def get_masked(image, mask_threshold): """ Populates the masked image with the gray scale threshold Returns ------- None. """ masked = cv2.inRange(image, mask_threshold, 255) return masked
[docs]def resize(image, size): """ This method resizes the image to the pixel size given. Parameters ---------- size : tuple int, The target size in which the image is going to be resized. Returns ------- None. """ size = tuple(size) assert len(size) == 2, 'Resizing needs two dimensions' image = cv2.resize(image, size) return image
[docs]def exposure_control(image: np.ndarray, mode: str = 'equalize_hist', **kwargs) -> np.ndarray: """modifies the exposure Parameters ---------- mode : str, optional Type of exposure correction. It can be selected from the options: ``'equalize_hist'`` or ``'equalize_adapthist'``. `equalize_hist <https://scikit-image.org/docs/stable/api/skimage.exposure.html#equalize-hist>`_ and `equalize_adapthist <https://scikit-image.org/docs/stable/api/skimage.exposure.html#equalize-adapthist>` use sk-image. by default 'equalize_hist' """ exps = {'equalize_hist': exposure.equalize_hist, 'equalize_adapthist': exposure.equalize_adapthist} assert mode in exps, 'Mode not valid.' image = exps[mode](image, **kwargs) return (image*255).astype('uint8')
[docs]def apply_filter(image: np.ndarray, mode: str, **kwargs) -> np.ndarray: """Applies different types of filters to the image Parameters ---------- mode : str Type of filter to be applied. The options are * ``'meijering'``: <Meijering neuriteness filter https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.meijering>_, * ``'frangi'``: < Frangi vesselness filter https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.frangi>_, * ``'prewitt'``: <Prewitt transform https://scikit-image.org/docs/stable/api/skimage.filters.html#prewitt>_, * ``'sobel'``: <Sobel filter https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.sobel>_, * ``'scharr'``: <Scharr transform https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.scharr>, * ``'roberts'``: <Roberts' Cross operator https://scikit-image.org/docs/stable/api/skimage.filters.html#examples-using-skimage-filters-roberts>_, * ``'sato'``: <Sato tubeness filter https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.sato>_. """ flts = { 'meijering': filters.meijering, 'frangi': filters.frangi, 'prewitt': filters.prewitt, 'sobel': filters.sobel, 'scharr': filters.scharr, 'roberts': filters.roberts, 'sato': filters.sato } assert mode in flts, 'Filter not valid.' if mode == 'roberts': if image.ndim != 2: print('Cannot apply roberts to color images') return image = flts[mode](image, **kwargs) return (image*255).astype('uint8')
[docs]def binerized_mask(image, masked): """ This function return the binarized version of the tape Returns ------- 2d array of the image . """ # image = cv2.bitwise_and(image, # image, # mask=masked) return cv2.bitwise_and(image, image, mask=masked)
[docs]def imwrite(fname: str, image: np.array, cmap='gray', **kwargs): """save any 2d numpy array (or list) to an image file Parameters ---------- fname : str flie name to be saved image : np.array 2d numpy array (or list) to be saved """ fname = Path(fname) fname.parent.mkdir(exist_ok=True) fname = fname.as_posix() # cv2.imwrite(fname, image) # else: plt.imsave(fname, image, cmap=cmap, **kwargs)