def __init__(self, replacement=True, start=0, equalizeCategories=False, *args, **kwargs): """ Args: replacement: Whether the same image can be picked multiple times. start: Number of random choices to skip at the beginning, useful when seeding the random number generator. """ BaseExplorer.__init__(self, *args, **kwargs) if type(replacement) not in (bool, int): raise RuntimeError("'replacement' should be a boolean") if type(start) is not int: raise RuntimeError("'start' should be an integer") self.replacement = replacement self.start = start self.equalizeCategories = equalizeCategories self.imagesByCat = None if not self.replacement: self.history = []
def __init__(self, sweepDirections=['left', 'right', 'up', 'down'], shiftDuringSweep=1, sweepOffObject=False, *args, **kwargs): """ Args: sweepDirections: Directions for sweeping. Must be a list containing one or more of 'left', 'right', 'up', and 'down' for horizontal and vertical sweeps, or 'leftup', 'leftdown', 'rightup', and 'rightdown' for diagonal sweeps (or 'upleft, 'downleft', 'upright', and 'downright'). Can also be the string 'all', for all eight directions. shiftDuringSweep: Number of pixels to jump with each step (during a sweep). sweepOffObject: Whether the sensor can only include a part of the object, as specified by the bounding box. If False, it will only move to positions that include as much of the object as possible. """ BaseExplorer.__init__(self, *args, **kwargs) if sweepDirections == 'all': sweepDirections = ['left', 'right', 'up', 'down', 'leftdown', 'leftup', 'rightdown', 'rightup'] else: for direction in sweepDirections: if direction not in ('left', 'right', 'up', 'down', 'leftup', 'upleft', 'leftdown', 'downleft', 'rightup', 'upright', 'rightdown', 'downright'): raise RuntimeError('Unknown sweep direction: %s' % direction) if type(shiftDuringSweep) is not int: raise RuntimeError("'shiftDuringSweep' should be an integer") if type(sweepOffObject) not in (bool, int): raise RuntimeError("'sweepOffObject' should be a boolean") self.sweepDirections = sweepDirections self.shiftDuringSweep = shiftDuringSweep self.sweepOffObject = sweepOffObject
def __init__(self, sweepDirections=["right", "down"], shiftDuringSweep=1, shiftBetweenSweeps=1, sweepOffObject=False, order=None, *args, **kwargs): """ Args: sweepDirections: Directions for sweeping (a list containing one or more of 'left', 'right', 'up', and 'down'). shiftDuringSweep: Number of pixels to jump with each step (during a sweep). shiftBetweenSweeps: Number of pixels to jump in between sweeps (for example, when moving down a line after sweeping across). sweepOffObject: Whether the sensor can only include a part of the object, as specified by the bounding box. If False, it will only move to positions that include as much of the object as possible. If True, it will sweep until all of the object moves off the sensor. If set to a floating point number between 0 and 1, then it will sweep until that fraction of the object moves off the sensor. order: Order in which to iterate (outer to inner). Default progresses through switching images, filters, and sweeping, where switching images is the outer loop and sweeping is the inner loop. Should be a list containing 'image', 'sweep', and 0, 1, ... numFilters-1. """ BaseExplorer.__init__(self, *args, **kwargs) for direction in sweepDirections: if direction not in ('left', 'right', 'up', 'down'): raise RuntimeError("Unknown sweep direction: '%s'" % direction) if type(shiftDuringSweep) is not int: raise RuntimeError("'shiftDuringSweep' must be an integer") if type(shiftBetweenSweeps) is not int: raise RuntimeError("'shiftBetweenSweeps' must be an integer") if float(sweepOffObject) < 0 or float(sweepOffObject) > 1.0: raise RuntimeError("'sweepOffObject' should be a boolean, or floating point" " number between 0 and 1") if order is not None: if 'image' not in order or 'sweep' not in order: raise RuntimeError("'order' must contain both 'image' and 'sweep'") if len([x for x in order if type(x) == str]) > 2: raise RuntimeError("'order' must contain no other strings besides " "'image' and 'sweep'") self.customOrder = True else: self.customOrder = False self.sweepDirections = sweepDirections self.shiftDuringSweep = shiftDuringSweep self.shiftBetweenSweeps = shiftBetweenSweeps self.sweepOffObject = sweepOffObject self.order = order
def next(self, seeking=False): """Go to the next position (next iteration). Args: 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) # If filters were changed, order may be invalid if self.order is None or \ len([x for x in self.order if type(x) == int]) != self.numFilters: # If user did not set a custom order, just create new one automatically if not self.customOrder: self.order = ["image"] self.order.extend(range(self.numFilters)) self.order += ["sweep"] # Otherwise, user needs to recreate the explorer with a new order else: raise RuntimeError( "'order' is invalid. Must recreate explorer with " "valid order after changing filters.") if self.position['reset'] and self.blankWithReset: # Last iteration was a blank, so don't increment the position self.position['reset'] = False else: self.position['reset'] = False for x in reversed(self.order): if x == 'image': # Iterate the image self.position['image'] += 1 if self.position['image'] == self.numImages: self.position['image'] = 0 self.position['reset'] = True else: break elif x == 'sweep': # Iterate the sweep position nextImage = self._nextSweepPosition() if not nextImage: break else: # Iterate the filter with index x self.position['filters'][x] += 1 if self.position['filters'][x] == self.numFilterOutputs[x]: self.position['filters'][x] = 0 self.position['reset'] = True else: break if nextImage: self._firstSweepPosition()
def next(self, seeking=False): """Go to the next position (next iteration). Args: 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) # If filters were changed, order may be invalid if self.order is None or \ len([x for x in self.order if type(x) == int]) != self.numFilters: # If user did not set a custom order, just create new one automatically if not self.customOrder: self.order = ["image"] self.order.extend(range(self.numFilters)) self.order += ["sweep"] # Otherwise, user needs to recreate the explorer with a new order else: raise RuntimeError("'order' is invalid. Must recreate explorer with " "valid order after changing filters.") if self.position['reset'] and self.blankWithReset: # Last iteration was a blank, so don't increment the position self.position['reset'] = False else: self.position['reset'] = False for x in reversed(self.order): if x == 'image': # Iterate the image self.position['image'] += 1 if self.position['image'] == self.numImages: self.position['image'] = 0 self.position['reset'] = True else: break elif x == 'sweep': # Iterate the sweep position nextImage = self._nextSweepPosition() if not nextImage: break else: # Iterate the filter with index x self.position['filters'][x] += 1 if self.position['filters'][x] == self.numFilterOutputs[x]: self.position['filters'][x] = 0 self.position['reset'] = True else: break if nextImage: self._firstSweepPosition()
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) self.directionIndex = 0 if self.numImages: self._firstSweepPosition()
def seek(self, iteration=None, position=None): """Seek to the specified position or iteration. Args: 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. """ # Zero out the history when seeking to iteration 0. This so we can replicate # how random explorers behave in the vision framework and NVT. if iteration is not None and iteration == 0: if not self.replacement: self.history = [] BaseExplorer.seek(self, iteration=iteration, position=position)
def next(self, seeking=False): """Go to the next position (next iteration). Args: 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) if self.position['reset'] and self.blankWithReset: # Last iteration was a blank, so don't increment the position self.position['reset'] = False else: self.position['reset'] = False self._nextSweepPosition() # Begin a new sweep if necessary if self.position['reset']: self.first()
def first(self, seeking=False): """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). Args: seeking: Passed from seek() through next() to avoid loading images unnecessarily when seeking """ BaseExplorer.first(self, center=False) if not self.numImages: return if not self.replacement \ and len(self.history) == self.getNumIterations(None): # All images have been visited self.history = [] if self.equalizeCategories: # Breakdown the images by category if self.imagesByCat is None: categoryIndex = [] for k in range(self.numImages): categoryIndex += [self.getImageInfo(k)['categoryIndex']] categories = list(set(categoryIndex)) numCats = len(categories) catPopulation = {} imagesByCat = {} for catIndex in categories: #catPopulation[catIndex] = len([c for c in categoryIndex if c == catIndex]) imagesByCat[catIndex] = [k for k, c in enumerate(categoryIndex) if c == catIndex] catPopulation[catIndex] = len(imagesByCat[catIndex]) minNumSamples = min([pop for (cat, pop) in catPopulation.items()]) totalNumSamples = minNumSamples * numCats # Store self.imagesByCat = imagesByCat self.categories = categories self.numCategories = numCats self.nextCatIndex = 0 # Pick random image from next category thisCat = self.imagesByCat[self.nextCatIndex] #randomImageIndex = random.randint(0, len(thisCat)) self.position['image'] = self.random.choice(thisCat) self.position['filters'] = self.pickRandomFilters(self.random) self.nextCatIndex = (self.nextCatIndex + 1) % self.numCategories else: # Pick a random image and set of filters while self.start >= 0: finished = False while not finished: # Pick a position randomly self.position['image'] = self.pickRandomImage(self.random) self.position['filters'] = self.pickRandomFilters(self.random) # Pick again if not replacing and this position has been visited if self.replacement or (self.position['image'], self.position['filters']) not in self.history: finished = True if not self.replacement: # Remember this position self.history.append( (self.position['image'], self.position['filters'][:])) self.start -= 1 self.start = 0 if not seeking: self.centerImage()
def first(self, seeking=False): """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). Args: seeking: Passed from seek() through next() to avoid loading images unnecessarily when seeking """ BaseExplorer.first(self, center=False) if not self.numImages: return if not self.replacement \ and len(self.history) == self.getNumIterations(None): # All images have been visited self.history = [] if self.equalizeCategories: # Breakdown the images by category if self.imagesByCat is None: categoryIndex = [] for k in range(self.numImages): categoryIndex += [self.getImageInfo(k)['categoryIndex']] categories = list(set(categoryIndex)) numCats = len(categories) catPopulation = {} imagesByCat = {} for catIndex in categories: #catPopulation[catIndex] = len([c for c in categoryIndex if c == catIndex]) imagesByCat[catIndex] = [ k for k, c in enumerate(categoryIndex) if c == catIndex ] catPopulation[catIndex] = len(imagesByCat[catIndex]) minNumSamples = min( [pop for (cat, pop) in catPopulation.items()]) totalNumSamples = minNumSamples * numCats # Store self.imagesByCat = imagesByCat self.categories = categories self.numCategories = numCats self.nextCatIndex = 0 # Pick random image from next category thisCat = self.imagesByCat[self.nextCatIndex] #randomImageIndex = random.randint(0, len(thisCat)) self.position['image'] = self.random.choice(thisCat) self.position['filters'] = self.pickRandomFilters(self.random) self.nextCatIndex = (self.nextCatIndex + 1) % self.numCategories else: # Pick a random image and set of filters while self.start >= 0: finished = False while not finished: # Pick a position randomly self.position['image'] = self.pickRandomImage(self.random) self.position['filters'] = self.pickRandomFilters( self.random) # Pick again if not replacing and this position has been visited if self.replacement or ( self.position['image'], self.position['filters']) not in self.history: finished = True if not self.replacement: # Remember this position self.history.append( (self.position['image'], self.position['filters'][:])) self.start -= 1 self.start = 0 if not seeking: self.centerImage()
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) if not self.numImages: return # Pick a random direction and filtered image self.direction = self.random.choice(self.sweepDirections) self.position['image'] = self.random.randint(0, self.numImages - 1) for i in range(self.numFilters): self.position['filters'][i] = self.random.randint(0, self.numFilterOutputs[i] - 1) filteredImages = self.getFilteredImages() # Pick a random starting position on the appropriate edge of the image sbbox = self._getSweepBoundingBox(filteredImages[0]) if self.direction == 'left': self.position['offset'][0] = sbbox[2] - 1 self.position['offset'][1] = self.random.randint(sbbox[1], sbbox[3] - 1) elif self.direction == 'right': self.position['offset'][0] = sbbox[0] self.position['offset'][1] = self.random.randint(sbbox[1], sbbox[3] - 1) elif self.direction == 'up': self.position['offset'][0] = self.random.randint(sbbox[0], sbbox[2] - 1) self.position['offset'][1] = sbbox[3] - 1 elif self.direction == 'down': self.position['offset'][0] = self.random.randint(sbbox[0], sbbox[2] - 1) self.position['offset'][1] = sbbox[1] elif self.direction in ('leftup', 'upleft'): if self.random.randint(0, 1): self.position['offset'][0] = \ self.random.randint(int(sbbox[0] + (sbbox[2] - sbbox[0]) / 2), sbbox[2] - 1) self.position['offset'][1] = sbbox[3] - 1 else: self.position['offset'][0] = sbbox[2] - 1 self.position['offset'][1] = \ self.random.randint(int(sbbox[1] + (sbbox[3] - sbbox[1]) / 2), sbbox[3] - 1) elif self.direction in ('leftdown', 'downleft'): if self.random.randint(0, 1): self.position['offset'][0] = \ self.random.randint(int(sbbox[0] + (sbbox[2] - sbbox[0]) / 2), sbbox[2] - 1) self.position['offset'][1] = sbbox[1] else: self.position['offset'][0] = sbbox[2] - 1 self.position['offset'][1] = \ self.random.randint(sbbox[1], int(sbbox[3] - 1 - (sbbox[3] - sbbox[1]) / 2)) elif self.direction in ('rightup', 'upright'): if self.random.randint(0, 1): self.position['offset'][0] = \ self.random.randint(sbbox[0], int(sbbox[2] - 1 - (sbbox[2] - sbbox[0]) / 2)) self.position['offset'][1] = sbbox[3] - 1 else: self.position['offset'][0] = sbbox[0] self.position['offset'][1] = \ self.random.randint(int(sbbox[1] + (sbbox[3] - sbbox[1]) / 2), sbbox[3] - 1) elif self.direction in ('rightdown', 'downright'): if self.random.randint(0, 1): self.position['offset'][0] = \ self.random.randint(sbbox[0], int(sbbox[2] - 1 - (sbbox[2] - sbbox[0]) / 2)) self.position['offset'][1] = sbbox[1] else: self.position['offset'][0] = sbbox[0] self.position['offset'][1] = \ self.random.randint(sbbox[1], int(sbbox[3] - 1 - (sbbox[3] - sbbox[1]) / 2)) # Increment the position by a random amount in the range # [0, shiftDuringSweep) if self.shiftDuringSweep > 1: prevShiftDuringSweep = self.shiftDuringSweep self.shiftDuringSweep = self.random.randint(0, self.shiftDuringSweep) self._nextSweepPosition() self.shiftDuringSweep = prevShiftDuringSweep if self.position['reset']: self.first() self.position['reset'] = True
def __init__(self, sweepDirections=["right", "down"], shiftDuringSweep=1, shiftBetweenSweeps=1, sweepOffObject=False, order=None, *args, **kwargs): """ Args: sweepDirections: Directions for sweeping (a list containing one or more of 'left', 'right', 'up', and 'down'). shiftDuringSweep: Number of pixels to jump with each step (during a sweep). shiftBetweenSweeps: Number of pixels to jump in between sweeps (for example, when moving down a line after sweeping across). sweepOffObject: Whether the sensor can only include a part of the object, as specified by the bounding box. If False, it will only move to positions that include as much of the object as possible. If True, it will sweep until all of the object moves off the sensor. If set to a floating point number between 0 and 1, then it will sweep until that fraction of the object moves off the sensor. order: Order in which to iterate (outer to inner). Default progresses through switching images, filters, and sweeping, where switching images is the outer loop and sweeping is the inner loop. Should be a list containing 'image', 'sweep', and 0, 1, ... numFilters-1. """ BaseExplorer.__init__(self, *args, **kwargs) for direction in sweepDirections: if direction not in ('left', 'right', 'up', 'down'): raise RuntimeError("Unknown sweep direction: '%s'" % direction) if type(shiftDuringSweep) is not int: raise RuntimeError("'shiftDuringSweep' must be an integer") if type(shiftBetweenSweeps) is not int: raise RuntimeError("'shiftBetweenSweeps' must be an integer") if float(sweepOffObject) < 0 or float(sweepOffObject) > 1.0: raise RuntimeError( "'sweepOffObject' should be a boolean, or floating point" " number between 0 and 1") if order is not None: if 'image' not in order or 'sweep' not in order: raise RuntimeError( "'order' must contain both 'image' and 'sweep'") if len([x for x in order if type(x) == str]) > 2: raise RuntimeError( "'order' must contain no other strings besides " "'image' and 'sweep'") self.customOrder = True else: self.customOrder = False self.sweepDirections = sweepDirections self.shiftDuringSweep = shiftDuringSweep self.shiftBetweenSweeps = shiftBetweenSweeps self.sweepOffObject = sweepOffObject self.order = order