def __init__(self, imageSize=default_image_size, timeNow=0.0): # * Initialize members, parameters self.context = Context.getInstance() self.logger = logging.getLogger(__name__) self.logger.debug("Creating simplified Retina") # to distinguish from other Retina versions self.imageSize = imageSize self.imageCenter = (self.imageSize[1] / 2, self.imageSize[0] / 2) self.timeNow = timeNow self.bounds = np.float32([[0.0, 0.0, 2.0], [self.imageSize[0] - 1, self.imageSize[1] - 1, 4.0]]) self.center = (self.bounds[0] + self.bounds[1]) / 2 self.logger.debug("Retina center: {}, image size: {}".format(self.center, self.imageSize)) self.bipolarBlurSize = (5, 5) # size of blurring kernel used when computing Bipolar cell response self.ganglionCenterSurroundKernel = np.float32( [ [ -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, 7, 7, 7, -1, -1 ], [ -1, -1, 7, 9, 7, -1, -1 ], [ -1, -1, 7, 7, 7, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1 ] ]) self.ganglionCenterSurroundKernel /= np.sum(self.ganglionCenterSurroundKernel) # normalize #self.logger.info("Ganglion center-surround kernel:\n{}".format(self.ganglionCenterSurroundKernel)) # [debug] self.ganglionKernelLevels = 4 self.ganglionKernels = [None] * self.ganglionKernelLevels self.ganglionKernels[0] = self.ganglionCenterSurroundKernel for i in xrange(1, self.ganglionKernelLevels): self.ganglionKernels[i] = cv2.resize(self.ganglionKernels[i - 1], dsize=None, fx=2, fy=2) self.ganglionKernels[i] /= np.sum(self.ganglionKernels[i]) # normalize #self.logger.info("Ganglion center-surround kernel sizes ({} levels): {}".format(self.ganglionKernelLevels, ", ".join("{}".format(k.shape) for k in self.ganglionKernels))) # [debug] # * Image and related members self.imageCenter = (self.imageSize[1] / 2, self.imageSize[0] / 2) self.imageShapeC3 = (self.imageSize[1], self.imageSize[0], 3) # numpy shape for 3 channel images self.imageShapeC1 = (self.imageSize[1], self.imageSize[0]) # numpy shape for single channel images # NOTE Image shapes (h, w, 1) and (h, w) are not compatible unless we use keepdims=True for numpy operations self.imageTypeInt = np.uint8 # numpy dtype for integer-valued images self.imageTypeFloat = np.float32 # numpy dtype for real-valued images self.images = OrderedDict() # ** RGB and HSV images self.images['BGR'] = np.zeros(self.imageShapeC3, dtype=self.imageTypeInt) self.images['HSV'] = np.zeros(self.imageShapeC3, dtype=self.imageTypeInt) self.images['H'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeInt) self.images['S'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeInt) self.images['V'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeInt) # ** Freq/hue-dependent response images for rods and different cone types self.imageRod = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesCone = dict() # NOTE dict keys must match names of Cone.cone_types self.imagesCone['S'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesCone['M'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesCone['L'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) # ** Bipolar and Ganglion cell response images # TODO Add more Ganglion cell types with different receptive field properties (color-opponent cells) # 'RG' +Red -Green # 'GR' +Green -Red # 'RB' +Red -Blue # 'BR' +Blue -Red # 'BY' +Blue -Yellow # 'YB' +Yellow -Blue # 'WK' +White -Black (currently 'ON') # 'KW' +Black -White (currently 'OFF') # NOTE: R = L cones, G = M cones, B = S cones self.imagesBipolar = dict() self.imagesBipolar['ON'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesBipolar['OFF'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesGanglion = dict() self.imagesGanglion['ON'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesGanglion['OFF'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) # TODO Verify why image shapes (h, w, 1) and (h, w) are not compatible (use keepdims=True for numpy operations) self.imagesGanglion['RG'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesGanglion['GR'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesGanglion['RB'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesGanglion['BR'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesGanglion['BY'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesGanglion['YB'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) # ** Combined response (salience) image self.imageSalience = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) # ** Spatial attention map with a central (covert) spotlight (currently unused; TODO move to VisualCortex? also, use np.ogrid?) self.imageAttention = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) cv2.circle(self.imageAttention, (self.imageSize[1] / 2, self.imageSize[0] / 2), self.imageSize[0] / 3, 1.0, cv.CV_FILLED) self.imageAttention = cv2.blur(self.imageAttention, (self.imageSize[0] / 4, self.imageSize[0] / 4)) # coarse blur # ** Output image(s) if self.context.options.gui: self.imageOut = np.zeros(self.imageShapeC3, dtype=self.imageTypeInt)
def __init__(self, imageSize=default_image_size, timeNow=0.0): # * Initialize members, parameters self.context = Context.getInstance() self.logger = logging.getLogger(__name__) self.imageSize = imageSize self.timeNow = timeNow self.bounds = np.float32([[0.0, 0.0, 2.0], [self.imageSize[0] - 1, self.imageSize[1] - 1, 4.0]]) self.center = (self.bounds[0] + self.bounds[1]) / 2 self.logger.debug("Retina center: {}, image size: {}".format(self.center, self.imageSize)) self.rodDistribution = SymmetricLogNormal(mu=5.0, sigma=0.5, center=self.center) self.rodPlotColor = 'darkmagenta' self.coneDistribution = MultivariateNormal(mu=self.center, cov=(np.float32([1000.0, 1000.0, 1.0]) * np.identity(3, dtype=np.float32))) # TODO Create cone populations of different types with their respective spatial distributions (e.g. blue cones are mostly spread out) self.conePlotColor = 'darkgreen' self.conePlotColorsByType = [hsv_to_rgb(np.float32([[[coneType.hueResponse.mu / 180.0, 1.0, 1.0]]]))[0, 0] for coneType in Cone.cone_types] self.bipolarCellDistribution = MultivariateNormal(mu=self.center + np.float32([0.0, 0.0, 10.0]), cov=(np.float32([16000.0, 16000.0, 1.0]) * np.identity(3, dtype=np.float32))) self.bipolarCellPlotColor = 'orange' # * Image and related members self.imageCenter = (self.imageSize[1] / 2, self.imageSize[0] / 2) self.imageShapeC3 = (self.imageSize[1], self.imageSize[0], 3) # numpy shape for 3 channel images self.imageShapeC1 = (self.imageSize[1], self.imageSize[0]) # numpy shape for single channel images # NOTE Image shapes (h, w, 1) and (h, w) are not compatible unless we use keepdims=True for numpy operations self.imageTypeInt = np.uint8 # numpy dtype for integer-valued images self.imageTypeFloat = np.float32 # numpy dtype for real-valued images self.images = OrderedDict() # ** RGB and HSV images self.images['BGR'] = np.zeros(self.imageShapeC3, dtype=self.imageTypeInt) self.images['HSV'] = np.zeros(self.imageShapeC3, dtype=self.imageTypeInt) self.images['H'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeInt) self.images['S'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeInt) self.images['V'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeInt) # ** Freq/hue-dependent response images for rods and different cone types self.imageRod = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesCone = dict() # NOTE dict keys must match names of Cone.cone_types self.imagesCone['S'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesCone['M'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) self.imagesCone['L'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeFloat) # ** Output image(s) self.imageOut = None if self.context.options.gui: self.imageOut = np.zeros(self.imageShapeC3, dtype=self.imageTypeInt) self.imagesBipolar = dict() self.imagesBipolar['ON'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeInt) self.imagesBipolar['OFF'] = np.zeros(self.imageShapeC1, dtype=self.imageTypeInt) # * Create neuron populations # ** Photoreceptors self.rods = Population(numNeurons=self.num_rods, timeNow=self.timeNow, neuronTypes=[Rod], bounds=self.bounds, distribution=self.rodDistribution, retina=self) self.cones = Population(numNeurons=self.num_cones, timeNow=self.timeNow, neuronTypes=[Cone], bounds=self.bounds, distribution=self.coneDistribution, retina=self) self.coneTypeNames = [coneType.name for coneType in Cone.cone_types] # mainly for plotting # ** Bipolar cells self.bipolarCells = Population(numNeurons=self.num_bipolar_cells, timeNow=self.timeNow, neuronTypes=[BipolarCell], bounds=self.bounds, distribution=self.bipolarCellDistribution, retina=self) # * Connect neuron populations growthConeDirection = self.bipolarCells.distribution.mu - self.cones.distribution.mu # NOTE only using cone distribution center growthConeDirection /= np.linalg.norm(growthConeDirection, ord=2) # need a unit vector self.cones.connectWith(self.bipolarCells, maxConnectionsPerNeuron=10, growthCone=GrowthCone(growthConeDirection, spreadFactor=1)) self.rods.connectWith(self.bipolarCells, maxConnectionsPerNeuron=25, growthCone=GrowthCone(growthConeDirection, spreadFactor=1))