def initSequence(self, state, params): # ================================================================= # If necessary, create intial state if self._getIterCount() == 0: stepSize = params['stepSize'] # What is the range on the X and Y offsets of the center points? shape = params['spaceShape'] xMin = -1 * (shape[1] // 2) xMax = xMin + shape[1] - 1 xPositions = range(stepSize * xMin, stepSize * xMax + 1, stepSize) yMin = -1 * (shape[0] // 2) yMax = yMin + shape[0] - 1 yPositions = range(stepSize * yMin, stepSize * yMax + 1, stepSize) self._centerOffsets = list(cross(yPositions, xPositions)) self._numCenterOffsets = len(self._centerOffsets) # What is the range on the X and Y offsets of the spread points? shape = params['spreadShape'] xMin = -1 * (shape[1] // 2) xMax = xMin + shape[1] - 1 xPositions = range(stepSize * xMin, stepSize * xMax + 1, stepSize) yMin = -1 * (shape[0] // 2) yMax = yMin + shape[0] - 1 yPositions = range(stepSize * yMin, stepSize * yMax + 1, stepSize) self._spreadOffsets = list(cross(yPositions, xPositions)) # Put the (0,0) entry first self._spreadOffsets.remove((0,0)) self._spreadOffsets.insert(0, (0,0)) self._numSpreadOffsets = len(self._spreadOffsets) # Set start position self._catIdx = 0 self._centerPosIdx = 0 # Which center point self._spreadPosIdx = 0 # radial position around the center point self._numCats = self._getNumCategories() # ================================================================= # Present it self._presentNextPosn(state, params)
def initSequence(self, state, params): # ================================================================= # If necessary, create intial state if self._getIterCount() == 0: stepSize = params['stepSize'] # What is the range on the X and Y offsets of the center points? shape = params['spaceShape'] xMin = -1 * (shape[1] // 2) xMax = xMin + shape[1] - 1 xPositions = range(stepSize * xMin, stepSize * xMax + 1, stepSize) yMin = -1 * (shape[0] // 2) yMax = yMin + shape[0] - 1 yPositions = range(stepSize * yMin, stepSize * yMax + 1, stepSize) self._centerOffsets = list(cross(yPositions, xPositions)) self._numCenterOffsets = len(self._centerOffsets) # What is the range on the X and Y offsets of the spread points? shape = params['spreadShape'] xMin = -1 * (shape[1] // 2) xMax = xMin + shape[1] - 1 xPositions = range(stepSize * xMin, stepSize * xMax + 1, stepSize) yMin = -1 * (shape[0] // 2) yMax = yMin + shape[0] - 1 yPositions = range(stepSize * yMin, stepSize * yMax + 1, stepSize) self._spreadOffsets = list(cross(yPositions, xPositions)) # Put the (0,0) entry first self._spreadOffsets.remove((0, 0)) self._spreadOffsets.insert(0, (0, 0)) self._numSpreadOffsets = len(self._spreadOffsets) # Set start position self._catIdx = 0 self._centerPosIdx = 0 # Which center point self._spreadPosIdx = 0 # radial position around the center point self._numCats = self._getNumCategories() # ================================================================= # Present it self._presentNextPosn(state, params)
def __init__(self, spaceShape=(5,5), spreadShape=None, spreadRadius=None, stepSize=1, resetEveryPos=False, verbosity=0, *args, **kwargs): """ spaceShape: The (height, width) of the 2-D space to explore. This sets the number of center-points. spreadShape: The shape (height, width) of the area around each center-point to explore if you want to spread in a square area. If this is specified, then radius must be None. spreadRadius: The radius of the spread if you want to spread in a circular area. If this is specified, then spreadShape must be None. When set to R, this explorer will visit all positions where: int(round(sqrt(dx*dx + dy*dy))) <= radius stepSize: The step size. How big each step is, in pixels. This controls *both* the spacing of the center-points within the block and the points we explore around each center-point. When spreadRadius is used to define the spread shape, then it will only visit points within stepSize*spreadRadius of the center point and insure that no two points it visits within this area are closer than stepSize from each other, where distance is defined as: int(round(sqrt(dx*dx + dy*dy))) This euclidean distance is NOT used to determine where the center points are - they are always laid out in a grid with x spacing and y spacing of stepSize. resetEveryPos: If False (the default), output a reset only when we first visit a new center point. This is what is normally used for training. If True, then output a reset on every iteration. This is often used for flash inference testing. """ BaseExplorer.__init__(self, *args, **kwargs) # Parameter checking if type(stepSize) is not int or stepSize < 1: raise RuntimeError("'stepSize' should be a positive integer") if len(spaceShape) != 2 or spaceShape[0] < 1 or spaceShape[1] < 1: raise RuntimeError("'spaceShape' should be a 2-item tuple specifying the" "(height, width) of the overall space to explore.") if spreadShape is not None: if spreadRadius is not None: raise RuntimeError ("When spreadShape is used, spreadRadius must be set to None") if len(spreadShape) != 2 or spreadShape[0] < 1 or spreadShape[1] < 1: raise RuntimeError("'spreadShape' should be a 2-item tuple specifying the" "(height, width) of the of the area round each center point to" "explore.") if spreadRadius is None and spreadShape is None: raise RuntimeError ("Either spreadRadius or spreadShape must be defined") # Parameters self._spaceShape = spaceShape self._spreadShape = spreadShape self._spreadRadius = spreadRadius self._stepSize = stepSize self._verbosity = verbosity self._resetEveryPos = resetEveryPos # ===================================================================== # Init data structures # What is the range on the X and Y offsets of the center points? shape = self._spaceShape # If the shape is (1,1), special case of just 1 center point if shape[0] == 1 and shape[1] == 1: self._centerOffsets = [(0,0)] else: xMin = -1 * (shape[1] // 2) xMax = xMin + shape[1] - 1 xPositions = range(stepSize * xMin, stepSize * xMax + 1, stepSize) yMin = -1 * (shape[0] // 2) yMax = yMin + shape[0] - 1 yPositions = range(stepSize * yMin, stepSize * yMax + 1, stepSize) self._centerOffsets = list(cross(yPositions, xPositions)) self._numCenterOffsets = len(self._centerOffsets) # ---------------------------------------------------------------- # Figure out the spread points based on spreadShape: if self._spreadShape is not None: # What is the range on the X and Y offsets of the spread points? shape = self._spreadShape # If the shape is (1,1), special case of no spreading around each center # point if shape[0] == 1 and shape[1] == 1: self._spreadOffsets = [(0,0)] else: xMin = -1 * (shape[1] // 2) xMax = xMin + shape[1] - 1 xPositions = range(stepSize * xMin, stepSize * xMax + 1, stepSize) yMin = -1 * (shape[0] // 2) yMax = yMin + shape[0] - 1 yPositions = range(stepSize * yMin, stepSize * yMax + 1, stepSize) self._spreadOffsets = list(cross(yPositions, xPositions)) # Put the (0,0) entry first self._spreadOffsets.remove((0,0)) self._spreadOffsets.insert(0, (0,0)) # --------------------------------------------------------------------- # Figure out the spread points based on spreadRadius else: # Special case of spreadRadius = 0:, no spreading around each center point if spreadRadius == 0: self._spreadOffsets = [(0,0)] # Build up a list of all offsets within spreadRadius * stepSize else: self._spreadOffsets = [] for y in range(-spreadRadius*stepSize, spreadRadius*stepSize+1): for x in range(-spreadRadius*stepSize, spreadRadius*stepSize+1): distance = int(round(math.sqrt(x*x + y*y))) if distance > spreadRadius*stepSize: continue # Make sure it's not closer than stepSize to another point within # the spread if not (x==0 and y==0) and stepSize > 1: tooClose = False for (otherY, otherX) in self._spreadOffsets: dx = x - otherX dy = y - otherY distance = int(round(math.sqrt(dx*dx + dy*dy))) if distance < stepSize: tooClose = True break if tooClose: continue self._spreadOffsets.append((y,x)) # Put the (0,0) entry first self._spreadOffsets.remove((0,0)) self._spreadOffsets.insert(0, (0,0)) if self._verbosity >= 1: print "Visiting spread positions:", self._spreadOffsets self._numSpreadOffsets = len(self._spreadOffsets) # Set start position self._centerPosIdx = 0 # Which center point self._spreadPosIdx = 0 # radial position around the center point
def __init__(self, spaceShape=(5, 5), spreadShape=None, spreadRadius=None, stepSize=1, resetEveryPos=False, verbosity=0, *args, **kwargs): """ spaceShape: The (height, width) of the 2-D space to explore. This sets the number of center-points. spreadShape: The shape (height, width) of the area around each center-point to explore if you want to spread in a square area. If this is specified, then radius must be None. spreadRadius: The radius of the spread if you want to spread in a circular area. If this is specified, then spreadShape must be None. When set to R, this explorer will visit all positions where: int(round(sqrt(dx*dx + dy*dy))) <= radius stepSize: The step size. How big each step is, in pixels. This controls *both* the spacing of the center-points within the block and the points we explore around each center-point. When spreadRadius is used to define the spread shape, then it will only visit points within stepSize*spreadRadius of the center point and insure that no two points it visits within this area are closer than stepSize from each other, where distance is defined as: int(round(sqrt(dx*dx + dy*dy))) This euclidean distance is NOT used to determine where the center points are - they are always laid out in a grid with x spacing and y spacing of stepSize. resetEveryPos: If False (the default), output a reset only when we first visit a new center point. This is what is normally used for training. If True, then output a reset on every iteration. This is often used for flash inference testing. """ BaseExplorer.__init__(self, *args, **kwargs) # Parameter checking if type(stepSize) is not int or stepSize < 1: raise RuntimeError("'stepSize' should be a positive integer") if len(spaceShape) != 2 or spaceShape[0] < 1 or spaceShape[1] < 1: raise RuntimeError( "'spaceShape' should be a 2-item tuple specifying the" "(height, width) of the overall space to explore.") if spreadShape is not None: if spreadRadius is not None: raise RuntimeError( "When spreadShape is used, spreadRadius must be set to None" ) if len(spreadShape ) != 2 or spreadShape[0] < 1 or spreadShape[1] < 1: raise RuntimeError( "'spreadShape' should be a 2-item tuple specifying the" "(height, width) of the of the area round each center point to" "explore.") if spreadRadius is None and spreadShape is None: raise RuntimeError( "Either spreadRadius or spreadShape must be defined") # Parameters self._spaceShape = spaceShape self._spreadShape = spreadShape self._spreadRadius = spreadRadius self._stepSize = stepSize self._verbosity = verbosity self._resetEveryPos = resetEveryPos # ===================================================================== # Init data structures # What is the range on the X and Y offsets of the center points? shape = self._spaceShape # If the shape is (1,1), special case of just 1 center point if shape[0] == 1 and shape[1] == 1: self._centerOffsets = [(0, 0)] else: xMin = -1 * (shape[1] // 2) xMax = xMin + shape[1] - 1 xPositions = range(stepSize * xMin, stepSize * xMax + 1, stepSize) yMin = -1 * (shape[0] // 2) yMax = yMin + shape[0] - 1 yPositions = range(stepSize * yMin, stepSize * yMax + 1, stepSize) self._centerOffsets = list(cross(yPositions, xPositions)) self._numCenterOffsets = len(self._centerOffsets) # ---------------------------------------------------------------- # Figure out the spread points based on spreadShape: if self._spreadShape is not None: # What is the range on the X and Y offsets of the spread points? shape = self._spreadShape # If the shape is (1,1), special case of no spreading around each center # point if shape[0] == 1 and shape[1] == 1: self._spreadOffsets = [(0, 0)] else: xMin = -1 * (shape[1] // 2) xMax = xMin + shape[1] - 1 xPositions = range(stepSize * xMin, stepSize * xMax + 1, stepSize) yMin = -1 * (shape[0] // 2) yMax = yMin + shape[0] - 1 yPositions = range(stepSize * yMin, stepSize * yMax + 1, stepSize) self._spreadOffsets = list(cross(yPositions, xPositions)) # Put the (0,0) entry first self._spreadOffsets.remove((0, 0)) self._spreadOffsets.insert(0, (0, 0)) # --------------------------------------------------------------------- # Figure out the spread points based on spreadRadius else: # Special case of spreadRadius = 0:, no spreading around each center point if spreadRadius == 0: self._spreadOffsets = [(0, 0)] # Build up a list of all offsets within spreadRadius * stepSize else: self._spreadOffsets = [] for y in range(-spreadRadius * stepSize, spreadRadius * stepSize + 1): for x in range(-spreadRadius * stepSize, spreadRadius * stepSize + 1): distance = int(round(math.sqrt(x * x + y * y))) if distance > spreadRadius * stepSize: continue # Make sure it's not closer than stepSize to another point within # the spread if not (x == 0 and y == 0) and stepSize > 1: tooClose = False for (otherY, otherX) in self._spreadOffsets: dx = x - otherX dy = y - otherY distance = int( round(math.sqrt(dx * dx + dy * dy))) if distance < stepSize: tooClose = True break if tooClose: continue self._spreadOffsets.append((y, x)) # Put the (0,0) entry first self._spreadOffsets.remove((0, 0)) self._spreadOffsets.insert(0, (0, 0)) if self._verbosity >= 1: print "Visiting spread positions:", self._spreadOffsets self._numSpreadOffsets = len(self._spreadOffsets) # Set start position self._centerPosIdx = 0 # Which center point self._spreadPosIdx = 0 # radial position around the center point
class InwardSweep(BaseExplorer): """ This explorer performs deterministic sweeps toward the center of the image. The starting point of each sweep is a point along the edge of a block of radius N pixels; the ending point of each sweep is the center of the image. Based on simple geometry, there will always be a total of 8 * N sweeps per image. """ # Pre-computed table _inwardNeighbors = tuple( [delta for delta in cross([-1, 0, 1], [-1, 0, 1])]) def __init__(self, radius=4, numRepetitions=1, *args, **kwargs): """ @param radius: the distance from the center, in pixels, at which the sweeps start; @param numRepetitions: number of times to present each inward sweep. """ BaseExplorer.__init__(self, *args, **kwargs) # Parameter checking if type(radius) is not int or radius < 1: raise RuntimeError("'radius' should be a positive integer") if type(numRepetitions) is not int or numRepetitions < 1: raise RuntimeError("'numRepetitions' should be a positive integer") # Parameters self._radius = radius self._numRepetitions = numRepetitions # Internal state self._itersDone = 0 def _computeNextPosn(self, iteration=None): """ Helper method that deterministically computes the next inward sweep position. """ radius = self._radius if iteration is None: iteration = self._itersDone # Take into account repetitions iterCount = iteration // self._numRepetitions # numRadials are all the positions on the boundary # Calculation 1) (2*radius+1)**2 - (2*radius-1)**2 # Calculation 2) (2*radius+1)*4 - 4 # numRadials, both ways is 8*radius # And each radial is radius + 1 iterations numRadialsPerCat = 8 * radius numItersPerCat = numRadialsPerCat * (radius + 1) catIndex = iterCount // numItersPerCat catIterCount = iterCount % numItersPerCat radialIndex = catIterCount // (radius + 1) # Determine quadrants: 0 (top), 1 (right), 2 (bottom), 3 (left) quadrantIndex = radialIndex // (2 * radius) radialPosn = catIterCount % (radius + 1) quadrantPosn = (radialIndex % (2 * radius)) # Determine start position of this radial posnX, posnY = { 0: (quadrantPosn - radius, -radius), 1: (radius, quadrantPosn - radius), 2: (radius - quadrantPosn, radius), 3: (-radius, radius - quadrantPosn), }[quadrantIndex] spokeIdx = iteration % (radius + 1) for spokeIter in range(spokeIdx): # Compute neighbor with minimal euclidean distance to center neighbors = [(posnX + dx, posnY + dy) for dx, dy in self._inwardNeighbors] posnX, posnY = min(neighbors, key=lambda a: a[0]**2 + a[1]**2) self.position['reset'] = (spokeIdx == 0) self.position['image'] = catIndex self.position['offset'] = [posnX, posnY] # Debugging output to console if False: print "[%04d] %d: (%d, %d) %s" % ( \ self._itersDone, self.position['image'], self.position['offset'][0], self.position['offset'][1], "RESET" if self.position['reset'] else "") # Update iteration count self._itersDone = iteration + 1 def seek(self, iteration=None, position=None): """ Seek to the specified position or iteration. iteration -- Target iteration number (or None). position -- Target position (or None). ImageSensor checks validity of inputs, checks that one (but not both) of position and iteration are None, and checks that if position is not None, at least one of its values is not None. Updates value of position. """ self._computeNextPosn(iteration=iteration) def first(self): """ Set up the position. BaseExplorer picks image 0, offset (0,0), etc., but explorers that wish to set a different first position should extend this method. Such explorers may wish to call BaseExplorer.first(center=False), which initializes the position tuple but does not call centerImage() (which could cause unnecessary filtering to occur). """ BaseExplorer.first(self, center=False) self._computeNextPosn(iteration=0) def next(self, seeking=False): """ Go to the next position (next iteration). seeking -- Boolean that indicates whether the explorer is calling next() from seek(). If True, the explorer should avoid unnecessary computation that would not affect the seek command. The last call to next() from seek() will be with seeking=False. """ BaseExplorer.next(self) self._computeNextPosn()
class InwardPictureExplorer(PictureSensor.PictureExplorer): """ A PictureSensor explorer that deterministically generates inward sweeps starting at each point along a square perimeter of side length 1+2*radialLength, with each such sweep taking the most expeditious route to the center position. """ # Pre-computed table _inwardNeighbors = tuple( [delta for delta in cross([-1, 0, 1], [-1, 0, 1])]) @classmethod def queryRelevantParams(klass): """ Returns a sequence of parameter names that are relevant to the operation of the explorer. May be extended or overridden by sub-classes as appropriate. """ return ('radialLength', ) def initSequence(self, state, params): """ Initiate the next sequence at the appropriate point along the block perimeter. """ radialLength = params['radialLength'] # Take into account repetitions iterCount = self._getIterCount() // self._getNumRepetitions() # numRadials are all the positions on the boundary # Calculation 1) (2*radialLength+1)**2 - (2*radialLength-1)**2 # Calculation 2) (2*randialLength+1)*4 - 4 # numRadials, both ways is 8*radialLength # And each radial is radialLength + 1 iterations numRadialsPerCat = 8 * radialLength numItersPerCat = numRadialsPerCat * (radialLength + 1) numCats = self._getNumCategories() catIndex = iterCount // numItersPerCat catIterCount = iterCount % numItersPerCat radialIndex = catIterCount // (radialLength + 1) # Determine quadrants: 0 (top), 1 (right), 2 (bottom), 3 (left) quadrantIndex = radialIndex // (2 * radialLength) radialPosn = catIterCount % (radialLength + 1) quadrantPosn = radialIndex % (2 * radialLength) # Determine start position of this radial posnX, posnY = { 0: (quadrantPosn - radialLength, -radialLength), 1: (radialLength, quadrantPosn - radialLength), 2: (radialLength - quadrantPosn, radialLength), 3: (-radialLength, radialLength - quadrantPosn), }[quadrantIndex] # Override default state state['posnX'] = posnX state['posnY'] = posnY state['velocityX'] = 0 state['velocityY'] = 0 state['angularPosn'] = 0 state['angularVelocity'] = 0 state['catIndex'] = catIndex def updateSequence(self, state, params): """ Move to the neighbor position closest to the center """ posnX = state['posnX'] posnY = state['posnY'] # Compute neighbor with minimal euclidean distance to center neighbors = [(posnX + dx, posnY + dy) for dx, dy in self._inwardNeighbors] state['posnX'], state['posnY'] = min(neighbors, key=lambda a: a[0]**2 + a[1]**2)