Source code for flamingo.classification.features.relativelocation

import numpy as np
import pandas
import scipy.ndimage as nd
import matplotlib.pyplot as plt

import flamingo.classification.models

[docs]def compute_prior(annotations, centroids, image_size, superpixel_grid, n=100): ''' Compute relative location prior according to Gould et al. (2008) Parameters ---------- ds : string String indicating the dataset to be used. Returns ------- maps : pandas.Panel4D 4D panel containing the relative location prior maps: maps[<other class>][<given class>] gives a n*n dataframe representing the dimensionless image map Other parameters ---------------- n : integer Half the size of the dimensionless image map ''' nm, nn = image_size nx, ny = superpixel_grid annotations = np.reshape(annotations,(nx,ny)) classes = np.unique(annotations) # allocate normalized relation maps mapi = {c1:{c2:np.zeros((2*n,2*n)) for c2 in classes} for c1 in classes} # get centroids centroids = zip(*list(centroids)) m_mat = np.array(centroids[0]).reshape((nx,ny)) n_mat = np.array(centroids[1]).reshape((nx,ny)) # normalize centroid coordinates to map grid m_mat = np.round(m_mat.astype(np.float32)/(nm-1)*(n-1)) n_mat = np.round(n_mat.astype(np.float32)/(nn-1)*(n-1)) # loop over all superpixels for i in range(nx): for j in range(ny): # list indices in dimensionless image map that match the superpixel centroids ind_m = (m_mat - m_mat[i,j] + n - 1).ravel().astype(np.uint) ind_n = (n_mat - n_mat[i,j] + n - 1).ravel().astype(np.uint) # determine class of current superpixel c0 = annotations[i,j] # loop over classes in current image for c in classes: # add score matrix with offset to relation map mapi[c][c0][ind_m,ind_n] += (annotations == c).astype(np.uint).ravel() return mapi
def aggregate_maps(maplist): classes = np.unique([k for m in maplist for k in m.keys()]) n = maplist[0].values()[0].values()[0].shape[0] / 2 # allocate normalized relation maps maps = pandas.Panel4D(labels=classes, items=classes, major_axis=range(2*n), minor_axis=range(2*n)) maps = maps.fillna(1) # Use a simple, small, uniform prior to deal with empty (zero) counts in the histogram for mapi in maplist: for c, mapi_from in mapi.iteritems(): for c0, mapi_to in mapi_from.iteritems(): maps[c][c0] += mapi_to # normalization tot = maps.sum(axis = 'labels') for c1 in classes: maps.ix[:,c1,:,:] = maps.ix[:,c1,:,:].divide(tot[c1]).as_matrix() return maps
[docs]def smooth_maps(maps, sigma=2): ''' Convolve relative location prior maps with a gaussian filter for smoothing purposes Parameters ---------- ds : string String indicating the dataset to be used. maps : pandas.Panel4D 4D panel containing the relative location prior maps: maps[<other class>][<given class>] gives a n*n dataframe representing the dimensionless image map Returns ------- maps : pandas.Panel4D 4D panel containing the smoothed relative location prior maps. Other parameters ---------------- sigma : integer Size of the gaussian kernel that is to be convolved with the relative location prior maps ''' classes = maps.labels # convolution per map for c0 in classes: for c1 in classes: maps[c1][c0] = nd.gaussian_filter(maps[c1][c0].as_matrix(), sigma = sigma) # normalize per given class tot = maps.sum(axis = 'labels') for c0 in classes: maps.ix[:,c0,:,:] = maps.ix[:,c0,:,:].divide(tot[c0]).as_matrix() return maps
def vote_sets(Y, maps): votes = [] for i, row in enumerate(Y): votes.append([]) for j, col in enumerate(row): votes[i].append([]) for Yi in col: votes[i][j].append(vote_image(Yi, maps)[0]) return votes
[docs]def vote_image(Y, maps, centroids=None, img_size=None, winner_takes_all_mode=False): ''' Class voting based on 1st order prediction and relative location prior maps Parameters ---------- ds : string String indicating the dataset to be used. Ipred : list of lists of tuple of lists of arrays with size [n_models][n_partitions](training,testing)[n_images] Arrays contain the 1st order prediction of the labelled images. Returns ------- votes : pandas.Panel Panel containing the votes for all classes and superpixels: maps[<class>] gives a nx*ny dataframe representing the probability of every superpixel to be <class> Ivote : np.array Labelled image based on classes in votes with maximum probability for every superpixel ''' Ipred = np.asarray(Y) nx, ny = Ipred.shape classes = maps.keys() maps = dict_to_panel(maps) votes = pandas.Panel(items = classes, major_axis = range(nx), minor_axis = range(ny)) votes = votes.fillna(0) n = maps.shape[-1] / 2 # compute normalized centroids (FIXME: remove None options) if centroids is None: xn, xs = np.linspace(0, n, nx, endpoint=False, retstep=True) yn, ys = np.linspace(0, n, ny, endpoint=False, retstep=True) cxn, cyn = np.meshgrid(yn + ys/2, xn + xs/2) else: cx, cy = [np.asarray(c).reshape((nx,ny)).astype(np.float32) for c in zip(*list(centroids))] if img_size is None: cxn = cx / np.max(cx) * (n-1) cyn = cy / np.max(cy) * (n-1) else: cxn = cx / (img_size[0]-1) * (n-1) cyn = cy / (img_size[1]-1) * (n-1) # for every superpixel, loop over the relative location maps for i in range(nx): for j in range(ny): rx = np.round(cxn - cxn[i,j] + n - 1).flatten().astype(np.uint) ry = np.round(cyn - cyn[i,j] + n - 1).flatten().astype(np.uint) c0 = Ipred[i,j] # get assignments with highest percentage if winner_takes_all_mode: highest_perc = np.zeros((nx, ny)) assignments = np.array(['' for ii in range(nx*ny)], dtype='a%d' % np.max([len(c) for c in classes])).reshape((nx,ny)) for c in classes: p = maps[c][c0].as_matrix()[ry,rx].reshape((nx,ny)) idx = p > highest_perc assignments[idx] = c highest_perc[idx] = p[idx] for c in classes: votes[c] += (assignments == c) else: # vote classes for c in classes: votes[c] += maps[c][c0].as_matrix()[ry,rx].reshape((nx,ny)) # normalize votes by superpixel grid size for c in votes.keys(): votes[c] = votes[c] / np.prod((nx,ny)) Ivote = pandas.DataFrame([votes.major_xs(i).idxmax(axis=1) for i in range(votes.shape[1])]) return votes, Ivote.as_matrix()
def compute_features(models, sets, maps, stats, features): # remove relative location features from sets for j, sets_parts in enumerate(sets): # loop over partitions for k, sets_img in enumerate(sets_parts): # loop over images for c in maps.iterkeys(): s = 'prob_%s' % c idx = list(features).index(s) sets[j][0][k][...,idx] = 0.0 # do first order prediction Y_predicted = flamingo.classification.models.predict_models(models, [s[0] for s in sets]) # do voting based on first prediction round and relative location prior votes = vote_sets(Y_predicted, maps) # translate voted probabilities to relative location features sets = votes_to_features(sets, votes, stats, features) return sets def votes_to_features(sets, votes, stats, features): # copy sets for each model sets = [sets for i in votes] for i, vote_models in enumerate(votes): # loop over models for j, vote_parts in enumerate(vote_models): # loop over partitions for k, vote_img in enumerate(vote_parts): # loop over images sets[i][j][0][k] = votes_to_feature(sets[i][j][0][k], vote_img, stats, features) return sets def votes_to_feature(X, votes, stats, features): for c in votes.items: s = 'prob_%s' % c avg = stats['avg'][s] std = np.sqrt(stats['var'][s]) val = votes[c].as_matrix() idx = list(features).index(s) X[...,idx] = (val - avg) / std return X def add_features(votes, features, features_in_block): features_in_block['relloc'] = [] for c in votes.items: s = 'prob_%s' % c features[s] = votes[c].as_matrix().ravel() features_in_block['relloc'].append(s) return features, features_in_block def remove_features(X, classes): # for i in range(len(X)): for c in classes: # X[i]['prob_%s' % c] = 0.0 X['prob_%s' % c] = 0.0 return X def panel_to_dict(maps): return {c1:{c0: maps[c1][c0].as_matrix() for c0 in maps.labels} for c1 in maps.items} def dict_to_panel(maps): return pandas.Panel4D(maps) def plot_maps(maps, figsize=(20,20), cmap='Reds'): classes = maps.keys() n = len(classes) fig, axs = plt.subplots(n,n,figsize=figsize) for k1 in classes: for k2 in classes: i = maps.keys().index(k1) j = maps.keys().index(k2) axs[i,j].matshow(maps[k1][k2], cmap=cmap) axs[i,j].set_xticks([]) axs[i,j].set_yticks([]) for i, classi in enumerate(classes): axs[i,0].set_ylabel(classi) axs[0,i].set_title(classi) return fig, axs def plot_votes(y, figsize=(7,5)): classes = np.unique(y) img = np.zeros(np.asarray(y).shape) for i, c in enumerate(classes): img[y == c] = i fig, axs = plt.subplots(figsize=figsize) axs.matshow(img) return fig, axs