Source code for pyfibre.model.tools.feature

"""
PyFibre
Image Tools Library

Created by: Frank Longford
Created on: 09/03/2018

Last Modified: 18/02/2019
"""

from collections import defaultdict

import numpy as np

from skimage.feature.texture import check_nD


[docs]def calculate_metric(P, weights): results = np.apply_over_axes( np.sum, (P * weights), axes=(0, 1))[0, 0] return results
[docs]def glcm_product_props(P): """Calculate properties with weights involving product terms""" asm = calculate_metric(P, P) return asm, np.sqrt(asm)
[docs]def glcm_log_props(P): """Calculate properties with weights involving logarithmic terms""" nat_log = np.log(P) nat_log[P < 1e-15] = 0 entropy = calculate_metric(P, -nat_log) return entropy
[docs]def glcm_difference_props(p_matrix): """Calculate properties with weights involving difference terms""" num_level = p_matrix.shape[0] i, j = np.ogrid[: num_level, : num_level] # Create weights for specified property diff = i - j square = (diff ** 2).reshape((num_level, num_level, 1, 1)) absolute = (np.abs(diff)).reshape((num_level, num_level, 1, 1)) contrast = calculate_metric(p_matrix, square) dissimilarity = calculate_metric(p_matrix, absolute) homogeneity = calculate_metric(p_matrix, 1. / (1. + square)) similarity = calculate_metric(p_matrix, 1. / (1. + absolute)) return contrast, dissimilarity, homogeneity, similarity
[docs]def glcm_props(p_matrix): # Calculate properties related to correlation num_level = p_matrix.shape[0] i = np.arange(num_level).reshape((num_level, 1, 1, 1)) j = np.arange(num_level).reshape((1, num_level, 1, 1)) mean_i = calculate_metric(p_matrix, i * p_matrix) mean_j = calculate_metric(p_matrix, j * p_matrix) diff_i = i - mean_i diff_j = j - mean_j std_i = np.sqrt(calculate_metric(p_matrix, diff_i ** 2)) std_j = np.sqrt(calculate_metric(p_matrix, diff_j ** 2)) return mean_i, mean_j, diff_i, diff_j, std_i, std_j
[docs]def greycoprops_edit(P): """Edited version of the scikit-image greycoprops function, including additional properties""" check_nD(P, 4, 'P') (num_level, num_level2, num_dist, num_angle) = P.shape if num_level != num_level2: raise ValueError('num_level and num_level2 must be equal.') if num_dist <= 0: raise ValueError('num_dist must be positive.') if num_angle <= 0: raise ValueError('num_angle must be positive.') metrics = defaultdict(np.ndarray) # Compute property for each GLCM # Compute sum of all squared probabilities metrics['ASM'], metrics['energy'] = glcm_product_props(P) # Calculate Entropy metrics metrics['entropy'] = glcm_log_props(P) # Calculate standard weighted metrics (metrics['contrast'], metrics['dissimilarity'], metrics['homogeneity'], metrics['similarity']) = glcm_difference_props(P) # Calculate properties related to correlation i = np.arange(num_level).reshape((num_level, 1, 1, 1)) j = np.arange(num_level).reshape((1, num_level, 1, 1)) mean_i, mean_j, diff_i, diff_j, std_i, std_j = glcm_props(P) metrics['autocorrelation'] = calculate_metric(P, i * j) metrics['mean'] = 0.5 * (mean_i + mean_j) metrics['covariance'] = calculate_metric(P, diff_i * diff_j) metrics['clustering'] = calculate_metric(P, i + j - diff_i - diff_j) # Calculate correlation correlation = np.zeros((num_dist, num_angle), dtype=np.float64) mask_0 = std_i < 1e-15 mask_1 = ~mask_0 # handle the standard case correlation[mask_1] = ( metrics['covariance'][mask_1] / (std_i[mask_1] * std_j[mask_1])) # handle the special case of standard deviations near zero correlation[mask_0] = 1 metrics['correlation'] = correlation return metrics