Esempio n. 1
0
 def generate_texture(self):
     text = np.zeros((self.size[0], self.size[1]))
     if self.texture_type == BGTextureType.Plain:
         for i in xrange(self.size[0]):
             for j in xrange(self.size[1]):
                 text[i][j] = 0
     elif self.texture_type == BGTextureType.Perlin:
         perlin = PerlinNoiseGenerator(self.texture.shape[0],
                 self.texture.shape[1])
         text = perlin.get_background_noise()
     elif self.texture_type == BGTextureType.HilbertCurve:
         hcurves = HilbertCurves(self.size[0], self.size[1],
                 self.hilbert_level)
         self.texture = hcurves.gen_hilbert_curve()
     if self.corruptor is not None:
         text = self.corruptor(text)
     return text
Esempio n. 2
0
class SpritePlacer(object):
    """
	Defines a dataset composed of a sequence of images of the
	specified dimensions (``gen.w`` by ``gen.h`` pixels). Each image
	contains a certain number of binary sprites or "sprites" scattered
	about. The ``gen`` parameter must be an iterator or an iterable
	such that:

	   iter(gen) -> iterator of
		   ((((x1, y1), sprite1), ((x2, y2), sprite2), ...), target)

	Where ``spriten`` is a :class:`Sprite` object, ``0 <= xn < w``, ``0 <=
	yn < h``. ``SpritePlacer`` will generate a scene where the top left
	pixel of the nth sprite is positioned at ``(xn, yn)``
	coordinates. ``target`` is a tuple, list or vector of numbers
	representing the class(es) or target(s) associated to the
	scene. Additionally, ``gen`` must have the following attributes:

	- ``gen.w`` must be the width of the scene in pixels.

	- ``gen.h`` must be the height of the scene in pixels.

	- ``gen.nout`` must be the length of the target
	- ``gen.nclasses`` must be either ``None`` or a tuple, list or

	  vectors of integers or ``None``, an integer at the nth position
	  meaning that the nth target is a class identifier from 0 included
	  to ``nclasses[n]`` excluded, ``None`` meaning that the nth target

	- ``gen.out_format`` must be 'array'

	- ``gen.out_dtype`` must be the dtype of the targets generated by
	  iterating over ``iter(gen)`` (typically 'uint8', if the
	  target(s) is(are) classes).

	The ``spriteland.gen`` module contains generators corresponding to
	this interface.

	If ``collision_check`` is set to ``True``, no sprites' masks will
	overlap. This is done by rejection sampling: gen will be iterated
	over until it produces sprites at positions that do not lead to
	overlaps. For small images with large sprites or a lot of sprites, the
	rejection rate might be high. SpritePlacer provides a method,
	``self.rejection_rate()`` to have an estimate of the rejection
	rate for the samples generated up to the point the method is
	called. A warning will be issued during the generation of the very
	first sample if it takes more than 1000 tries, to help identify
	problems with placement.

	Another issue to be aware of with ``collision_check`` and
	rejection sampling is that the distribution of scenes might be
	biased as a result. For instance, if some sprites are larger than
	some others, scenes with them might be rejected at a greater
	frequency. Assymetrical sprites might be found more often at one side
	or corner than at the others, and so on. These biases might make
	learning easier. For the time being SpritePlacer does not give
	feedback to the generator that might help it doing a counter-bias
	to guarantee certain important statistics. It is recommended to at
	least verify the distribution of classes.

	The dataset can be iterated over and yields (input, target) where
	input and target are vectors.
	"""
    def __init__(self, gen, collision_check=False, enable_perlin=False):
        self.gen = gen
        self.collision_check = collision_check
        self.use_patch_centers = gen.use_patch_centers

        self.enable_perlin = enable_perlin

        self.w = gen.w
        self.h = gen.h
        self.nin = gen.w * gen.h
        assert gen.out_format == 'array'
        self.out_format = gen.out_format
        self.out_dtype = gen.out_dtype
        self.nout = gen.nout
        self.nclasses = gen.nclasses

        self.n_successes = 0
        self.n_rejections = 0

        if enable_perlin:
            self.perlin_gen = PerlinNoiseGenerator(self.w, self.h, 32)

    def rejection_rate(self):
        """
	       	If collision_check is True, returns the rejection rate of the
		generator, which is the number of scenes that were rejected
		because of overlaps divided by the total number of scenes
		considered.
		"""
        total = self.n_successes + self.n_rejections
        if total == 0:
            return None
        else:
            return float(self.n_rejections) / total

    def __iter__(self):
        return copy.copy(self)

    def next(self):
        nrows_patches = self.gen.nrows_patches
        ncols_patches = self.gen.ncols_patches
        nelems = nrows_patches * ncols_patches
        gen = self.gen
        if self.collision_check:
            collider = numpy.zeros((self.h, self.w))

    #while True:
        if self.enable_perlin:
            data = self.perlin_gen.get_background_noise()
        else:
            data = numpy.zeros((self.h, self.w))

        targets = numpy.zeros((self.nout, ), dtype=self.out_dtype)

        if self.use_patch_centers:
            object_presences = numpy.zeros(nelems)
            object_presences.fill(-1)

        if not self.collision_check:
            description, target = gen.next()
            for (x, y), sprite in description:
                if self.use_patch_centers:
                    #Center the object in the patch

                    ystart = y - (sprite.h / 2)
                    yend = y + (sprite.h / 2)

                    xstart = x - (sprite.w / 2)
                    xend = x + (sprite.w / 2)

                    if sprite.h % 2 == 1:
                        ystart = y - (sprite.h / 2) - 1
                        yend = y + (sprite.h / 2)

                    if sprite.w % 2 == 1:
                        xstart = x - (sprite.w / 2) - 1
                        xend = x + (sprite.w / 2)

                    data[ystart:yend, xstart:xend] = sprite.textured_patch
                    idx = 0

                    for center in self.gen.patch_centers:
                        if numpy.array_equal(center, [x, y]):
                            break
                        idx += 1
                    object_presences[idx] = self.gen.spritenames.index(
                        sprite.name)
                else:
                    data[y:y + sprite.h,
                         x:x + sprite.w] = sprite.textured_patch

            targets[:] = target
            self.n_successes += 1

        else:
            ntrials = 0
            while True:
                if self.n_successes == 0 and ntrials and ntrials % 1000 == 0:
                    print >> sys.stderr, "WARNING: Rejected %i candidates, could not yet fit a single scene together. You might want to generate larger images." % ntrials
                ntrials += 1
                description, target = gen.next()
                collider.fill(0)
                for (x, y), sprite in description:
                    a, b = y - sprite.marginh, y + sprite.h + sprite.marginh
                    c, d = x - sprite.marginw, x + sprite.w + sprite.marginw

                    if a < 0 or b >= self.h or c < 0 or d >= self.w:
                        ba, bb = (a < 0) * -a, sprite.mh - (b >= self.h) * (
                            b - self.h + 1)
                        bc, bd = (c < 0) * -c, sprite.mw - (d >= self.w) * (
                            d - self.w + 1)

                        a, b = max(0, a), min(b, self.h - 1)
                        c, d = max(0, c), min(d, self.w - 1)

                        collider[a:b, c:d] += sprite.mask[ba:bb, bc:bd]
                    else:
                        collider[a:b, c:d] += sprite.mask

                if numpy.any(collider > 255) or numpy.any(
                        collider == 2) or numpy.any(collider == 3):
                    self.n_rejections += 1
                    continue
                else:
                    for (x, y), sprite in description:
                        if self.use_patch_centers:
                            # the x,y is the
                            # upper left corner of
                            # the object.

                            ystart = y
                            yend = y + (sprite.h)

                            xstart = x
                            xend = x + (sprite.w)

                            #Center the object in the patch
                            if self.gen.center_objects:
                                ystart = y - \
                                int(math.ceil(sprite.h / 2))
                                yend = y + \
                                int(math.ceil(sprite.h / 2))

                                xstart = x - \
                                int(math.ceil(sprite.w / 2))
                                xend = x + \
                                int(math.ceil(sprite.w / 2))

                            data[ystart:yend,
                                 xstart:xend] = sprite.textured_patch

                            idx = 0

                            for center in self.gen.patch_centers:
                                if numpy.array_equal(center, [x, y]):
                                    break
                                idx += 1
                            object_presences[idx] = self.gen.spritenames.index(
                                sprite.name)
                        else:
                            data[y:y + sprite.h,
                                 x:x + sprite.w] = sprite.textured_patch

                    targets[:] = target
                    self.n_successes += 1
                    break

        if self.use_patch_centers:
            return data.reshape(self.nin), targets, object_presences
        else:
            return data.reshape(self.nin), targets
