def smooth_resize(img, n_rows, n_cols, smooth_type): ##----CAUTION--- ## THIS FUNCTION DOES NOT UPSCALE ON ONE AXIS AND DOWNSCALE IN THE OTHER # smooth_type= gaussian, bilinear interpolation, median or whatever # flag: 0 down else up if n_rows==img.shape[0]: return img if n_cols==img.shape[1]: return img flag = n_rows > img.shape[0] ratio_rows = (n_rows)*1.0 / img.shape[0] ratio_cols = (n_cols)*1.0 / img.shape[1] if flag: kernel_size = (math.ceil((ratio_rows + ratio_cols) / 2))*2-1 else: kernel_size = (math.ceil(math.log(math.ceil((math.pow(ratio_rows,-1) + math.pow(ratio_cols,-1)) / 2),2)))* 2 + 1 resized_img = Sampling.simple_resize(img, n_rows, n_cols) if flag else Sampling.simple_resize(img, n_rows, n_cols) if smooth_type == Sampling.FILTER_MEDIAN: return conv.median_filter_nd(resized_img, kernel_size) elif smooth_type == Sampling.FILTER_BILINEAR_INTERPOLATION: return conv.convolution_nd(resized_img, ker.bilinear_interpolation(kernel_size)) elif smooth_type == Sampling.FILTER_GAUSSIAN: return conv.convolution_nd(resized_img, ker.gaussian(kernel_size))
def __init__( self, shape, **kwargs ): self.shape = shape self.posecells = zeros(shape) #NOTE: might not need if gaussian_filter works self.kernel_3d = self.diff_gaussian( PC_E_DIM, PC_I_DIM, PC_E_SIGMA, PC_I_SIGMA, order=3 ) self.kernel_2d = self.diff_gaussian( PC_E_DIM, PC_I_DIM, PC_E_SIGMA, PC_I_SIGMA, order=2 ) self.kernel_1d = self.diff_gaussian( PC_E_DIM, PC_I_DIM, PC_E_SIGMA, PC_I_SIGMA, order=1 ) self.kernel_1d_sep = self.diff_gaussian_separable( PC_E_DIM, PC_I_DIM, PC_E_SIGMA, PC_I_SIGMA ) self.global_inhibition = PC_GLOBAL_INHIB self.pc_vtrans_scale = PC_CELL_X_SIZE self.pc_vrot_scale = 2.0*pi/shape[2]#PC_C_SIZE_TH #TODO: maybe change everything to float32 to make it go faster? #self.conv = Convolution( im=self.posecells, fil=self.kernel_1d, sep=True, type=float64 ) #self.conv = Convolution( im=self.posecells, fil=self.kernel_1d_sep, sep=True, type=float64 ) self.conv = Convolution( im=self.posecells, fil=self.kernel_3d, sep=False, type=float64 ) filter = self.diff_gaussian_offset_2d( PC_E_SIGMA, PC_I_SIGMA, shape=(7,7), origin=(0,0) ) #self.conv.new_filter( self.kernel_2d, dim=2 ) self.conv.new_filter( filter, dim=2 ) self.filter_dict_2d = self.build_diff_gaussian_set_2d( PC_E_SIGMA, PC_I_SIGMA, shape=(7,7), precision=1 ) self.filter_dict_2d_precision = 10 # multiple the decimal by this number to get the right key
def convoluteWavs(self,wav): BLOCKSIZE = 1024 def preprocess(): if self.audioData.shape[0] < wav.audioData.shape[0]: audioSize = self.audioData.shape[0] if audioSize%BLOCKSIZE != 0: lastblock = self.audioData[(self.audioData.shape[0]-(self.audioData.shape[0]%BLOCKSIZE)):] temp = self.audioData[:(self.audioData.shape[0]-(self.audioData.shape[0]%BLOCKSIZE))] self.audioData = np.concatenate((temp,WavProcessing.pad(len(lastblock),lastblock,BLOCKSIZE))) resultConv = np.zeros((self.audioData.shape[0],2),dtype=np.int16) elif self.audioData.shape[0] >= wav.audioData.shape[0]: audioSize = wav.audioData.shape[0] if audioSize%BLOCKSIZE != 0: lastblock = wav.audioData[(wav.audioData.shape[0]-(wav.audioData.shape[0]%BLOCKSIZE)):] temp = wav.audioData[:(wav.audioData.shape[0]-(wav.audioData.shape[0]%BLOCKSIZE))] wav.audioData = np.concatenate((temp,WavProcessing.pad(len(lastblock),lastblock,BLOCKSIZE))) resultConv = np.zeros((wav.audioData.shape[0],2),dtype=np.int16) return resultConv,Matrix.ceil(audioSize,BLOCKSIZE) resultConv, nblocks = preprocess() for i in xrange(nblocks): start = BLOCKSIZE*i end = BLOCKSIZE*(i+1) conv = Convolution(Matrix(self.audioData[start:end,0].tolist(),0),Matrix(wav.audioData[start:end,0].tolist(),0),Convolution.CIRCULAR) resultConv[start:end] = conv.convolute() self.audioData = resultConv[:] conv._plot()
class Conv(Layer): def __init__(self, n_filters, filter_shape,weight_scale,weight_decay): self.n_filters = n_filters self.filter_shape = filter_shape self.weight_scale = weight_scale self.weight_decay = weight_decay self.conv_ob = Convolution() def setup(self, input_shape, rng): n_featuremaps = input_shape[1] W_shape = (n_featuremaps, self.n_filters) + self.filter_shape # this appends the filter shape eg : (16,4,3,3) self.W = rng.normal( size=W_shape, scale=self.weight_scale) # generate random filters with gaussian(normal) distribution self.b = numpy.zeros(self.n_filters) # initialize bias weights equal to zero def params(self): return self.W, self.b def param_incs(self): return self.dW, self.db def set_params(self,W,b): self.W = W self.b = b def output_shape(self, input_shape): # Zero padding is considered height = input_shape[2] #- self.filter_shape[0] + 1 width = input_shape[3] #- self.filter_shape[1] + 1 shape = (input_shape[0], self.n_filters, height, width) return shape def forward_propogation(self, input): # forward propogation print("Forward Propogation : Convolution") self.last_input = input # activation this layer self.last_input_shape = input.shape # shape of activation conv_shape = self.output_shape(input.shape) convout = self.conv_ob.convolve(input,self.W,conv_shape) z=self.W return convout + self.b[numpy.newaxis, :, numpy.newaxis, numpy.newaxis] def backward_propogation(self, output_grad): # backward propogation of gradients print("Backward Propogation : Convolution") input_grad = numpy.empty(self.last_input_shape) self.dW = numpy.zeros(self.W.shape) # Convolve input_grad, self.dW = self.conv_ob.convolve_backprop(self.last_input, output_grad, self.W, self.dW) n_imgs = output_grad.shape[0] self.db = numpy.sum(output_grad, axis=(0, 2, 3)) / (n_imgs) self.dW =self.dW - self.weight_decay * self.W return input_grad
def resol_spectrum (self,E,a,b,ordering,plot_this=False): if (ordering < -1) or (ordering > 1): print('Error: set ordering = 1 for NO, -1 for IO, 0 for both') return -1 Reactor_Spectrum.unosc_spectrum(self,E) Oscillation_Prob.eval_prob(self,E,0) self.norm_osc_spect_N = self.norm_spectrum_un * self.prob_E_N self.norm_osc_spect_I = self.norm_spectrum_un * self.prob_E_I #Evis = E - 0.8 ### class Convolution conv = Convolution() print('\n...adding experimental resolution via numerical convolution...') print('\nIt might take a while') self.resol_N = conv.numerical_conv(self.norm_osc_spect_N,E,a=a,b=b) self.resol_I = conv.numerical_conv(self.norm_osc_spect_I,E,a=a,b=b) if plot_this: fig = plt.figure() #fig.suptitle(r'Antineutrino spectrum') ax = fig.add_subplot(111) ax.legend() ax.grid() ax.set_xlabel(r'$\text{E}_{\text{vis}}$ [\si{MeV}]') ax.set_ylabel(r'N($\bar{\nu}$) [arb. unit]') ax.set_ylim(-0.005,0.095) ax.set_title(r'Antineutrino spectrum' + '\nwith finite energy resolution') if ordering == 1: # NO ax.plot(E-0.8,self.resol_N,'b',linewidth=1,label='NO') ax.legend() fig.savefig('AntineutrinoSpectrum/resol_spectrum_N.pdf',format='pdf',transparent=True) print('\nThe plot has been saved in AntineutrinoSpectrum/resol_spectrum_N.pdf') if ordering == -1: # IO ax.plot(E-0.8,self.resol_I,'r',linewidth=1,label='IO') ax.legend() fig.savefig('AntineutrinoSpectrum/resol_spectrum_I.pdf',format='pdf',transparent=True) print('\nThe plot has been saved in AntineutrinoSpectrum/resol_spectrum_I.pdf') if ordering == 0: # both NO and IO ax.plot(E-0.8,self.resol_N,'b',linewidth=1,label='NO') ax.plot(E-0.8,self.resol_I,'r--',linewidth=1,label='IO') ax.legend() fig.savefig('AntineutrinoSpectrum/resol_spectrum.pdf', format='pdf', transparent=True) print('\nThe plot has been saved in AntineutrinoSpectrum/resol_spectrum.pdf') return self.resol_N, self.resol_I
def __init__(self): '''Get the four layer's kernels, create the correlations and a convolution wrapper. :const MIN_IMG_WIDTH: Minimum image width for which to use NumPy/SciPy for convolution ''' self.kernels = DifferenceOfGaussians() self.correlations = Correlation(self.kernels.full_kernels) self.convolver = Convolution() self.MIN_IMG_WIDTH = 256
class MapDNF(FieldMap): def __init__(self, name, size, dt=0.1, wrap=True, tau=0.64, h=0, model='cnft', th=0.75, iExc=1.25, iInh=0.7, wExc=0.1, wInh=10, alpha=10, mapSize=1., **kwargs): super(MapDNF, self).__init__(name, size, dt=dt, wrap=wrap, tau=tau, h=h, model=model, th=th, **kwargs) self.act = ActivationMap(name + "_activation", size, dt=dt, model=model, th=th) self.lat = Convolution(name + "_lateral", size, dt=dt, wrap=wrap) self.kernel = LateralWeightsMap(name + "_kernel", mapSize=mapSize, globalSize=size, wrap=wrap, iExc=iExc, iInh=iInh, wExc=wExc, wInh=wInh, alpha=alpha) self.act.addChildren(field=self) self.addChildren(lat=self.lat) self.lat.addChildren(source=self.act, kernel=self.kernel) self.kernel.compute() def getActivation(self): return self.act def getArrays(self): return [ self.act, self.lat, ]
def plotDefaults(self): self.convolution = Convolution() self.plotUpdate() self.updateSlider() self.tminXInput.setText('{}'.format(self.convolution.getMinRangeX())) self.tminHInput.setText('{}'.format(self.convolution.getMinRangeH())) self.tmaxXInput.setText('{}'.format(self.convolution.getMaxRangeX())) self.tmaxHInput.setText('{}'.format(self.convolution.getMaxRangeH())) self.XFunctionInput.setText('{}'.format(self.convolution.getXFunctionString())) self.HFunctionInput.setText('{}'.format(self.convolution.getHFunctionString()))
def __init__(self): super().__init__() self.title = 'La construction de la convolution' self.left = 50 self.top = 50 self.width = 1600 self.height = 900 self.sliderTimeFactor = 10 self.modeEcho = True self.convolution = Convolution() self.initUI() self.plotDefaults()
def convoluteWavs(self, wav): BLOCKSIZE = 1024 def preprocess(): if self.audioData.shape[0] < wav.audioData.shape[0]: audioSize = self.audioData.shape[0] if audioSize % BLOCKSIZE != 0: lastblock = self.audioData[( self.audioData.shape[0] - (self.audioData.shape[0] % BLOCKSIZE)):] temp = self.audioData[:( self.audioData.shape[0] - (self.audioData.shape[0] % BLOCKSIZE))] self.audioData = np.concatenate( (temp, WavProcessing.pad(len(lastblock), lastblock, BLOCKSIZE))) resultConv = np.zeros((self.audioData.shape[0], 2), dtype=np.int16) elif self.audioData.shape[0] >= wav.audioData.shape[0]: audioSize = wav.audioData.shape[0] if audioSize % BLOCKSIZE != 0: lastblock = wav.audioData[( wav.audioData.shape[0] - (wav.audioData.shape[0] % BLOCKSIZE)):] temp = wav.audioData[:( wav.audioData.shape[0] - (wav.audioData.shape[0] % BLOCKSIZE))] wav.audioData = np.concatenate( (temp, WavProcessing.pad(len(lastblock), lastblock, BLOCKSIZE))) resultConv = np.zeros((wav.audioData.shape[0], 2), dtype=np.int16) return resultConv, Matrix.ceil(audioSize, BLOCKSIZE) resultConv, nblocks = preprocess() for i in xrange(nblocks): start = BLOCKSIZE * i end = BLOCKSIZE * (i + 1) conv = Convolution( Matrix(self.audioData[start:end, 0].tolist(), 0), Matrix(wav.audioData[start:end, 0].tolist(), 0), Convolution.CIRCULAR) resultConv[start:end] = conv.convolute() self.audioData = resultConv[:] conv._plot()
def __init__( self, input_dim=(1, 28, 28), conv_param={ 'filter_num': 30, 'filter_size': 5, 'pad': 0, 'stride': 1 }, hidden_size=100, output_size=10, weight_init_std=0.01 ): # 畳み込み層のハイパーパラメータ filter_num = conv_param['filter_num'] filter_size = conv_param['filter_size'] filter_pad = conv_param['pad'] filter_stride = conv_param['stride'] input_size = input_dim[1] conv_output_size = (input_size - filter_size + 2 * filter_pad) / filter_stride + 1 pool_output_size = int( filter_num * (conv_output_size / 2) * (conv_output_size / 2) ) # 重みパラメータ self.params = {} self.params['W1'] = weight_init_std * \ np.random.randn(filter_num, input_dim[0], filter_size, filter_size) self.params['b1'] = np.zeros(filter_num) self.params['W2'] = weight_init_std * \ np.random.randn(pool_output_size, hidden_size) self.params['b2'] = np.zeros(hidden_size) self.params['W3'] = weight_init_std * \ np.random.randn(hidden_size, output_size) self.params['b3'] = np.zeros(output_size) # レイヤー self.layers = OrderedDict() self.layers['Conv1'] = Convolution( self.params['W1'], self.params['b1'], conv_param['stride'], conv_param['pad'] ) self.layers['Relu1'] = Relu() self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2) self.layers['Affine2'] = Affine(self.params['W2'], self.params['b2']) self.layers['Relu2'] = Relu() self.layers['Affine3'] = Affine(self.params['W3'], self.params['b3']) self.last_layer = Softmax()
def createConvolution(self): width = 1280 height = 720 window_width = 50 window_height = 40 # Break image into 18 vertical layers since image height is 720 margin = 100 # How much to slide left and right for searching print("warped shape: ", warped.shape) rough_lane_width = 897 return Convolution(width = width, height = height, window_width = window_width, window_height = window_height, margin = margin, rough_lane_width = rough_lane_width)
def Convolution(x, args, name): """ Create a convolutional layer with :param x: the placeholder for the tensor :param args: the arguments for the convolution (filter, strides, padding) :param name: a label for the operation :return: a convolved tensor """ from convolution import Convolution return Convolution(x, args, name)
def __init__(self): output_size = 10 hidden_size = 12 self.modules = [ Reshape((28, 28), (28, 28, 1)), Convolution((28, 28, 1), 5, 8), # to 24 MaxPool(2), # to 12 Pad(1), # to 14 Convolution((14, 14, 8), 3, 16), #to 12 MaxPool(2), # to 6 Convolution((6, 6, 16), 3, 24), # to 4 MaxPool(2), # to 2 Reshape((2,2,24),(2 * 2 * 24,)), MatrixMult([2 * 2 * 24, hidden_size]), MatrixAdd([hidden_size]), Relu(), MatrixMult([hidden_size, output_size]), Softmax(), ]
def __init__(self, n_filters, filter_shape,weight_scale,weight_decay): self.n_filters = n_filters self.filter_shape = filter_shape self.weight_scale = weight_scale self.weight_decay = weight_decay self.conv_ob = Convolution()
class Focal(): '''Filter Overlap Correction ALgorithm, simulates the foveal pit region of the human retina. Created by Basabdatta Sen Bhattacharya. See DOI: 10.1109/TNN.2010.2048339 ''' def __init__(self): self.kernels = DifferenceOfGaussians() self.correlations = Correlation(self.kernels.full_kernels) self.convolver = Convolution() self.MIN_IMG_WIDTH = 256 def apply(self, image, spikes_per_unit=0.3): spike_images = self.filter_image(image) focal_spikes = self.focal(spike_images, spikes_per_unit=spikes_per_unit) return focal_spikes def focal(self, spike_images, spikes_per_unit=0.3): '''Filter Overlap Correction ALgorithm, simulates the foveal pit region of the human retina. Created by Basabdatta Sen Bhattacharya. See DOI: 10.1109/TNN.2010.2048339 spike_images => A list of the values generated by the convolution procedure, stored as four 2D arrays, each with the same size/shape of the original image. spikes_per_unit => Percentage of the total spikes to be processed, specified in a per unit [0, 1] range. returns: an ordered list of [spike index, sorting value, cell layer/type] tuples. ''' ordered_spikes = [] img_size = spike_images[0].size img_shape = spike_images[0].shape height, width = img_shape num_images = len(spike_images) #how many non-zero spikes are in the images max_cycles = 0 for i in range(num_images): max_cycles += numpy.sum(img[i] != 0) total_spikes = max_cycles.copy() #reduce to desired number max_cycles = numpy.int(spikes_per_unit*max_cycles) #copy images from list to a large image to make it a single search space big_shape = (height*2, width*2) big_image = numpy.zeros(big_shape) big_coords = [(0, 0), (0, width), (height, 0), (height, width)] for cell_type in range(num_images): row, col = big_coords[cell_type] tmp_img = original_img[cell_type].copy() tmp_img[numpy.where(tmp_img == 0)] = -numpy.inf big_image[row:row+height, col:col+width] = tmp_img # Main FoCal loop for count in xrange(max_cycles): # print out completion percentage percent = (count*100.)/float(total_spikes-1) sys.stdout.write("\rFocal %d%%"%(percent)) # Get maximum value's index max_idx = numpy.argmax(img_copies) # and its coordinates max_coords = numpy.unravel_index(max_idx, big_shape) # and the value max_val = big_image[max_coords] if max_val == numpy.inf or max_val == -numpy.inf or max_val == numpy.nan: sys.stderr.write("\nWrong max value in FoCal!") break # translate coordinates from the big image's to a single image coordinates if max_coords[0] < height and max_coords[1] < width: single_coords = max_coords else: single_coords = self.global_to_single_coords(max_coords, img_shape) # calculate a local index, to store per ganglion cell layer info local_idx = single_coords[0]*width + single_coords[1] # calculate the type of cell from the index cell_type = self.cell_type_from_global_coords(max_coords, img_shape) # append max spike info to return list ordered_spikes.append([local_idx, max_val, cell_type]) # correct surrounding pixels for overlapping kernel influence for overlap_cell_type in range(len(original_img)): # get equivalent coordinates for each layer overlap_idx = self.local_coords_to_global_idx(single_coords, overlap_cell_type, img_shape, big_shape) is_max_val_layer = overlap_cell_type == cell_type # c_i = c_i - c_{max}<K_i, K_{max}> self.adjust_with_correlation_g(big_image, self.correlations[cell_type]\ [overlap_cell_type], overlap_idx, max_val, is_max_val_layer=is_max_val_layer) return ordered_spikes def filter_image(self, img, force_homebrew=False): '''Perform convolution with calculated kernels img => the image to convolve force_hombrew => if True: use my separated convolution code else: use SciPy sepfir2d ''' num_kernels = len(self.kernels.full_kernels) img_width, img_height = img.shape convolved_img = {} for cell_type in range(num_kernels): if img_width < self.MIN_IMG_WIDTH or img_height < self.MIN_IMG_WIDTH: force_homebrew = True else: force_homebrew = False c = self.convolver.dog_sep_convolution(img, self.kernels[cell_type], cell_type, originating_function="filter", force_homebrew=force_homebrew) convolved_img[cell_type] = c return convolved_img def adjust_with_correlation(self, img, correlation, max_idx, max_val, is_max_val_layer=True): img_height, img_width = img.shape correlation_width = correlation.shape[0] half_correlation_width = correlation_width/2 half_img_width = img_width/2 half_img_height = img_height/2 # Get max value's coordinates row, col = idx2coord(max_idx, img_width) row_idx = row/half_img_height col_idx = col/half_img_width # Calculate the zone to affect with the correlation up_lim = (row_idx)*half_img_height left_lim = (col_idx)*half_img_width down_lim = (row_idx + 1)*half_img_height right_lim = (col_idx + 1)*half_img_width max_img_row = numpy.min([down_lim - 1, row + half_correlation_width + 1]) max_img_col = numpy.min([right_lim - 1, col + half_correlation_width + 1]) min_img_row = numpy.max([up_lim, row - half_correlation_width]) min_img_col = numpy.max([left_lim, col - half_correlation_width]) max_img_row_diff = max_img_row - row max_img_col_diff = max_img_col - col min_img_row_diff = row - min_img_row min_img_col_diff = col - min_img_col min_knl_row = half_correlation_width - min_img_row_diff min_knl_col = half_correlation_width - min_img_col_diff max_knl_row = half_correlation_width + max_img_row_diff max_knl_col = half_correlation_width + max_img_col_diff img_r = [r for r in range(min_img_row, max_img_row)] img_c = [c for c in range(min_img_col, max_img_col)] knl_r = [r for r in range(min_knl_row, max_knl_row)] knl_c = [c for c in range(min_knl_col, max_knl_col)] # c_i = c_i - c_{max}<K_i, K_{max}> img[img_r, img_c] -= max_val*correlation[knl_r, knl_c] # mark any weird pixels as -inf so they don't matter in the search inf_indices = numpy.where(img[img_r, img_c] == numpy.inf) img[inf_indices] = 0 img[inf_indices] -= numpy.inf nan_indices = numpy.where(img[img_r, img_c] == numpy.nan) img[nan_indices] = 0 img[nan_indices] -= numpy.inf # mark max value's coordinate to -inf to get it out of the search if is_max_val_layer: img[row, col] -= numpy.inf # No need to return, values are affected because I'm doing = and -= ops def local_coords_to_global_idx(self, coords, cell_type, local_img_shape, global_img_shape): row_add = cell_type/2 col_add = cell_type%2 global_coords = (coords[0] + row_add*local_img_shape[0], coords[1] + col_add*local_img_shape[1]) global_idx = global_coords[0]*global_img_shape[1] + global_coords[1] return global_idx def global_to_single_coords(self, coords, single_shape): row_count = coords[0]/single_shape[0] col_count = coords[1]/single_shape[1] new_row = coords[0] - single_shape[0]*row_count new_col = coords[1] - single_shape[1]*col_count return (new_row, new_col) def cell_type_from_global_coords(self, coords, single_shape): row_type = coords[0]/single_shape[0] col_type = coords[1]/single_shape[1] cell_type = row_type*2 + col_type return cell_type
class App(QWidget): def __init__(self): super().__init__() self.title = 'La construction de la convolution' self.left = 50 self.top = 50 self.width = 1600 self.height = 900 self.sliderTimeFactor = 10 self.modeEcho = True self.convolution = Convolution() self.initUI() self.plotDefaults() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.show() self.createCanvas() self.createWidgets() self.createGridLayout() def createCanvas(self): # Figure and canvas instances - canvas takes the `figure` instance as a parameter to __init__ self.figureX = plt.figure() self.figureH = plt.figure() self.figureRelative = plt.figure() self.figureResult = plt.figure() self.figureProducts = plt.figure() self.canvasX = FigureCanvas(self.figureX) self.canvasH = FigureCanvas(self.figureH) self.canvasRelative = FigureCanvas(self.figureRelative) self.canvasResult = FigureCanvas(self.figureResult ) self.canvasProducts = FigureCanvas(self.figureProducts) # this is the Navigation widget # it takes the Canvas widget and a parent # self.toolbarX = NavigationToolbar(self.canvasX, self) def createWidgets(self): #Button Widgets self.buttonReset = QPushButton('Réinitialisation') self.buttonReset.clicked.connect(self.plotDefaults) self.buttonUpdate = QPushButton('Mettre à jour les graphiques') self.buttonUpdate.clicked.connect(self.plotUpdate) self.buttonEcho = QRadioButton('Mode echo') self.buttonEcho.setChecked(True) self.buttonEcho.clicked.connect(self.setModeEcho) self.buttonReverse = QRadioButton('Mode retourné') self.buttonReverse.clicked.connect(self.setModeReverse) self.sliderTimeLabel = QLabel("Selection du point t à évaluer") self.sliderTimeLabel.setAlignment(Qt.AlignCenter) self.sliderEchoLabel = QLabel("Nombre de points contribuant à l'évaluation du point t") self.sliderEchoLabel.setAlignment(Qt.AlignCenter) self.tminXLabel = QLabel("Valeur minimum de t pout x(t)") self.tminXLabel.setAlignment(Qt.AlignRight) self.tmaxXLabel = QLabel("Valeur maximum de t pour x(t)") self.tmaxXLabel.setAlignment(Qt.AlignRight) self.tminHLabel = QLabel("Valeur minimum de t pour h(t)") self.tminHLabel.setAlignment(Qt.AlignRight) self.tmaxHLabel = QLabel("Valeur maximum de t pour h(t)") self.tmaxHLabel.setAlignment(Qt.AlignRight) self.XFunctionLabel = QLabel("Fonction x(t)") self.XFunctionLabel.setAlignment(Qt.AlignRight) self.HFunctionLabel = QLabel("Fonction h(t)") self.HFunctionLabel.setAlignment(Qt.AlignRight) self.MessageLabel = QLabel("Les fonctions doivent être entrées avec" + " la syntaxe Python et la nomenclature Numpy. " + "Il y a 1000 points dans le vecteur \"t\".") self.MessageLabel.setAlignment(Qt.AlignCenter) self.sliderTime = QSlider(Qt.Horizontal) self.sliderTime.valueChanged.connect(self.moveTau) self.sliderTime.setTickPosition(QSlider.TicksBelow) self.sliderEcho = QSlider(Qt.Horizontal) self.sliderEcho.valueChanged.connect(self.changeNumberOfEchos) self.sliderEcho.setTickPosition(QSlider.TicksBelow) self.sliderEcho.setMinimum(1) self.sliderEcho.setMaximum(300) self.tminXInput = QLineEdit() self.tminXInput.setValidator(QDoubleValidator()) self.tminXInput.textChanged.connect(self.updateMinRangeX) self.tmaxXInput = QLineEdit() self.tmaxXInput.setValidator(QDoubleValidator()) self.tmaxXInput.textChanged.connect(self.updateMaxRangeX) self.tminHInput = QLineEdit() self.tminHInput.setValidator(QDoubleValidator()) self.tminHInput.textChanged.connect(self.updateMinRangeH) self.tmaxHInput = QLineEdit() self.tmaxHInput.setValidator(QDoubleValidator()) self.tmaxHInput.textChanged.connect(self.updateMaxRangeH) self.XFunctionInput = QLineEdit() self.XFunctionInput.returnPressed.connect(self.updateXFunction) self.HFunctionInput = QLineEdit() self.HFunctionInput.returnPressed.connect(self.updateHFunction) def createGridLayout(self): # set the layout self.horizontalGroupBox = QGroupBox("Grid") layout = QGridLayout() layout.setColumnStretch(0, 50) layout.setColumnStretch(2, 50) layout.setColumnStretch(4, 1000) layout.addWidget(self.canvasX, 0, 0, 1, 2) layout.addWidget(self.canvasH, 0, 2, 1, 2) layout.addWidget(self.canvasRelative, 1, 0, 1, 4) layout.addWidget(self.canvasProducts, 0, 4, 2, 1) layout.addWidget(self.canvasResult, 2, 4, 10, 1) layout.addWidget(self.sliderTimeLabel, 2, 0, 1, 4) layout.addWidget(self.sliderTime, 3, 0, 1, 4) layout.addWidget(self.sliderEchoLabel, 4, 0, 1, 4) layout.addWidget(self.sliderEcho, 5, 0, 1, 4) layout.addWidget(self.buttonReset, 6, 0) layout.addWidget(self.buttonUpdate, 6, 1) layout.addWidget(self.buttonEcho, 6, 2) layout.addWidget(self.buttonReverse, 6, 3) layout.addWidget(self.tminXLabel, 7,0) layout.addWidget(self.tmaxXLabel, 8,0) layout.addWidget(self.tminXInput, 7,1) layout.addWidget(self.tmaxXInput, 8,1) layout.addWidget(self.tminHLabel, 7,2) layout.addWidget(self.tmaxHLabel, 8,2) layout.addWidget(self.tminHInput, 7,3) layout.addWidget(self.tmaxHInput, 8,3) layout.addWidget(self.XFunctionInput, 9,1,1,3) layout.addWidget(self.HFunctionInput, 10,1,1,3) layout.addWidget(self.XFunctionLabel, 9,0,1,1) layout.addWidget(self.HFunctionLabel, 10,0, 1,1) layout.addWidget(self.MessageLabel, 11,0, 1, 4) self.setLayout(layout) def plotDefaults(self): self.convolution = Convolution() self.plotUpdate() self.updateSlider() self.tminXInput.setText('{}'.format(self.convolution.getMinRangeX())) self.tminHInput.setText('{}'.format(self.convolution.getMinRangeH())) self.tmaxXInput.setText('{}'.format(self.convolution.getMaxRangeX())) self.tmaxHInput.setText('{}'.format(self.convolution.getMaxRangeH())) self.XFunctionInput.setText('{}'.format(self.convolution.getXFunctionString())) self.HFunctionInput.setText('{}'.format(self.convolution.getHFunctionString())) def updateSlider(self): self.sliderTime.setMinimum(self.convolution.getMinRangeX()*self.sliderTimeFactor) self.sliderTime.setMaximum(self.convolution.getMaxRangeX()*self.sliderTimeFactor) #self.sliderTime.setTickInterval(self.convolution.getStep()) self.sliderTime.setSingleStep((self.convolution.getMaxRangeX()-self.convolution.getMinRangeX())/100) def plotUpdate(self): self.figureX.clear() ax = self.figureX.add_subplot(111) dataX = self.convolution.getXfunction() ax.plot(dataX[0], dataX[1]) ax.set_title("x(t)") self.canvasX.draw() self.figureH.clear() ax = self.figureH.add_subplot(111) dataH = self.convolution.getHfunction() ax.plot(dataH[0], dataH[1]) ax.set_title("h(t)") self.canvasH.draw() self.figureRelative.clear() ax = self.figureRelative.add_subplot(111) tau = self.convolution.getTau() ax.plot(dataX[0], dataX[1], color='blue') ax.axvline(x=tau, color='red') ax.plot((dataH[0]-dataH[0][0]+tau), dataH[1], color='green') ax.text(0.9, 0.9, 't = {}'.format(tau), transform=ax.transAxes, fontsize='large') ax.set_title("Positions relatives de x(t) et h(t)") self.canvasRelative.draw() tauindex = int(((tau-self.convolution.getMinRangeX())/self.convolution.getStep())) self.figureResult.clear() ax = self.figureResult.add_subplot(111) ax.set_title("Convolution x(t) et h(t)") data = self.convolution.getConvolution() ax.plot(data[0], data[1]) ax.axvline(x=tau, color='red') ax.scatter(tau, data[1][tauindex]) ax.text(0.8, 0.9, 'x(t) * h(t) = {0:5.4f}'.format(data[1][tauindex]), transform=ax.transAxes, fontsize='large') self.canvasResult.draw() if self.modeEcho == True: self.productPlotWithEchos() else: self.productPlotReverse() def productPlotWithEchos(self): self.figureProducts.clear() tau = self.convolution.getTau() dataX = self.convolution.getXfunction() dataH = self.convolution.getHfunction() ax = self.figureProducts.add_subplot(111) ax.axvline(x=tau, color='red') ax.plot(dataX[0], dataX[1], color='blue') ax.plot((dataH[0]-dataH[0][0]+tau), dataH[1], color='green') tauindex = int(((tau-self.convolution.getMinRangeX())/self.convolution.getStep())) ax.text(0.7, 0.95, r'$\Delta\tau=$ {0:5.4f}'.format(self.convolution.getEchoPoints()*self.convolution.getStep()), transform=ax.transAxes, fontsize='large') textincrement = 0 total=dataH[1][0]*dataX[1][tauindex]*self.convolution.getEchoPoints()*self.convolution.getStep() ax.scatter(tau, dataX[1][tauindex], marker='x') for i, echo in enumerate(self.convolution.createEchos()): try: intersection = (dataX[1][i*(self.convolution.getEchoPoints())]* dataH[1][self.convolution.getHindex(echo-self.convolution.getMinRangeX()+self.convolution.getMinRangeH())]) except IndexError: intersection = 0 if intersection>0: tOffset = dataH[0][0]-tau+echo-self.convolution.getMinRangeX() line, = ax.plot((dataH[0]-tOffset), dataX[1][i*(self.convolution.getEchoPoints())] * dataH[1], alpha = 0.5) ax.scatter(tau, intersection, color=line.get_color()) if textincrement < 16: ax.text(0.7, 0.9-textincrement*0.05, r'$x(t-\tau_{{{0}}})h(\tau_{{{0}}}) =$ {1:5.4f}'.format(textincrement+1, intersection), transform=ax.transAxes, fontsize='large', color=line.get_color()) textincrement+=1 total += intersection*self.convolution.getEchoPoints()*self.convolution.getStep() ax.text(0.95, 0.1, r"$\sum{{x(t-\tau_{{n}})\cdot h(\tau_{{n}})\cdot\Delta\tau}}=${0:5.2f}".format(total), transform=ax.transAxes, fontsize='x-large', ha='right') ax.set_title("Translation de h(t) en un point") minVert = npmin([dataX[1], dataH[1]]) maxVert = npmax([dataX[1], dataH[1]]) adjust = (maxVert-minVert)*0.1 plt.axis([dataX[0][0], dataX[0][-1], minVert-adjust, maxVert+adjust]) self.canvasProducts.draw() def productPlotReverse(self): self.figureProducts.clear() tau = self.convolution.getTau() dataX = self.convolution.getXfunction() dataH = self.convolution.getHfunction() ax = self.figureProducts.add_subplot(111) ax.axvline(x=tau, color='red') ax.plot(dataX[0], dataX[1], color='blue') ax.plot(-(dataH[0]-dataH[0][0])+tau, dataH[1], color='green') tauindex = int(((tau-self.convolution.getMinRangeX())/self.convolution.getStep())) ax.text(0.7, 0.95, r'$\Delta\tau=$ {0:5.4f}'.format(self.convolution.getEchoPoints()*self.convolution.getStep()), transform=ax.transAxes, fontsize='large') textincrement = 0 total=dataH[1][0]*dataX[1][tauindex]*self.convolution.getEchoPoints()*self.convolution.getStep() ax.scatter(tau, dataX[1][tauindex], marker='x') for i, echo in enumerate(self.convolution.createEchos()): try: intersection = (dataX[1][i*(self.convolution.getEchoPoints())]* dataH[1][self.convolution.getHindex(echo-self.convolution.getMinRangeX()+ self.convolution.getMinRangeH())]) except IndexError: intersection = 0 if intersection>0: xposition = tau-echo+self.convolution.getMinRangeX() line, = ax.plot([xposition, xposition], [0, intersection]) #Find color and apply to scatter and text ax.scatter(xposition, intersection, color=line.get_color()) if textincrement < 16: ax.text(0.7, 0.9-textincrement*0.05, r'$x(t-\tau_{{{0}}})h(\tau_{{{0}}}) =$ {1:5.4f}'.format(textincrement+1, intersection), transform=ax.transAxes, fontsize='large', color=line.get_color()) textincrement+=1 total += intersection*self.convolution.getEchoPoints()*self.convolution.getStep() ax.text(0.95, 0.1, r"$\sum{{x(\tau_{{n}})\cdot h(t-\tau_{{n}})\cdot\Delta\tau}}=${0:5.2f}".format(total), transform=ax.transAxes, fontsize='x-large', ha='right') ax.set_title("Translation de h(t) en un point") #SET Axes to fix X minVert = npmin([dataX[1], dataH[1]]) maxVert = npmax([dataX[1], dataH[1]]) adjust = (maxVert-minVert)*0.1 plt.axis([dataX[0][0], dataX[0][-1], minVert-adjust, maxVert+adjust]) self.canvasProducts.draw() def updateMinRangeX(self, minvalue): self.convolution.setMinRangeX(float(minvalue)) self.plotUpdate() self.updateSlider() def updateMaxRangeX(self, maxvalue): self.convolution.setMaxRangeX(float(maxvalue)) self.plotUpdate() self.updateSlider() def updateMinRangeH(self, minvalue): self.convolution.setMinRangeH(float(minvalue)) self.plotUpdate() self.updateSlider() def updateMaxRangeH(self, maxvalue): self.convolution.setMaxRangeH(float(maxvalue)) self.plotUpdate() self.updateSlider() def updateXFunction(self): self.convolution.setXFunction(self.XFunctionInput.text()) self.plotUpdate() def updateHFunction(self): self.convolution.setHFunction(self.HFunctionInput.text()) self.plotUpdate() def moveTau(self): tau = self.sliderTime.value()/float(self.sliderTimeFactor) self.convolution.setTau(tau) self.plotUpdate() def changeNumberOfEchos(self): self.convolution.setEchoRate(self.sliderEcho.value()) self.plotUpdate() def setModeEcho(self): self.modeEcho = True self.productPlotWithEchos() def setModeReverse(self): self.modeEcho = False self.productPlotReverse()
names = ['i-3-a', 'i-3-b', 'i-3-c'] char = 97 for name in names: path = '../input/convolution/' + name + '.jpg' img = cv2.imread(path) print(path) i = 0 for n in [3, 7, 15]: kernel = np.ones((n, n), dtype=np.float32) / (n * n) size = str(n) + 'x' + str(n) print(size) start_time = time.time() img_out_1 = conv.convolution_nd(img, kernel, conv_type=conv.CONV_ITERATIVE) print("--- classical algorithm: %s seconds ---" % (time.time() - start_time)) name = '../output/convolution/o-3-' + chr(char) + '-' + str( i) + '-' + size + 'ca.png' cv2.imwrite(name, img_out_1) i += 1 start_time = time.time() img_out_2 = conv.convolution_nd(img, kernel, conv_type=conv.CONV_KERNEL_SIZE) print("--- vectorized element-wise multiplication %s seconds ---" % (time.time() - start_time)) name = '../output/convolution/o-3-' + chr(char) + '-' + str(
def __init__(self,num_filt=64): Neural_Network.__init__(self) self.conv = Convolution(num_filt)
class CNN(Neural_Network) : def __init__(self,num_filt=64): Neural_Network.__init__(self) self.conv = Convolution(num_filt) def train(self,X=None,y=None,nodesNumLayer=[16],nodes_outputLayer=1,learning_rate=0.1,epochs=100,hidden_activation=None,output_activation = None,save=False): if X is None or y is None : print('No Dataset or labels given') exit() if hidden_activation is None or output_activation is None : print("Activation function not given") exit() self.nodesNumLayer=nodesNumLayer #list of number of nodes in each layer self.nodes_outputLayer=nodes_outputLayer self.lr = learning_rate self.init_weights_bias(self.conv.feed_through_layer(X[0,:]).flatten().shape[0]) self.hidden_activation = hidden_activation self.output_activation = output_activation cost_function=self.MSE for i in range(epochs) : cost_sum = 0 print("epoch",i) for j in range(X.shape[0]) : convoluted_op = self.conv.feed_through_layer(X[j,:]) cop_shape = convoluted_op.shape #print("cop_shape",cop_shape) convoluted_op = convoluted_op.flatten() y_pred = self.feedForward(convoluted_op,hidden_activation,output_activation) cost_sum += np.sum(cost_function(y_pred,y[j])) self.backProp(cost_function,y[j],y_pred,X[j,:],cop_shape) print("cost:",cost_sum) print() def backProp(self,cost_function,actual,predicted,inp,conv_layer_shape): errors = [] derivative_cost = scp.derivative(self.MSE,actual,dx=1e-6,args=(predicted,)) output_layer = self.layer_vals[-1] output_error = derivative_cost*np.vectorize(scp.derivative)(self.output_activation,output_layer,dx=1e-6) current_err = output_error.reshape(1,-1) i=1 while i<=(len(self.weights)) : errors.append(current_err) current_layer = self.layer_vals[-(i+1)] current_err = np.matmul(current_err,self.weights[-i].T)*np.vectorize(scp.derivative)(self.hidden_activation,current_layer,dx=1e-6) i+=1 self.conv.conv_backProp(current_err.reshape(conv_layer_shape[0],conv_layer_shape[1],conv_layer_shape[2]),inp) for i in range(len(self.weights)-1) : x,y = np.meshgrid(errors[i],np.vectorize(self.hidden_activation)(self.layer_vals[-(i+2)])) delta_w = x*y*self.lr self.weights[-(i+1)] += delta_w self.bias[-(i+1)] += (self.lr*errors[i].flatten()) x,y = np.meshgrid(errors[len(self.weights)-1],self.layer_vals[0]) delta_w=x*y*self.lr self.weights[0] += delta_w self.bias[0] += (self.lr*errors[len(self.weights)-1].flatten()) def test(self,X,y): count=0 for i in range(X.shape[0]) : convoluted_op = self.conv.feed_through_layer(X[i,:]) cop_shape = convoluted_op.shape #print("cop_shape",cop_shape) convoluted_op = convoluted_op.flatten() y_pred = self.feedForward(convoluted_op,self.hidden_activation,self.output_activation) if np.argmax(y_pred) == np.argmax(y[i]) : count+=1 return count/y.shape[0]
h3 = self.i(h3) h4 = self.i(h4) h3_square = h3 * h3 h4_square = h4 * h4 summed = numpy.add(h3_square, h4_square) img = numpy.sqrt(summed) img = self.f(summed) self.set(img) self.set(self.normalize(self.get())) def i(self, img): return img / 255 def f(self, img): return img * 255 if __name__ == "__main__": import sys first = Convolution(sys.argv[1]) second = Convolution(sys.argv[1]) first.apply_def('h3') second.apply_def('h4') i = ConvolutionSquare(sys.argv[1]) i.apply_multiplication(first, second) i.save_to_file("output.png")
from MLP import MLP from convolution import Convolution, Pooling, Model from mnist import loadData if __name__ == '__main__': trainX, trainY, testX, testY, valX, valY = loadData() model = Model() model.add_layer(Convolution(16, 1, 3, 1)) model.add_layer(Pooling(2, 2)) model.add_layer(MLP(784, 128, 10, activation='sigmoid')) model.feed_forward(trainX[0])
class Focal(): '''Filter Overlap Correction ALgorithm, simulates the foveal pit region of the human retina. Created by Basabdatta Sen Bhattacharya. See DOI: 10.1109/TNN.2010.2048339 ''' def __init__(self): '''Get the four layer's kernels, create the correlations and a convolution wrapper. :const MIN_IMG_WIDTH: Minimum image width for which to use NumPy/SciPy for convolution ''' self.kernels = DifferenceOfGaussians() self.correlations = Correlation(self.kernels.full_kernels) self.convolver = Convolution() self.MIN_IMG_WIDTH = 256 def apply(self, image, spikes_per_unit=0.3, overlapcorr=True): '''Wrapper function to convert an image into a FoCal representation :param image: The image to convert :param spikes_per_unit: How many spikes to return, specified in per-unit (i.e. multiply by 100 to get percentage) ''' spike_images = self.filter_image(image) focal_spikes = self.focal(spike_images, spikes_per_unit=spikes_per_unit, overlapcorr=overlapcorr) return focal_spikes def focal(self, spike_images, spikes_per_unit=0.3, overlapcorr=True): '''Filter Overlap Correction ALgorithm, simulates the foveal pit region of the human retina. Created by Basabdatta Sen Bhattacharya. See DOI: 10.1109/TNN.2010.2048339 spike_images => A list of the values generated by the convolution procedure, stored as four 2D arrays, each with the same size/shape of the original image. spikes_per_unit => Percentage of the total spikes to be processed, specified in a per unit [0, 1] range. returns: an ordered list of [spike index, sorting value, cell layer/type] tuples. ''' ordered_spikes = [] img_size = spike_images[0].size img_shape = spike_images[0].shape height, width = img_shape num_images = len(spike_images) #how many non-zero spikes are in the images max_cycles = 0 for i in range(num_images): max_cycles += numpy.sum(spike_images[i] != 0) total_spikes = max_cycles.copy() #reduce to desired number max_cycles = numpy.int(spikes_per_unit * max_cycles) #copy images from list to a large image to make it a single search space big_shape = (height * 2, width * 2) big_image = numpy.zeros(big_shape) big_coords = [(0, 0), (0, width), (height, 0), (height, width)] for cell_type in range(num_images): row, col = big_coords[cell_type] tmp_img = spike_images[cell_type].copy() tmp_img[numpy.where(tmp_img == 0)] = -numpy.inf big_image[row:row + height, col:col + width] = tmp_img # Main FoCal loop for count in range(max_cycles): # print out completion percentage percent = (count * 100.) / float(total_spikes - 1) sys.stdout.write("\rFocal %d%%" % (percent)) # Get maximum value's index, max_idx = numpy.argmax(big_image) # its coordinates max_coords = numpy.unravel_index(max_idx, big_shape) # and the value max_val = big_image[max_coords] if max_val == numpy.inf or max_val == -numpy.inf or max_val == numpy.nan: sys.stderr.write("\nWrong max value in FoCal!") break # translate coordinates from the big image's to a single image coordinates if max_coords[0] < height and max_coords[1] < width: single_coords = max_coords else: single_coords = self.global_to_single_coords( max_coords, img_shape) # calculate a local index, to store per ganglion cell layer info local_idx = single_coords[0] * width + single_coords[1] # calculate the type of cell from the index cell_type = self.cell_type_from_global_coords( max_coords, img_shape) # append max spike info to return list ordered_spikes.append([local_idx, max_val, cell_type]) if overlapcorr: # correct surrounding pixels for overlapping kernel influence for overlap_cell_type in range(len(spike_images)): # get equivalent coordinates for each layer overlap_idx = self.local_coords_to_global_idx( single_coords, overlap_cell_type, img_shape, big_shape) is_max_val_layer = overlap_cell_type == cell_type # c_i = c_i - c_{max}<K_i, K_{max}> self.adjust_with_correlation( big_image, self.correlations[cell_type][overlap_cell_type], overlap_idx, max_val, is_max_val_layer=is_max_val_layer) return ordered_spikes def filter_image(self, img, force_homebrew=False): '''Perform convolution with calculated kernels img => the image to convolve force_hombrew => if True: use my separated convolution code else: use SciPy sepfir2d ''' num_kernels = len(self.kernels.full_kernels) img_width, img_height = img.shape convolved_img = {} for cell_type in range(num_kernels): if img_width < self.MIN_IMG_WIDTH or img_height < self.MIN_IMG_WIDTH: force_homebrew = True else: force_homebrew = False c = self.convolver.dog_sep_convolution( img, self.kernels[cell_type], cell_type, originating_function="filter", force_homebrew=force_homebrew) convolved_img[cell_type] = c return convolved_img def adjust_with_correlation(self, img, correlation, max_idx, max_val, is_max_val_layer=True): '''Modify surrounding pixels by the correlation of kernels. Example: If max_val is in layer 1, we overlap all layers and then multiply surrounding pixels by the correlation between layer 1 and layerX (1,2,3, or 4). :param img: An image representing the spikes generated by the previous step or simulation of a ganglion cell layer :param max_idx: index of the pixel/neuron that has the maximum value from the previous step or simulation :param max_val: value of the max pixel/neuron :param is_max_val_layer: Required to mark max_idx as visited :returns: img with the proper adjustment ''' img_height, img_width = img.shape correlation_width = correlation.shape[0] half_correlation_width = int(correlation_width / 2) half_img_width = int(img_width / 2) half_img_height = int(img_height / 2) # Get max value's coordinates row, col = idx2coord(max_idx, img_width) row_idx = int(row / half_img_height) col_idx = int(col / half_img_width) # Calculate the zone to affect with the correlation up_lim = (row_idx) * half_img_height left_lim = (col_idx) * half_img_width down_lim = (row_idx + 1) * half_img_height right_lim = (col_idx + 1) * half_img_width max_img_row = numpy.min( [down_lim - 1, row + half_correlation_width + 1]) max_img_col = numpy.min( [right_lim - 1, col + half_correlation_width + 1]) min_img_row = numpy.max([up_lim, row - half_correlation_width]) min_img_col = numpy.max([left_lim, col - half_correlation_width]) max_img_row_diff = max_img_row - row max_img_col_diff = max_img_col - col min_img_row_diff = row - min_img_row min_img_col_diff = col - min_img_col min_knl_row = half_correlation_width - min_img_row_diff min_knl_col = half_correlation_width - min_img_col_diff max_knl_row = half_correlation_width + max_img_row_diff max_knl_col = half_correlation_width + max_img_col_diff # c_i = c_i - c_{max}<K_i, K_{max}> img[min_img_row:max_img_row, min_img_col:max_img_col] -= max_val * correlation[ min_knl_row:max_knl_row, min_knl_col:max_knl_col] # mark any weird pixels as -inf so they don't matter in the search inf_indices = numpy.where(img[min_img_row:max_img_row, min_img_col:max_img_col] == numpy.inf) img[inf_indices] = 0 img[inf_indices] -= numpy.inf nan_indices = numpy.where(img[min_img_row:max_img_row, min_img_col:max_img_col] == numpy.nan) img[nan_indices] = 0 img[nan_indices] -= numpy.inf # mark max value's coordinate to -inf to get it out of the search if is_max_val_layer: img[row, col] -= numpy.inf # No need to return, variables are passed as reference because we're doing = and -= ops def local_coords_to_global_idx(self, coords, cell_type, local_img_shape, global_img_shape): '''Utility to transform from local (width*height) coordinates to global (2*width, 2*height) coords. --------- Layers are represented in the global image as: [ 0 | 1 ] ------- [ 2 | 3 ] --------- ''' row_add = int(cell_type / 2) col_add = int(cell_type % 2) global_coords = (coords[0] + row_add * local_img_shape[0], coords[1] + col_add * local_img_shape[1]) global_idx = global_coords[0] * global_img_shape[1] + global_coords[1] return global_idx def global_to_single_coords(self, coords, single_shape): '''Utility to transform from global (2*width, 2*height) coordinates to local (width*height) coords . --------- Layers are represented in the global image as: [ 0 | 1 ] ------- [ 2 | 3 ] --------- ''' row_count = int(coords[0] / single_shape[0]) col_count = int(coords[1] / single_shape[1]) new_row = coords[0] - single_shape[0] * row_count new_col = coords[1] - single_shape[1] * col_count return (new_row, new_col) def cell_type_from_global_coords(self, coords, single_shape): '''Utility to compute which layer does a coordinate belong to''' row_type = int(coords[0] / single_shape[0]) col_type = int(coords[1] / single_shape[1]) cell_type = row_type * 2 + col_type return cell_type
class PoseCellNetwork: def __init__( self, shape, **kwargs ): self.shape = shape self.posecells = zeros(shape) #NOTE: might not need if gaussian_filter works self.kernel_3d = self.diff_gaussian( PC_E_DIM, PC_I_DIM, PC_E_SIGMA, PC_I_SIGMA, order=3 ) self.kernel_2d = self.diff_gaussian( PC_E_DIM, PC_I_DIM, PC_E_SIGMA, PC_I_SIGMA, order=2 ) self.kernel_1d = self.diff_gaussian( PC_E_DIM, PC_I_DIM, PC_E_SIGMA, PC_I_SIGMA, order=1 ) self.kernel_1d_sep = self.diff_gaussian_separable( PC_E_DIM, PC_I_DIM, PC_E_SIGMA, PC_I_SIGMA ) self.global_inhibition = PC_GLOBAL_INHIB self.pc_vtrans_scale = PC_CELL_X_SIZE self.pc_vrot_scale = 2.0*pi/shape[2]#PC_C_SIZE_TH #TODO: maybe change everything to float32 to make it go faster? #self.conv = Convolution( im=self.posecells, fil=self.kernel_1d, sep=True, type=float64 ) #self.conv = Convolution( im=self.posecells, fil=self.kernel_1d_sep, sep=True, type=float64 ) self.conv = Convolution( im=self.posecells, fil=self.kernel_3d, sep=False, type=float64 ) filter = self.diff_gaussian_offset_2d( PC_E_SIGMA, PC_I_SIGMA, shape=(7,7), origin=(0,0) ) #self.conv.new_filter( self.kernel_2d, dim=2 ) self.conv.new_filter( filter, dim=2 ) self.filter_dict_2d = self.build_diff_gaussian_set_2d( PC_E_SIGMA, PC_I_SIGMA, shape=(7,7), precision=1 ) self.filter_dict_2d_precision = 10 # multiple the decimal by this number to get the right key def build_diff_gaussian_set_2d( self, sigma_e, sigma_i, shape=(7,7), precision=1 ): """Builds a set of difference of gaussian kernels with origins within a unit square. These will be used as a look up table of approximate kernels to improve speed""" dict = {} # larger precision values denote greater precision. Must be integer to prevent floating point errors for x in xrange( -5 * precision, 5 * precision ): for y in xrange( -5 * precision, 5 * precision ): dict[ ( x, y ) ] = self.diff_gaussian_offset_2d( sigma_e, sigma_i, shape=shape, origin=( x / ( precision * 10 ), y / ( precision * 10 ) ) ) return dict # builds a 3D gaussian filter kernel with lengths of 'dim' def build_kernel( self, dim, sigma, order=3 ): if order==3: f = empty( ( dim, dim, dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): for y in xrange( dim ): for z in xrange( dim ): f[x,y,z] = 1.0 / (sigma*math.sqrt(2*pi)) * \ math.exp( (-(x-center)**2 - (y-center)**2 - (z-center)**2 ) / (2*sigma**2)) f /= abs(sum(f.ravel())) # normalize return f elif order==2: f = empty( ( dim, dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): for y in xrange( dim ): f[x,y] = 1.0 / (sigma*math.sqrt(2*pi)) * \ math.exp( (-(x-center)**2 - (y-center)**2 ) / (2*sigma**2)) f /= abs(sum(f.ravel())) # normalize return f elif order==1: f = empty( ( dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): f[x] = 1.0 / (sigma*math.sqrt(2*pi)) * \ math.exp( -(x-center)**2 / (2*sigma**2)) f /= abs(sum(f.ravel())) # normalize return f else: pass #TODO: put an error statement here # builds a 3D difference of gaussians filter kernel with lengths of 'dim' def diff_gaussian( self, dim_e, dim_i, sigma_e, sigma_i, order=3 ): dim = max(dim_e, dim_i) if order==3: f = empty( ( dim, dim, dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): for y in xrange( dim ): for z in xrange( dim ): f[x,y,z] = ( 1 if max(x,y,z) <= center + dim_e and min(x,y,z) >= center - dim_e else 0 ) * \ 1.0 / (sigma_e*math.sqrt(2*pi))**3 * \ math.exp( (-(x-center)**2 - (y-center)**2 - (z-center)**2 ) / (2*sigma_e**2)) - \ ( 1 if max(x,y,z) <= center + dim_i and min(x,y,z) >= center - dim_i else 0 ) * \ 1.0 / (sigma_i*math.sqrt(2*pi))**3 * \ math.exp( (-(x-center)**2 - (y-center)**2 - (z-center)**2 ) / (2*sigma_i**2)) f /= abs(sum(f.ravel())) # normalize return f elif order==2: f = empty( ( dim, dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): for y in xrange( dim ): f[x,y] = ( 1 if max(x,y) <= center + dim_e and min(x,y) >= center - dim_e else 0 ) * \ 1.0 / (sigma_e * sigma_e * 2 * pi) * \ math.exp( (-(x-center)**2 - (y-center)**2 ) / (2*sigma_e**2)) - \ ( 1 if max(x,y) <= center + dim_i and min(x,y) >= center - dim_i else 0 ) * \ 1.0 / (sigma_i * sigma_i * 2 * pi) * \ math.exp( (-(x-center)**2 - (y-center)**2 ) / (2*sigma_i**2)) f /= abs(sum(f.ravel())) # normalize return f elif order==1: f = empty( ( dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): f[x] = ( 1 if x <= center + dim_e and x >= center - dim_e else 0 ) * \ 1.0 / (sigma_e*math.sqrt(2*pi)) * \ math.exp( -(x-center)**2 / (2*sigma_e**2)) - \ ( 1 if x <= center + dim_i and x >= center - dim_i else 0 ) * \ 1.0 / (sigma_i*math.sqrt(2*pi)) * \ math.exp( -(x-center)**2 / (2*sigma_i**2)) f /= abs(sum(f.ravel())) # normalize return f else: pass #TODO: put an error statement here """ This one uses the Ratslam C++ gaussian formulas, which are not technically correct # builds a 3D difference of gaussians filter kernel with lengths of 'dim' def diff_gaussian( self, dim_e, dim_i, sigma_e, sigma_i, order=3 ): dim = max(dim_e, dim_i) if order==3: f = zeros( ( dim, dim, dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): for y in xrange( dim ): for z in xrange( dim ): f[x,y,z] = ( 1 if max(x,y,z) <= center + dim_e and min(x,y,z) >= center - dim_e else 0 ) * \ 1.0 / (sigma_e*math.sqrt(2*pi)) * \ math.exp( (-(x-center)**2 - (y-center)**2 - (z-center)**2 ) / (2*sigma_e**2)) - \ ( 1 if max(x,y,z) <= center + dim_i and min(x,y,z) >= center - dim_i else 0 ) * \ 1.0 / (sigma_i*math.sqrt(2*pi)) * \ math.exp( (-(x-center)**2 - (y-center)**2 - (z-center)**2 ) / (2*sigma_i**2)) f /= abs(sum(f.ravel())) # normalize return f elif order==2: f = zeros( ( dim, dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): for y in xrange( dim ): f[x,y] = ( 1 if max(x,y) <= center + dim_e and min(x,y) >= center - dim_e else 0 ) * \ 1.0 / (sigma_e*math.sqrt(2*pi)) * \ math.exp( (-(x-center)**2 - (y-center)**2 ) / (2*sigma_e**2)) - \ ( 1 if max(x,y) <= center + dim_i and min(x,y) >= center - dim_i else 0 ) * \ 1.0 / (sigma_i*math.sqrt(2*pi)) * \ math.exp( (-(x-center)**2 - (y-center)**2 ) / (2*sigma_i**2)) f /= abs(sum(f.ravel())) # normalize return f elif order==1: f = zeros( ( dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): f[x] = ( 1 if x <= center + dim_e and x >= center - dim_e else 0 ) * \ 1.0 / (sigma_e*math.sqrt(2*pi)) * \ math.exp( -(x-center)**2 / (2*sigma_e**2)) - \ ( 1 if x <= center + dim_i and x >= center - dim_i else 0 ) * \ 1.0 / (sigma_i*math.sqrt(2*pi)) * \ math.exp( -(x-center)**2 / (2*sigma_i**2)) f /= abs(sum(f.ravel())) # normalize return f else: pass #TODO: put an error statement here """ # FIXME: this doesn't actually work at all, because DoG filters are not separable # builds a 1D difference of gaussians filter kernel that can be used successively to create a 3D kernel def diff_gaussian_separable( self, dim_e, dim_i, sigma_e, sigma_i ): dim = max(dim_e, dim_i) f = empty( ( dim ) ) center = math.floor( dim / 2 ) for x in xrange( dim ): f[x] = ( 1 if x <= center + dim_e and x >= center - dim_e else 0 ) * \ 1.0 / (sigma_e*math.sqrt(2*pi)) * \ math.exp( -(x-center)**2 / (2*sigma_e**2)) - \ ( 1 if x <= center + dim_i and x >= center - dim_i else 0 ) * \ 1.0 / (sigma_i*math.sqrt(2*pi)) * \ math.exp( -(x-center)**2 / (2*sigma_i**2)) f /= abs(sum(f.ravel())) # normalize f = cbrt( f ) # Take the cubed root, so the filter applied 3 times will be normalized return f def diff_gaussian_offset_2d( self, sigma_e, sigma_i, shape=( 7, 7 ), origin=( 0, 0 ) ): """Builds a 2D difference of gaussian kernel centered at the origin given""" f = empty( shape ) x, y = meshgrid( arange( shape[0] ) - origin[0], arange( shape[1] ) - origin[1] ) center = ( math.floor( shape[0] / 2 ), math.floor( shape[1] / 2 ) ) f = 1.0 / ( 2* sigma_e**2 * pi ) * \ exp( (-( x - center[0])**2 - (y - center[1])**2 ) / (2*sigma_e**2)) - \ 1.0 / ( 2 * sigma_i**2 * pi ) * \ exp( (-( x - center[0])**2 - (y - center[1])**2 ) / (2*sigma_i**2)) f /= abs(sum(f.ravel())) # normalize #f = square( cbrt( f ) ) # The result of this filter and a 1D filter should be normalized f = cbrt( f ) # TEMP return f def diff_gaussian_offset_1d( self, sigma_e, sigma_i, size=7, origin=0 ): """Builds a 1D difference of gaussian kernel centered at the origin given""" f = empty( size ) x = arange( size ) - origin center = math.floor( size / 2 ) f = 1.0 / (sigma_e*math.sqrt(2*pi)) * \ exp( -square(x-center) / (2*sigma_e**2)) - \ 1.0 / (sigma_i*math.sqrt(2*pi)) * \ exp( -square(x-center) / (2*sigma_i**2)) f /= abs(sum(f.ravel())) # normalize f = cbrt( f ) # The result of this filter and a 2D filter should be normalized return f def filters_from_origins( self, origins, shape=( 7, 7 ) ): num = origins.shape[1] filters = empty( ( shape[0], shape[1], num ) ) for z in xrange(num): filters[:,:,z] = self.diff_gaussian_offset_2d( PC_E_SIGMA, PC_I_SIGMA, shape=shape, origin=origins[:,z] ) return filters def filters_from_origins_approx( self, origins, shape=( 7, 7 ) ): num = origins.shape[1] filters = empty( ( shape[0], shape[1], num ) ) prec = self.filter_dict_2d_precision for z in xrange(num): filters[:,:,z] = self.filter_dict_2d[ ( int( origins[:,z][0] * prec ), int( origins[:,z][0] * prec ) ) ] return filters def path_integration( self, vtrans, vrot ): vtrans /= self.pc_vtrans_scale vrot /= self.pc_vrot_scale #TODO ?? is this right? #TODO - this can be optimized better in the future mid = math.floor( self.shape[2] / 2 ) #""" dir_pc = arange( self.shape[2] ).reshape( (1, self.shape[2] ) ) origins_exact = concatenate( ( vtrans*cos( (dir_pc - mid)*self.pc_vrot_scale ), vtrans*sin( (dir_pc - mid)*self.pc_vrot_scale ) ), axis=0 ) origins = concatenate( ( around( vtrans*cos( (dir_pc - mid)*self.pc_vrot_scale ) ), around( vtrans*sin( (dir_pc - mid)*self.pc_vrot_scale ) ) ), axis=0 ) origins_diff = origins_exact - origins #filters = self.filters_from_origins( origins_diff ) # Use a lookup table to get the filter set quickly filters = self.filters_from_origins_approx( origins_diff ) self.posecells = self.conv.conv_im( self.posecells, axes=[0,1], radius=ceil( abs( vtrans ) ), origins=origins, filters=filters ) #""" """ for dir_pc in xrange( self.shape[2] ): # use a 2D gaussian filter across every theta (direction) layer, with the origin offset based on vtrans and vrot origin = ( vtrans*cos( (dir_pc - mid)*self.pc_vrot_scale ), vtrans*sin( (dir_pc - mid)*self.pc_vrot_scale ) ) #origin = ( vtrans*cos( (dir_pc)*self.pc_vrot_scale ), vtrans*sin( (dir_pc)*self.pc_vrot_scale ) ) #origin = (4,4) ####print origin #filter = self.diff_gaussian_offset_2d( PC_E_SIGMA, PC_I_SIGMA, shape=(7,7), origin=origin ) filter = self.diff_gaussian_offset_2d( PC_E_SIGMA, PC_I_SIGMA, shape=(12,12), origin=origin ) #filter = self.diff_gaussian_offset_2d( PC_E_SIGMA, PC_I_SIGMA, shape=(7,7), origin=(0,0) ) #self.conv.new_filter( filter, dim=2 ) #self.posecells = self.conv.conv_im( self.posecells, axes=[0,1] ) # Using origin shifted filter self.posecells[:,:,dir_pc] = \ ndimage.correlate( self.posecells[:,:,dir_pc], filter, mode='wrap' ) #self.posecells[:,:,dir_pc] = \ # ndimage.correlate( self.posecells[:,:,dir_pc], filter, mode='wrap', origin=origin ) #self.posecells[:,:,dir_pc] = \ # ndimage.correlate( self.posecells[:,:,dir_pc], self.kernel_2d, mode='wrap', origin=origin ) """ # Remove any negative values self.posecells[self.posecells < 0] = 0 # and then use a 1D gaussian across the theta layers #TODO - this can be optimized better in the future origin = math.floor(vrot+.5) #for x in xrange( self.shape[0] ): # for y in xrange( self.shape[1] ): # self.posecells[x,y,:] = ndimage.correlate( self.posecells[x,y,:], self.kernel_1d, mode='wrap', origin=origin ) filter = self.diff_gaussian_offset_1d( PC_E_SIGMA, PC_I_SIGMA, size=7, origin=origin ) self.conv.new_filter( filter, dim=1 ) self.posecells = self.conv.conv_im( self.posecells, axes=[2] ) #self.posecells = ndimage.correlate1d(input=self.posecells, weights=filter.tolist(), axis=2, mode='wrap') # Remove any negative values self.posecells[self.posecells < 0] = 0 # Not entirely sure what this should do yet ##??????????????????? def get_pc_max( self ): (x,y,th) = unravel_index(self.posecells.argmax(), self.posecells.shape) return (x,y,th) #pass # TODO - just copy it from ratslam-python for now def inject( self, energy, loc ): # loc is of the form [ x, y, z ] self.posecells[ loc ] += energy def update( self, v=(0.0, 0.0) ): vtrans = v[0] vrot = v[1] # 1. Internal X-Y Layer Update # 2. Inter-Layer Update #input and output the same might not work #self.posecells = ndimage.correlate(self.posecells, self.kernel_3d, mode='wrap') self.posecells = self.conv.conv_im( self.posecells ) # 3. Global Inhibition self.posecells[self.posecells < self.global_inhibition] = 0 self.posecells[self.posecells >= self.global_inhibition] -= self.global_inhibition # 4. Normalization total = sum(self.posecells.ravel()) if total != 0: self.posecells /= total # Path Integration self.path_integration( vtrans, vrot ) # get the maximum pose cell self.max_pc = self.get_pc_max() return self.max_pc
def __init__(self): self.kernels = DifferenceOfGaussians() self.correlations = Correlation(self.kernels.full_kernels) self.convolver = Convolution() self.MIN_IMG_WIDTH = 256