Esempio n. 3
0
class SpritePlacer(object):
	"""
	Defines a dataset composed of a sequence of images of the
	specified dimensions (``gen.w`` by ``gen.h`` pixels). Each image
	contains a certain number of binary sprites or "sprites" scattered
	about. The ``gen`` parameter must be an iterator or an iterable
	such that:

	   iter(gen) -> iterator of
		   ((((x1, y1), sprite1), ((x2, y2), sprite2), ...), target)

	Where ``spriten`` is a :class:`Sprite` object, ``0 <= xn < w``, ``0 <=
	yn < h``. ``SpritePlacer`` will generate a scene where the top left
	pixel of the nth sprite is positioned at ``(xn, yn)``
	coordinates. ``target`` is a tuple, list or vector of numbers
	representing the class(es) or target(s) associated to the
	scene. Additionally, ``gen`` must have the following attributes:

	- ``gen.w`` must be the width of the scene in pixels.

	- ``gen.h`` must be the height of the scene in pixels.

	- ``gen.nout`` must be the length of the target
	- ``gen.nclasses`` must be either ``None`` or a tuple, list or

	  vectors of integers or ``None``, an integer at the nth position
	  meaning that the nth target is a class identifier from 0 included
	  to ``nclasses[n]`` excluded, ``None`` meaning that the nth target

	- ``gen.out_format`` must be 'array'

	- ``gen.out_dtype`` must be the dtype of the targets generated by
	  iterating over ``iter(gen)`` (typically 'uint8', if the
	  target(s) is(are) classes).

	The ``spriteland.gen`` module contains generators corresponding to
	this interface.

	If ``collision_check`` is set to ``True``, no sprites' masks will
	overlap. This is done by rejection sampling: gen will be iterated
	over until it produces sprites at positions that do not lead to
	overlaps. For small images with large sprites or a lot of sprites, the
	rejection rate might be high. SpritePlacer provides a method,
	``self.rejection_rate()`` to have an estimate of the rejection
	rate for the samples generated up to the point the method is
	called. A warning will be issued during the generation of the very
	first sample if it takes more than 1000 tries, to help identify
	problems with placement.

	Another issue to be aware of with ``collision_check`` and
	rejection sampling is that the distribution of scenes might be
	biased as a result. For instance, if some sprites are larger than
	some others, scenes with them might be rejected at a greater
	frequency. Assymetrical sprites might be found more often at one side
	or corner than at the others, and so on. These biases might make
	learning easier. For the time being SpritePlacer does not give
	feedback to the generator that might help it doing a counter-bias
	to guarantee certain important statistics. It is recommended to at
	least verify the distribution of classes.

	The dataset can be iterated over and yields (input, target) where
	input and target are vectors.
	"""

	def __init__(self, gen, collision_check = False, enable_perlin = False):
		self.gen = gen
		self.collision_check = collision_check
                self.use_patch_centers = gen.use_patch_centers

		self.enable_perlin = enable_perlin

		self.w = gen.w
		self.h = gen.h
		self.nin = gen.w * gen.h
		assert gen.out_format == 'array'
		self.out_format = gen.out_format
		self.out_dtype = gen.out_dtype
		self.nout = gen.nout
		self.nclasses = gen.nclasses

		self.n_successes = 0
		self.n_rejections = 0

		if enable_perlin:
			self.perlin_gen = PerlinNoiseGenerator(self.w, self.h, 32)

	def rejection_rate(self):
		"""
	       	If collision_check is True, returns the rejection rate of the
		generator, which is the number of scenes that were rejected
		because of overlaps divided by the total number of scenes
		considered.
		"""
		total = self.n_successes + self.n_rejections
		if total == 0:
			return None
		else:
			return float(self.n_rejections) / total

	def __iter__(self):
                nrows_patches = self.gen.nrows_patches
                ncols_patches = self.gen.ncols_patches
                nelems = nrows_patches * ncols_patches
		gen = iter(self.gen)
		if self.collision_check:
			collider = numpy.zeros((self.h, self.w))
		while True:
			if self.enable_perlin:
				data = self.perlin_gen.get_background_noise()
			else:
				data = numpy.zeros((self.h, self.w))
			targets = numpy.zeros((self.nout,), dtype = self.out_dtype)
                        if self.use_patch_centers:
                            object_presences = numpy.zeros(nelems)
                            object_presences.fill(-1)

			if not self.collision_check:
				description, target = gen.next()
				for (x, y), sprite in description:
                                    if self.use_patch_centers:
                                        #Center the object in the patch

                                        ystart = y - (sprite.h / 2)
                                        yend = y + (sprite.h / 2)

                                        xstart = x - (sprite.w / 2)
                                        xend = x + (sprite.w / 2)

                                        if sprite.h % 2 == 1:
                                            ystart = y - (sprite.h / 2) - 1
                                            yend = y + (sprite.h / 2)

                                        if sprite.w % 2 == 1:
                                            xstart = x - (sprite.w / 2) - 1
                                            xend = x + (sprite.w / 2)

                                        data[ystart: yend, xstart: xend] = sprite.textured_patch
                                        idx = 0

                                        for center in self.gen.patch_centers:
                                            if numpy.array_equal(center, [x, y]):
                                                break
                                            idx +=1
                                        object_presences[idx] = self.gen.spritenames.index(sprite.name)
                                    else:
					data[y:y + sprite.h, x:x + sprite.w] = sprite.textured_patch

				targets[:] = target
				self.n_successes += 1

			else:
				ntrials = 0
				while True:
					if self.n_successes == 0 and ntrials and ntrials % 1000 == 0:
						print >> sys.stderr, "WARNING: Rejected %i candidates, could not yet fit a single scene together. You might want to generate larger images." % ntrials
					ntrials += 1
					description, target = gen.next()
					collider.fill(0)

					for (x, y), sprite in description:
						a, b = y - sprite.marginh, y + sprite.h + sprite.marginh
						c, d = x - sprite.marginw, x + sprite.w + sprite.marginw

						if a < 0 or b >= self.h or c < 0 or d >= self.w:
							ba, bb = (a < 0)*-a, sprite.mh - (b >= self.h) * (b - self.h + 1)
							bc, bd = (c < 0)*-c, sprite.mw - (d >= self.w) * (d - self.w + 1)

							a, b = max(0, a), min(b, self.h - 1)
							c, d = max(0, c), min(d, self.w - 1)

							collider[a:b, c:d] += sprite.mask[ba:bb, bc:bd]
						else:
							collider[a:b, c:d] += sprite.mask

					if numpy.any(collider > 255) or numpy.any(collider == 2) or numpy.any(collider == 3):
						self.n_rejections += 1
						continue
					else:
						for (x, y), sprite in description:
                                                    if self.use_patch_centers:
                                                        # the x,y is the
                                                        # upper left corner of
                                                        # the object.

                                                        ystart = y
                                                        yend = y + (sprite.h)

                                                        xstart = x
                                                        xend = x + (sprite.w)

                                                        #Center the object in the patch
                                                        if self.gen.center_objects:
                                                            ystart = y - \
                                                            int(math.ceil(sprite.h / 2))
                                                            yend = y + \
                                                            int(math.ceil(sprite.h / 2))

                                                            xstart = x - \
                                                            int(math.ceil(sprite.w / 2))
                                                            xend = x + \
                                                            int(math.ceil(sprite.w / 2))

                                                        data[ystart: yend, xstart: xend] = sprite.textured_patch

                                                        idx = 0

                                                        for center in self.gen.patch_centers:
                                                            if numpy.array_equal(center, [x, y]):
                                                                break
                                                            idx +=1
                                                        object_presences[idx] = self.gen.spritenames.index(sprite.name)
                                                    else:
							data[y: y + sprite.h, x: x + sprite.w] = sprite.textured_patch

						targets[:] = target
						self.n_successes += 1
						break

                        if self.use_patch_centers:
                            yield data.reshape(self.nin), targets, object_presences
                        else:
                            yield data.reshape(self.nin), targets