def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    mode = image.mode;
    originalSize = image.size;
    sizes = [(int(round(image.size[0]*s)), int(round(image.size[1]*s)))
      for s in self.scales]

    resizedImages = []
    for size in sizes:
      if size < image.size:
        resizedImage = image.resize(size,Image.ANTIALIAS)
      else:
        resizedImage = image.resize(size,Image.BICUBIC)
      x = (originalSize[0] - size[0])/2
      y = (originalSize[1] - size[1])/2
      newImage = Image.new(mode,originalSize,self.background)
      newImage.paste(resizedImage,(x,y))
      resizedImages.append(newImage)

    if not self.simultaneous:
      return resizedImages
    else:
      return [resizedImages]
Пример #2
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
        BaseFilter.process(self, image)
        s = min(image.size)
        sizeRange = [0, s]

        imageArray = numpy.array(image.split()[0].getdata())
        newImage = Image.new("LA", image.size)
        newImage.putdata([uint(p) for p in imageArray])
        newImage.putalpha(image.split()[1])
        for i in xrange(int(self.difficulty * self.maxLines)):
            # Generate random line
            start = (random.randint(sizeRange[0], sizeRange[1]),
                     random.randint(sizeRange[0], sizeRange[1]))
            end = (random.randint(sizeRange[0], sizeRange[1]),
                   random.randint(sizeRange[0], sizeRange[1]))

            # Generate random color
            color = random.randint(0, 255)

            # Add the line to the image
            draw = ImageDraw.Draw(newImage)
            draw.line((start, end), fill=color)

        return newImage
Пример #3
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    # ---------------------------------------------------------------------------
    # Create the mask around the source image
    mask = image.split()[-1]
    if image.mode[-1] != 'A' or isSimpleBBox(mask):
      mask = createMask(image, threshold=self._threshold, fillHoles=True,
                        backgroundColor=self.background, blurRadius=self._blurRadius,
                        maskScale=self._maskScale)


    # ---------------------------------------------------------------------------
    # Process each value
    newImages = []
    for value in self._values:
      if value is None:
        value = self.background

      bg = ImageChops.constant(image, value)
      newImage = Image.composite(image.split()[0], bg, mask)
      newImage.putalpha(image.split()[-1])
      newImages.append(newImage)

    if len(newImages) == 1:
      return newImages[0]
    else:
      return newImages
Пример #4
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    s = min(image.size)
    sizeRange = [int(0.1 * s), int(0.4 * s)]

    newArray = numpy.array(image.split()[0].getdata())
    newArray.resize(image.size[1],image.size[0])
    for j in xrange(self.numRectangles):
      # Generate random rectange
      size = (self.random.randint(sizeRange[0], sizeRange[1]),
        self.random.randint(sizeRange[0], sizeRange[1]))
      loc = [self.random.randint(0,image.size[1]),
             self.random.randint(0,image.size[0])]
      # Move the location so that the rectangle is centered on it
      loc[0] -= size[0]/2
      loc[1] -= size[1]/2
      # Generate random color
      color = self.random.randint(0,255)
      # Add the rectangle to the image
      newArray[max(0,loc[0]):min(newArray.shape[0], loc[0]+size[0]), \
        max(0,loc[1]):min(newArray.shape[1],loc[1]+size[1])] = color
    newImage = Image.new("L", image.size)
    newImage.putdata([uint(p) for p in newArray.flatten()])
    newImage.putalpha(image.split()[1])
    return newImage
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    mode = image.mode;
    originalSize = image.size;
    sizes = [(int(round(image.size[0]*s)), int(round(image.size[1]*s)))
      for s in self.scales]

    resizedImages = []
    for size in sizes:
      if size < image.size:
        resizedImage = image.resize(size,Image.ANTIALIAS)
      else:
        resizedImage = image.resize(size,Image.BICUBIC)
      x = (originalSize[0] - size[0])/2
      y = (originalSize[1] - size[1])/2
      newImage = Image.new(mode,originalSize,self.background)
      newImage.paste(resizedImage,(x,y))
      resizedImages.append(newImage)

    if not self.simultaneous:
      return resizedImages
    else:
      return [resizedImages]
Пример #6
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    s = min(image.size)
    sizeRange = [int(0.1 * s), int(0.4 * s)]

    newArray = numpy.array(image.split()[0].getdata())
    newArray.resize(image.size[1],image.size[0])
    for j in xrange(self.numRectangles):
      # Generate random rectange
      size = (self.random.randint(sizeRange[0], sizeRange[1]),
        self.random.randint(sizeRange[0], sizeRange[1]))
      loc = [self.random.randint(0,image.size[1]),
             self.random.randint(0,image.size[0])]
      # Move the location so that the rectangle is centered on it
      loc[0] -= size[0]/2
      loc[1] -= size[1]/2
      # Generate random color
      color = self.random.randint(0,255)
      # Add the rectangle to the image
      newArray[max(0,loc[0]):min(newArray.shape[0], loc[0]+size[0]), \
        max(0,loc[1]):min(newArray.shape[1],loc[1]+size[1])] = color
    newImage = Image.new("L", image.size)
    newImage.putdata([uint(p) for p in newArray.flatten()])
    newImage.putalpha(image.split()[1])
    return newImage
Пример #7
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
    BaseFilter.process(self, image)

    base, alpha = image.split()

    if self.scaleTowardCenter:
      scale = float(self.factor)
      assert base.mode == "L"
      maxValue = 255 # TODO: Determine how to get maximum value __allowed__.
      offset = ((1.0 - self.factor) / 2.0) * maxValue
      newImage = ImageMath.eval(
          "convert(convert(gray, 'F') * scale + offset, mode)",
          gray=base,
          scale=scale,
          offset=offset,
          mode=base.mode,
        )
    else:
      contrastEnhancer = ImageEnhance.Contrast(image.split()[0])
      newImage = contrastEnhancer.enhance(self.factor)

    newImage.putalpha(alpha)

    return newImage
Пример #8
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
    BaseFilter.process(self, image)
    s = min(image.size)
    sizeRange = [0, s]

    imageArray = numpy.array(image.split()[0].getdata())
    newImage = Image.new("LA", image.size)
    newImage.putdata([uint(p) for p in imageArray])
    newImage.putalpha(image.split()[1])
    for i in xrange(int(self.difficulty*self.maxLines)):
      # Generate random line
      start = (random.randint(sizeRange[0], sizeRange[1]),
        random.randint(sizeRange[0], sizeRange[1]))
      end = (random.randint(sizeRange[0], sizeRange[1]),
        random.randint(sizeRange[0], sizeRange[1]))

      # Generate random color
      color = random.randint(0,255)

      # Add the line to the image
      draw = ImageDraw.Draw(newImage)
      draw.line((start, end), fill=color)

    return newImage
Пример #9
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
        BaseFilter.process(self, image)
        newImage = ImageOps.flip(image)
        return newImage
Пример #10
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
    BaseFilter.process(self, image)
    newImage = ImageOps.flip(image)
    return newImage
Пример #11
0
    def process(self, image):
        """
    image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

        BaseFilter.process(self, image)

        if not self.expand and self.targetRatio:
            # Pad the image to the aspect ratio of the sensor
            # This allows us to rotate in expand=False without cutting off parts
            # of the image unnecessarily
            # Unlike expand=True, the object doesn't get smaller
            ratio = (image.size[0] / float(image.size[1]))
            if ratio < self.targetRatio:
                # Make image wider
                size = (int(image.size[0] * self.targetRatio / ratio),
                        image.size[1])
                newImage = Image.new('LA', size, (self.background, 0))
                newImage.paste(image,
                               ((newImage.size[0] - image.size[0]) / 2, 0))
                image = newImage
            elif ratio > self.targetRatio:
                # Make image taller
                size = (image.size[0],
                        int(image.size[1] * ratio / self.targetRatio))
                newImage = Image.new('LA', size, (self.background, 0))
                newImage.paste(image,
                               (0, (newImage.size[1] - image.size[1]) / 2))
                image = newImage

        if self.highQuality:
            resample = Image.BICUBIC
        else:
            resample = Image.NEAREST
        outputs = []
        for angle in self.angles:
            # Rotate the image, which expands it and pads it with black and a 0
            # alpha value
            rotatedImage = image.rotate(angle,
                                        resample=resample,
                                        expand=self.expand)

            # Create a new larger image to hold the rotated image
            # It is filled with the background color and an alpha value of 0
            outputImage = Image.new('LA', rotatedImage.size,
                                    (self.background, 0))
            # Paste the rotated image into the new image, using the rotated image's
            # alpha channel as a mask
            # This effectively just fills the area around the rotation with the
            # background color, and imports the alpha channel from the rotated image
            outputImage.paste(rotatedImage, None, rotatedImage.split()[1])
            outputs.append(outputImage)
        return outputs
Пример #12
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
        BaseFilter.process(self, image)
        newImage = ImageOps.mirror(image)
        if not self.both:
            return newImage
        else:
            return [image, newImage]
Пример #13
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
        BaseFilter.process(self, image)
        newImage = ImageOps.mirror(image)
        if not self.both:
            return newImage
        else:
            return [image, newImage]
Пример #14
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

        BaseFilter.process(self, image)

        brightnessEnhancer = ImageEnhance.Brightness(image.split()[0])
        newImage = brightnessEnhancer.enhance(self.factor)
        newImage.putalpha(image.split()[1])
        return newImage
Пример #15
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    brightnessEnhancer = ImageEnhance.Brightness(image.split()[0])
    newImage = brightnessEnhancer.enhance(self.factor)
    newImage.putalpha(image.split()[1])
    return newImage
Пример #16
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    if self.box[2] > image.size[0] or self.box[3] > image.size[1]:
      raise RuntimeError('Crop coordinates exceed image bounds')

    return image.crop(self.box)
Пример #17
0
  def process(self, image):
    """
    image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    if not self.expand and self.targetRatio:
      # Pad the image to the aspect ratio of the sensor
      # This allows us to rotate in expand=False without cutting off parts
      # of the image unnecessarily
      # Unlike expand=True, the object doesn't get smaller
      ratio = (image.size[0] / float(image.size[1]))
      if ratio < self.targetRatio:
        # Make image wider
        size = (int(image.size[0] * self.targetRatio / ratio), image.size[1])
        newImage = Image.new('LA', size, (self.background, 0))
        newImage.paste(image, ((newImage.size[0] - image.size[0])/2, 0))
        image = newImage
      elif ratio > self.targetRatio:
        # Make image taller
        size = (image.size[0], int(image.size[1] * ratio / self.targetRatio))
        newImage = Image.new('LA', size, (self.background, 0))
        newImage.paste(image, (0, (newImage.size[1] - image.size[1])/2))
        image = newImage

    if self.highQuality:
      resample = Image.BICUBIC
    else:
      resample = Image.NEAREST
    outputs = []
    for angle in self.angles:
      # Rotate the image, which expands it and pads it with black and a 0
      # alpha value
      rotatedImage = image.rotate(angle,
                                  resample=resample,
                                  expand=self.expand)

      # Create a new larger image to hold the rotated image
      # It is filled with the background color and an alpha value of 0
      outputImage = Image.new('LA', rotatedImage.size, (self.background, 0))
      # Paste the rotated image into the new image, using the rotated image's
      # alpha channel as a mask
      # This effectively just fills the area around the rotation with the
      # background color, and imports the alpha channel from the rotated image
      outputImage.paste(rotatedImage, None, rotatedImage.split()[1])
      outputs.append(outputImage)
    return outputs
Пример #18
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    if image.size == (self.width, self.height):
      return image

    # Resize the image
    targetRatio = self.width / float(self.height)
    imageRatio = image.size[0] / float(image.size[1])
    if self.scaleHeightTo:
      ySize = self.scaleHeightTo
      scaleFactor = self.scaleHeightTo / float(image.size[1])
      xSize = int(scaleFactor * image.size[0])
    elif self.scaleWidthTo:
      xSize = self.scaleWidthTo
      scaleFactor = self.scaleWidthTo / float(image.size[0])
      ySize = int(scaleFactor * image.size[1])
    else:
      if imageRatio > targetRatio:
        xSize = self.width
        scaleFactor = self.width / float(image.size[0])
        ySize = int(scaleFactor * image.size[1])
      else:
        ySize = self.height
        scaleFactor = self.height / float(image.size[1])
        xSize = int(scaleFactor * image.size[0])

    if (xSize, ySize) < image.size:
      image = image.resize((xSize, ySize),Image.ANTIALIAS)
    else:
      image = image.resize((xSize, ySize),Image.BICUBIC)

    # Pad the image if necessary
    if self.pad and image.size != (self.width, self.height):
      paddedImage = Image.new('L', (self.width, self.height),
        self.background)
      alpha = Image.new('L', (self.width, self.height))
      paddedImage.putalpha(alpha)
      paddedImage.paste(image,
        ((self.width - image.size[0])/2, (self.height - image.size[1])/2))
      image = paddedImage

    return image
Пример #19
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
    BaseFilter.process(self, image)
    type = self.random.choice(self.types)
    #Default matrix
    matrix = (1, 0, 0, 0, 1, 0)
    size = list(image.size)
    newImage = Image.new('LA', size)
    if type == 'shear_x':
        shear = self.difficulty*self.maxShear - self.difficulty*0.3 + self.difficulty*0.3*self.random.random()
        matrix = (1, shear, -shear*size[1], 0, 1, 0)
        size[0] += int(shear*size[0])
        newImage = image.transform(tuple(size), Image.AFFINE, matrix)
        bbox = list(newImage.split()[1].getbbox())
        bbox[1] = 0
        bbox[3] = size[1]
        newImage = newImage.crop(bbox)
    elif type == 'shear_y':
        shear = self.difficulty*self.maxShear - self.difficulty*0.3 + self.difficulty*0.3*self.random.random()
        matrix = (1, 0, 0, shear, 1, -shear*size[0])
        size[1] += int(shear*size[1])
        newImage = image.transform(tuple(size), Image.AFFINE, matrix)
        bbox = list(newImage.split()[1].getbbox())
        bbox[0] = 0
        bbox[2] = size[0]
        newImage = newImage.crop(bbox)
    elif type == 'squeeze_x':
        squeeze = self.minSqueeze - (self.minSqueeze - self.maxSqueeze)*(self.difficulty - self.difficulty*0.3 + self.difficulty*0.3*self.random.random())
        matrix = (1/squeeze, 0, 0, 0, 1, 0)
        newImage = ImageChops.offset(image.transform(tuple(size), Image.AFFINE, matrix), int((size[0] - squeeze*size[0])/2), 0)
    elif type == 'squeeze_y':
        squeeze = self.minSqueeze - (self.minSqueeze - self.maxSqueeze)*(self.difficulty - self.difficulty*0.3 + self.difficulty*0.3*self.random.random())
        matrix = (1, 0, 0, 0, 1/squeeze, 0)
        newImage = ImageChops.offset(image.transform(tuple(size), Image.AFFINE, matrix), 0, int((size[1] - squeeze*size[1])/2))
    #Appropriate sizing
    if newImage.size[0] > image.size[0] or newImage.size[1] > image.size[1]:
        newImage = newImage.resize(image.size)
    elif newImage.size[1] < image.size[1]:
        retImage = Image.new('LA', image.size)
        retImage.paste(newImage, (0, int((image.size[1] - newImage.size[1])/2.0)))
        newImage = retImage
    elif newImage.size[0] < image.size[0]:
        retImage = Image.new('LA', image.size)
        retImage.paste(newImage, (0, int((image.size[0] - newImage.size[0])/2.0)))
    return newImage
Пример #20
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    if image.size == (self.width, self.height):
      return image

    # Resize the image
    targetRatio = self.width / float(self.height)
    imageRatio = image.size[0] / float(image.size[1])
    if self.scaleHeightTo:
      ySize = self.scaleHeightTo
      scaleFactor = self.scaleHeightTo / float(image.size[1])
      xSize = int(scaleFactor * image.size[0])
    elif self.scaleWidthTo:
      xSize = self.scaleWidthTo
      scaleFactor = self.scaleWidthTo / float(image.size[0])
      ySize = int(scaleFactor * image.size[1])
    else:
      if imageRatio > targetRatio:
        xSize = self.width
        scaleFactor = self.width / float(image.size[0])
        ySize = int(scaleFactor * image.size[1])
      else:
        ySize = self.height
        scaleFactor = self.height / float(image.size[1])
        xSize = int(scaleFactor * image.size[0])

    if (xSize, ySize) < image.size:
      image = image.resize((xSize, ySize),Image.ANTIALIAS)
    else:
      image = image.resize((xSize, ySize),Image.BICUBIC)

    # Pad the image if necessary
    if self.pad and image.size != (self.width, self.height):
      paddedImage = Image.new('L', (self.width, self.height),
        self.background)
      alpha = Image.new('L', (self.width, self.height))
      paddedImage.putalpha(alpha)
      paddedImage.paste(image,
        ((self.width - image.size[0])/2, (self.height - image.size[1])/2))
      image = paddedImage

    return image
Пример #21
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    mask = image.split()[1]
    for i in xrange(self.level):
      sharpness_enhancer = ImageEnhance.Sharpness(image.split()[0])
      image = sharpness_enhancer.enhance(0.0)
    image.putalpha(mask)
    return image
Пример #22
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    mask = image.split()[1]
    for i in xrange(self.level):
      sharpness_enhancer = ImageEnhance.Sharpness(image.split()[0])
      image = sharpness_enhancer.enhance(0.0)
    image.putalpha(mask)
    return image
Пример #23
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
        BaseFilter.process(self, image)
        #Type of gradient?
        type = self.random.choice(self.types)

        gradientImage = self.gradientImages.get((image.size, type))

        if not gradientImage:
            #Gradient image, used as mask
            gradientImage = Image.new("L", image.size)
            gradientArray = numpy.array(gradientImage.split()[0].getdata())
            gradientArray.resize(image.size[1], image.size[0])

            #Calculate gradient
            opacity = self.difficulty - self.difficulty * .2 + self.random.random(
            ) * self.difficulty * .2
            for i in xrange(image.size[1]):
                for j in xrange(image.size[0]):
                    if type == 'horizontal':
                        gradientArray[i][j] = int(
                            float(j) / image.size[0] * 255 / opacity)
                    elif type == 'vertical':
                        gradientArray[i][j] = int(
                            float(i) / image.size[1] * 255 / opacity)
                    elif type == 'circular':
                        gradientArray[i][j] = int(
                            math.sqrt((i - image.size[1] / 2)**2 +
                                      (j - image.size[0] / 2)**2) /
                            math.sqrt((image.size[1] / 2)**2 +
                                      (image.size[0] / 2)**2) * 255 / opacity)

            gradientImage.putdata([uint(p) for p in gradientArray.flatten()])
            #Add gradient image to dictionary
            self.gradientImages[(image.size, type)] = gradientImage

        #Image to composite with for brightness
        whiteImage = Image.new("LA", image.size)
        whiteArray = numpy.array(whiteImage.split()[0].getdata())
        whiteArray += 255
        whiteImage.putdata([uint(p) for p in whiteArray])
        newImage = Image.composite(image, whiteImage, gradientImage)
        return newImage
Пример #24
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    if self.mode != 'gray':
      raise RuntimeError("EqualizeHistogram only supports grayscale images.")

    if self.region == 'bbox':
      bbox = image.split()[1].getbbox()
      croppedImage = image.crop(bbox)
      croppedImage.load()
      alpha = croppedImage.split()[1]
      croppedImage = ImageOps.equalize(croppedImage.split()[0])
      croppedImage.putalpha(alpha)
      image.paste(croppedImage, bbox)
    elif self.region == 'mask':
      bbox = image.split()[1].getbbox()
      croppedImage = image.crop(bbox)
      croppedImage.load()
      alpha = croppedImage.split()[1]
      # Fill in the part of the cropped image outside the bounding box with
      # uniformly-distributed noise
      noiseArray = \
        numpy.random.randint(0, 255, croppedImage.size[0]*croppedImage.size[1])
      noiseImage = Image.new('L', croppedImage.size)
      noiseImage.putdata([uint(p) for p in noiseArray])
      compositeImage = Image.composite(croppedImage, noiseImage, alpha)
      # Equalize the composite image
      compositeImage = ImageOps.equalize(compositeImage.split()[0])
      # Paste the part of the equalized image within the mask back
      # into the cropped image
      croppedImage = Image.composite(compositeImage, croppedImage, alpha)
      croppedImage.putalpha(alpha)
      # Paste the cropped image back into the full image
      image.paste(croppedImage, bbox)
    elif self.region == 'all':
      alpha = image.split()[1]
      image = ImageOps.equalize(image.split()[0])
      image.putalpha(alpha)
    return image
Пример #25
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image
    """

    BaseFilter.process(self, image)

    newImage = image

    # Shifting by more than one pixel can cause problems, so even if
    # stepSize > 1, get there by thickening by one shift at a time
    for x in xrange(-self.shiftSize,self.shiftSize+1):
      for y in xrange(-self.shiftSize,self.shiftSize+1):
        offsetImage = ImageChops.offset(image,x,y)
        newImage = ImageChops.lighter(newImage,offsetImage)
    return newImage
Пример #26
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image
    """

        BaseFilter.process(self, image)

        newImage = image

        # Shifting by more than one pixel can cause problems, so even if
        # stepSize > 1, get there by thickening by one shift at a time
        for x in xrange(-self.shiftSize, self.shiftSize + 1):
            for y in xrange(-self.shiftSize, self.shiftSize + 1):
                offsetImage = ImageChops.offset(image, x, y)
                newImage = ImageChops.lighter(newImage, offsetImage)
        return newImage
Пример #27
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    if self.mode != 'gray':
      raise RuntimeError("NormalizeContrast only supports grayscale images.")

    if self.region == 'bbox':
      bbox = image.split()[1].getbbox()
      croppedImage = image.crop(bbox)
      croppedImage.load()
      alpha = croppedImage.split()[1]
      croppedImage = \
        ImageOps.autocontrast(croppedImage.split()[0], cutoff=self.cutoff)
      croppedImage.putalpha(alpha)
      image.paste(croppedImage, image.bbox)
    elif self.region == 'mask':
      bbox = image.split()[1].getbbox()
      croppedImage = image.crop(bbox)
      croppedImage.load()
      alpha = croppedImage.split()[1]
      # Fill in the part of the cropped image outside the bounding box with a
      # uniform shade of gray
      grayImage = ImageChops.constant(croppedImage, 128)
      compositeImage = Image.composite(croppedImage, grayImage, alpha)
      # Equalize the composite image
      compositeImage = \
        ImageOps.autocontrast(compositeImage.split()[0], cutoff=self.cutoff)
      # Paste the part of the equalized image within the mask back
      # into the cropped image
      croppedImage = Image.composite(compositeImage, croppedImage, alpha)
      croppedImage.putalpha(alpha)
      # Paste the cropped image back into the full image
      image.paste(croppedImage, bbox)
    elif self.region == 'all':
      alpha = image.split()[1]
      image = ImageOps.autocontrast(image.split()[0], cutoff=self.cutoff)
      image.putalpha(alpha)
    return image
Пример #28
0
  def process(self, image):
    """
    Perform LogPolar filtering on the input image and return the response

    @param image -- The image to process
    """

    #image.save("logPolarDebugInput.png")
    BaseFilter.process(self, image)
    #image.save("logPolarDebugPostBase.png")

    out = self._applyKernel(image, 0)
    outImg = Image.fromarray(out.astype(numpy.int8))
    #outImg.save("logPolarDebug.png")
    maskOut = self._applyKernel(image, 1)
    maskOutImg = Image.fromarray(maskOut.astype(numpy.int8))
    outImg.putalpha(maskOutImg)
    #outImg.save("logPolarDebugMask.png")
    self._lastOutputImage = outImg
    return outImg
Пример #29
0
    def process(self, image):
        """
    Perform LogPolar filtering on the input image and return the response

    @param image -- The image to process
    """

        #image.save("logPolarDebugInput.png")
        BaseFilter.process(self, image)
        #image.save("logPolarDebugPostBase.png")

        out = self._applyKernel(image, 0)
        outImg = Image.fromarray(out.astype(numpy.int8))
        #outImg.save("logPolarDebug.png")
        maskOut = self._applyKernel(image, 1)
        maskOutImg = Image.fromarray(maskOut.astype(numpy.int8))
        outImg.putalpha(maskOutImg)
        #outImg.save("logPolarDebugMask.png")
        self._lastOutputImage = outImg
        return outImg
Пример #30
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

        BaseFilter.process(self, image)

        if image.size == (self.width, self.height):
            return image

        if image.size[0] > self.width or image.size[1] > self.height:
            raise RuntimeError('Image is larger than target size')

        newImage = Image.new(image.mode, (self.width, self.height),
                             self.background)
        xPad = self.width - image.size[0]
        yPad = self.height - image.size[1]
        newImage.paste(image, (xPad / 2, yPad / 2))
        return newImage
Пример #31
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    if image.size == (self.width, self.height):
      return image

    if image.size[0] > self.width or image.size[1] > self.height:
      raise RuntimeError('Image is larger than target size')

    newImage = Image.new(image.mode, (self.width, self.height),
      self.background)
    xPad = self.width - image.size[0]
    yPad = self.height - image.size[1]
    newImage.paste(image, (xPad/2, yPad/2))
    return newImage
Пример #32
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
    BaseFilter.process(self, image)
    #Type of gradient?
    type = self.random.choice(self.types)

    gradientImage = self.gradientImages.get((image.size, type))

    if not gradientImage:
        #Gradient image, used as mask
        gradientImage = Image.new("L", image.size)
        gradientArray = numpy.array(gradientImage.split()[0].getdata())
        gradientArray.resize(image.size[1], image.size[0])

        #Calculate gradient
        opacity = self.difficulty - self.difficulty*.2 + self.random.random()*self.difficulty*.2
        for i in xrange(image.size[1]):
            for j in xrange(image.size[0]):
                if type == 'horizontal':
                    gradientArray[i][j] = int(float(j)/image.size[0]*255/opacity)
                elif type == 'vertical':
                    gradientArray[i][j] = int(float(i)/image.size[1]*255/opacity)
                elif type == 'circular':
                    gradientArray[i][j] = int(math.sqrt((i - image.size[1]/2)**2 + (j - image.size[0]/2)**2)/math.sqrt((image.size[1]/2)**2 + (image.size[0]/2)**2)*255/opacity)

        gradientImage.putdata([uint(p) for p in gradientArray.flatten()])
        #Add gradient image to dictionary
        self.gradientImages[(image.size, type)] = gradientImage

    #Image to composite with for brightness
    whiteImage = Image.new("LA", image.size)
    whiteArray = numpy.array(whiteImage.split()[0].getdata())
    whiteArray += 255
    whiteImage.putdata([uint(p) for p in whiteArray])
    newImage = Image.composite(image, whiteImage, gradientImage)
    return newImage
Пример #33
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    sizes = [(int(round(image.size[0]*s)), int(round(image.size[1]*s)))
      for s in self.scales]

    resizedImages = []
    for size in sizes:
      if size < image.size:
        resizedImages.append(image.resize(size,Image.ANTIALIAS))
      else:
        resizedImages.append(image.resize(size,Image.BICUBIC))

    if not self.simultaneous:
      return resizedImages
    else:
      return [resizedImages]
Пример #34
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
    BaseFilter.process(self, image)
    #Create numpy array from image grayscale data and resize to image dimensions
    imageArray = numpy.array(image.split()[0].getdata())
    imageArray.resize(image.size[1], image.size[0])
    #Calculate offset from difficulty level
    offset = self.difficulty*(self.maxOffset)
    #Add random change to offset within window size
    halfWindowSize = 0.1*offset
    offset = (offset - halfWindowSize) + halfWindowSize*self.random.random()*((-1)**self.random.randint(1, 2))
    #Apply random direction
    offset *= ((-1)**self.random.randint(1, 2))
    imageArray += offset
    #Recreate PIL image
    newImage = Image.new("L", image.size)
    newImage.putdata([uint(p) for p in imageArray.flatten()])
    newImage.putalpha(image.split()[1])
    return newImage
Пример #35
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
    BaseFilter.process(self, image)
    #Create numpy array from image grayscale data and resize to image dimensions
    imageArray = numpy.array(image.split()[0].getdata())
    imageArray.resize(image.size[1], image.size[0])
    #Calculate offset from difficulty level
    offset = self.difficulty*(self.maxOffset)
    #Add random change to offset within window size
    halfWindowSize = 0.1*offset
    offset = (offset - halfWindowSize) + halfWindowSize*self.random.random()*((-1)**self.random.randint(1, 2))
    #Apply random direction
    offset *= ((-1)**self.random.randint(1, 2))
    imageArray += offset
    #Recreate PIL image
    newImage = Image.new("L", image.size)
    newImage.putdata([uint(p) for p in imageArray.flatten()])
    newImage.putalpha(image.split()[1])
    return newImage
Пример #36
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

        BaseFilter.process(self, image)

        sizes = [(int(round(image.size[0] * s)), int(round(image.size[1] * s)))
                 for s in self.scales]

        resizedImages = []
        for size in sizes:
            if size < image.size:
                resizedImages.append(image.resize(size, Image.ANTIALIAS))
            else:
                resizedImages.append(image.resize(size, Image.BICUBIC))

        if not self.simultaneous:
            return resizedImages
        else:
            return [resizedImages]
Пример #37
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

        BaseFilter.process(self, image)

        # ---------------------------------------------------------------------------
        # Create the mask around the source image
        mask = image.split()[-1]
        if image.mode[-1] != 'A' or isSimpleBBox(mask):
            mask = createMask(image,
                              threshold=self._threshold,
                              fillHoles=True,
                              backgroundColor=self.background,
                              blurRadius=self._blurRadius,
                              maskScale=self._maskScale)

        # ---------------------------------------------------------------------------
        # Process each value
        newImages = []
        for value in self._values:
            if value is None:
                value = self.background

            bg = ImageChops.constant(image, value)
            newImage = Image.composite(image.split()[0], bg, mask)
            newImage.putalpha(image.split()[-1])
            newImages.append(newImage)

        if len(newImages) == 1:
            return newImages[0]
        else:
            return newImages
Пример #38
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

        BaseFilter.process(self, image)

        sizes = []
        for i, size in enumerate(self.sizes):
            if len(size) == 1:
                # Convert scalar sizes to absolute sizes in pixels
                sizes.append((int(round(image.size[0] * float(size[0]))),
                              int(round(image.size[1] * float(size[0])))))
            else:
                sizes.append((int(size[0]), int(size[1])))

        newImages = []
        for size in sizes:
            if image.size == size:
                newImage = image

            elif self.method == 'fit':
                # Resize the image to fit in the target size, preserving aspect ratio
                targetRatio = size[0] / float(size[1])
                imageRatio = image.size[0] / float(image.size[1])
                if imageRatio > targetRatio:
                    xSize = size[0]
                    scale = size[0] / float(image.size[0])
                    ySize = int(scale * image.size[1])
                else:
                    ySize = size[1]
                    scale = size[1] / float(image.size[1])
                    xSize = int(scale * image.size[0])
                newImage = self._resize(image, (xSize, ySize))
                # Pad with the background color if necessary
                if newImage.size != size:
                    paddedImage = Image.new('LA', size, self.background)
                    paddedImage.paste(newImage,
                                      ((size[0] - newImage.size[0]) / 2,
                                       (size[1] - newImage.size[1]) / 2))
                    newImage = paddedImage

            elif self.method == 'crop':
                # Resize the image to fill the new size
                targetRatio = size[0] / float(size[1])
                imageRatio = image.size[0] / float(image.size[1])
                if imageRatio > targetRatio:
                    # Original image is too wide
                    scale = size[1] / float(image.size[1])
                    newSize = (int(scale * image.size[0]), size[1])
                    cropStart = ((newSize[0] - size[0]) / 2, 0)
                else:
                    # Original image is too tall
                    scale = size[0] / float(image.size[0])
                    newSize = (size[0], int(scale * image.size[1]))
                    cropStart = (0, (newSize[1] - size[1]) / 2)

                newImage = self._resize(image, newSize)
                # Crop if necessary
                if newSize != size:
                    newImage = newImage.crop(
                        (cropStart[0], cropStart[1], cropStart[0] + size[0],
                         cropStart[1] + size[1]))

            elif self.method == 'stretch':
                # Resize the image to each target size, ignoring aspect ratio
                newImage = self._resize(image, size)

            elif self.method == 'center':
                # Center the original image in the new image without rescaling it
                newImage = Image.new('LA', size, self.background)
                x = (size[0] - image.size[0]) / 2
                y = (size[1] - image.size[1]) / 2
                newImage.paste(image, (x, y))

            newImages.append(newImage)

        if not self.simultaneous:
            if len(newImages) == 1:
                return newImages[0]
            else:
                return newImages
        else:
            return [newImages]
Пример #39
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)


    # If no background image, just return the input image as-is
    if self.bgPath is None:
      return image

    # ---------------------------------------------------------------------------
    # Open the background image(s) if we haven't done so already
    if self.bgImgs is None:

      # If given a relative path, make it relative to the vision data directory
      if not os.path.isabs(self.bgPath):
        basePath = os.path.abspath(os.curdir)
        basePath = os.path.split(basePath)
        while(basePath[0]):
          if basePath[1] == 'vision':
            break
          basePath = os.path.split(basePath[0])

        # Did we find the vision directory?
        if basePath[1] == 'vision':
          fullPath = VisionUtils.findData(os.path.join(basePath[0], 'vision'),
                        self.bgPath, 'backgound', 'background images', True)
          #basePath = os.path.join(basePath[0], 'vision', 'data')
        else:
          fullPath = self.bgPath
      else:
        fullPath = self.bgPath


      # If given a filename, we only have 1 image
      if os.path.isfile(fullPath):
        self.bgImgs = [Image.open(fullPath).convert('LA')]

      # Else, open up all images in this directory
      else:
        self.bgImgs = []
        w = os.walk(fullPath)
        while True:
          try:
            dirpath, dirnames, filenames = w.next()
          except StopIteration:
            break

          # Don't enter directories that begin with '.'
          for d in dirnames[:]:
            if d.startswith('.'):
              dirnames.remove(d)
          dirnames.sort()

          # Ignore files that begin with '.'
          filenames = [f for f in filenames if not f.startswith('.')]
          filenames.sort()
          imageFilenames = [os.path.join(dirpath, f) for f in filenames]

          # Process each image
          for filename in imageFilenames:
            self.bgImgs.append(Image.open(filename).convert('L'))

      # Keep a cache of all images, scaled to the input image size
      self.scaledBGImgs = [x.copy() for x in self.bgImgs]


    # Pick a background at random.
    idx = self._rng.randint(0, len(self.bgImgs)-1)
    bgImg = self.scaledBGImgs[idx]

    # ---------------------------------------------------------------------------
    # re-scale the background to the source image if necessary
    if bgImg.size != image.size:
      bgImg = self.scaledBGImgs[idx] = self.bgImgs[idx].resize(image.size, Image.ANTIALIAS)

    # ---------------------------------------------------------------------------
    # Create the mask around the source image
    mask = image.split()[-1]
    if image.mode[-1] != 'A' or isSimpleBBox(mask):
      mask = createMask(image, threshold=self._threshold, fillHoles=True,
                        backgroundColor=self.background, blurRadius=self._blurRadius,
                        maskScale=self._maskScale)

    # ---------------------------------------------------------------------------
    # Paste the image onto the background
    newImage = bgImg.copy()
    newImage.paste(image, (0,0), mask)

    # Put an "all-on" alpha channel because we now want the network to consider the entire
    #  image
    newImage.putalpha(ImageChops.constant(newImage, 255))

    return newImage
Пример #40
0
  def _processImage(self, image, bbox):
    """Return a single image, or a list containing one or more images.

    @param image -- The image to process.
    """
    BaseFilter.process(self, image)

    inWidth, inHeight = image.size

    # Get output dims and buffers (cached)
    outWidth, outHeight, inBuffer, outBuffer, mask = self._prepare(image.size)

    # Ask the sub-class the build the filter bank
    self._buildFilterBank()

    inputOffset  = 0
    outputOffset = 0

    data = image.split()[0]
    inputVector = numpy.asarray(data, dtype=numpy.float32)

    inputVector.shape = (inHeight, inWidth)

    # If we are using "color-key" mode, then detect the value of
    # the upper-left pixel and use it as the value of
    # 'offImagePixelValue'
    if self._offImagePixelValue in ('colorKey', u'colorKey'):
      offImagePixelValue = inputVector[0, 0]
    else:
      offImagePixelValue = self._offImagePixelValue

    result = []

    # Compute the convolution responses

    # Determine proper input/output dimensions
    outputSize = outHeight * outWidth * self._outputPlaneCount

    # Locate correct portion of output
    outputVector = numpy.zeros((outHeight,
                                outWidth,
                                self._outputPlaneCount),
                                dtype=numpy.float32)
    outputVector.shape = (self._outputPlaneCount, outHeight, outWidth)


    # Compute the bounding box to use for our C implementation
    imageBox = numpy.array([0, 0, inWidth, inHeight], dtype=numpy.int32)

    ## --- DEBUG CODE ----
    #global id
    #o = inputVector
    #f = os.path.abspath('convolution_input_%d.txt' % id)
    #print f
    #numpy.savetxt(f, o)
    #id += 1
    ##from dbgp.client import brk; brk(port=9019)
    ## --- DEBUG CODE END ----

    # Call the fast convolution C code
    self._convolve(inputVector,
                   bbox,
                   imageBox,
                   outputVector,
                   offImagePixelValue,
                   inBuffer,
                   outBuffer)

    outputVector = numpy.rollaxis(outputVector, 0, 3)
    outputVector = outputVector.reshape(outWidth * outHeight,
                                        self._outputPlaneCount).flatten()
    assert outputVector.dtype == numpy.float32

    locationCount = len(outputVector) / self._outputPlaneCount
    response = outputVector.reshape(locationCount, self._outputPlaneCount)

    ## --- DEBUG CODE ----
    #global id
    #o = outputVector.flatten()
    ##print outputVector.shape, len(o)
    #f = os.path.abspath('convolution_output_%d.txt' % id)
    #print f
    #numpy.savetxt(f, o)
    #id += 1
    ##from dbgp.client import brk; brk(port=9019)
    ## --- DEBUG CODE END ----

    # Convert the reponses to images
    result = []
    for i in range(response.shape[1]):
      newImage = Image.new('L', (outWidth, outHeight))
      #data = (self._gainConstant * 255.0 * response[:,i]).clip(min=0.0, max=255.0).astype(numpy.uint8)
      data = (255.0 * response[:,i]).clip(min=0.0, max=255.0).astype(numpy.uint8)
      newImage.putdata([uint(p) for p in data])
      newImage.putalpha(mask)
      result.append(newImage)

    return (result, outputVector)
Пример #41
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
        # Get our random state back
        saveState = numpy.random.get_state()
        numpy.random.set_state(self._randomState)

        # Send through parent class first
        BaseFilter.process(self, image)

        alpha = image.split()[1]
        # -----------------------------------------------------------------------
        # black and white
        if self.mode == 'bw':
            # For black and white images, our doBackground pixels are 255 and our figure pixels
            #  are 0.
            assert self.noiseThickness != 0, "ImageSensor parameter noiseThickness cannot be 0"
            pixels = numpy.array(image.split()[0].getdata(), dtype=int)
            (imgWidth, imgHeight) = image.size
            pixels2d = (numpy.array(pixels)).reshape(imgHeight, imgWidth)
            noiseArrayW = numpy.floor(imgWidth / float(self.noiseThickness))
            noiseArrayH = numpy.floor(imgHeight / float(self.noiseThickness))
            thickNoise = numpy.random.random((noiseArrayH, noiseArrayW))
            thickNoise = 255 * (thickNoise < self.noiseLevel)
            idxW = numpy.array(
                [int(self.noiseThickness * i) for i in xrange(noiseArrayW)])
            idxH = numpy.array(
                [int(self.noiseThickness * i) for i in xrange(noiseArrayH)])
            for nt1 in xrange(self.noiseThickness):
                for nt2 in xrange(self.noiseThickness):
                    submatIdx = numpy.ix_(idxH + nt1, idxW + nt2)
                    if self.doForeground and self.doBackground:
                        pixels2d[submatIdx] ^= thickNoise
                    elif self.doForeground:
                        pixels2d[submatIdx] = (pixels2d[submatIdx] ^ thickNoise
                                               ) | pixels2d[submatIdx]
                    elif self.doBackground:
                        pixels2d[submatIdx] = (pixels2d[submatIdx] ^ thickNoise
                                               ) & pixels2d[submatIdx]
                pixels2d = numpy.abs(pixels2d)
                pixels = pixels2d.reshape(1, imgWidth * imgHeight)[0]

        # -----------------------------------------------------------------------
        # gray-scale
        elif self.mode == 'gray':
            pixels = numpy.array(image.split()[0].getdata(), dtype=int)
            noise = numpy.random.random(
                len(pixels))  # get array of floats from 0 to 1

            # Add +/- self.noiseLevel to each pixel
            noise = (noise - 0.5) * 2 * self.noiseLevel * 255
            mask = numpy.array(alpha.getdata(), dtype=int) != self.background
            if self.doForeground and self.doBackground:
                pixels += noise
            elif self.doForeground:
                pixels[mask != 0] += noise[mask != 0]
            elif self.doBackground:
                pixels[mask == 0] += noise[mask == 0]
            pixels = pixels.clip(min=0, max=255)

        else:
            raise ValueError("This image mode not supported")

        # write out the new pixels
        #from dbgp.client import brk; brk(port=9049)
        newimage = Image.new(image.mode, image.size)

        #newimage.putdata([uint(p) for p in pixels])
        newimage.putdata(pixels.tolist())
        newimage.putalpha(alpha)

        # If generating dynamic noise, change our random state each time.
        if self.dynamic:
            self._randomState = numpy.random.get_state()

        # Restore random state
        numpy.random.set_state(saveState)

        return newimage
Пример #42
0
  def _processImage(self, image, bbox):
    """Return a single image, or a list containing one or more images.

    @param image -- The image to process.
    """
    BaseFilter.process(self, image)

    inWidth, inHeight = image.size

    # Get output dims and buffers (cached)
    outWidth, outHeight, inBuffer, outBuffer, mask = self._prepare(image.size)

    # Ask the sub-class the build the filter bank
    self._buildFilterBank()

    inputOffset  = 0
    outputOffset = 0

    data = image.split()[0]
    inputVector = numpy.asarray(data, dtype=numpy.float32)

    inputVector.shape = (inHeight, inWidth)

    # If we are using "color-key" mode, then detect the value of
    # the upper-left pixel and use it as the value of
    # 'offImagePixelValue'
    if self._offImagePixelValue in ('colorKey', u'colorKey'):
      offImagePixelValue = inputVector[0, 0]
    else:
      offImagePixelValue = self._offImagePixelValue

    result = []

    # Compute the convolution responses

    # Determine proper input/output dimensions
    outputSize = outHeight * outWidth * self._outputPlaneCount

    # Locate correct portion of output
    outputVector = numpy.zeros((outHeight,
                                outWidth,
                                self._outputPlaneCount),
                                dtype=numpy.float32)
    outputVector.shape = (self._outputPlaneCount, outHeight, outWidth)


    # Compute the bounding box to use for our C implementation
    imageBox = numpy.array([0, 0, inWidth, inHeight], dtype=numpy.int32)

    ## --- DEBUG CODE ----
    #global id
    #o = inputVector
    #f = os.path.abspath('convolution_input_%d.txt' % id)
    #print f
    #numpy.savetxt(f, o)
    #id += 1
    ##from dbgp.client import brk; brk(port=9019)
    ## --- DEBUG CODE END ----

    # Call the fast convolution C code
    self._convolve(inputVector,
                   bbox,
                   imageBox,
                   outputVector,
                   offImagePixelValue,
                   inBuffer,
                   outBuffer)

    outputVector = numpy.rollaxis(outputVector, 0, 3)
    outputVector = outputVector.reshape(outWidth * outHeight,
                                        self._outputPlaneCount).flatten()
    assert outputVector.dtype == numpy.float32

    locationCount = len(outputVector) / self._outputPlaneCount
    response = outputVector.reshape(locationCount, self._outputPlaneCount)

    ## --- DEBUG CODE ----
    #global id
    #o = outputVector.flatten()
    ##print outputVector.shape, len(o)
    #f = os.path.abspath('convolution_output_%d.txt' % id)
    #print f
    #numpy.savetxt(f, o)
    #id += 1
    ##from dbgp.client import brk; brk(port=9019)
    ## --- DEBUG CODE END ----

    # Convert the reponses to images
    result = []
    for i in range(response.shape[1]):
      newImage = Image.new('L', (outWidth, outHeight))
      #data = (self._gainConstant * 255.0 * response[:,i]).clip(min=0.0, max=255.0).astype(numpy.uint8)
      data = (255.0 * response[:,i]).clip(min=0.0, max=255.0).astype(numpy.uint8)
      newImage.putdata([uint(p) for p in data])
      newImage.putalpha(mask)
      result.append(newImage)

    return (result, outputVector)
Пример #43
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
        BaseFilter.process(self, image)
        type = self.random.choice(self.types)
        #Default matrix
        matrix = (1, 0, 0, 0, 1, 0)
        size = list(image.size)
        newImage = Image.new('LA', size)
        if type == 'shear_x':
            shear = self.difficulty * self.maxShear - self.difficulty * 0.3 + self.difficulty * 0.3 * self.random.random(
            )
            matrix = (1, shear, -shear * size[1], 0, 1, 0)
            size[0] += int(shear * size[0])
            newImage = image.transform(tuple(size), Image.AFFINE, matrix)
            bbox = list(newImage.split()[1].getbbox())
            bbox[1] = 0
            bbox[3] = size[1]
            newImage = newImage.crop(bbox)
        elif type == 'shear_y':
            shear = self.difficulty * self.maxShear - self.difficulty * 0.3 + self.difficulty * 0.3 * self.random.random(
            )
            matrix = (1, 0, 0, shear, 1, -shear * size[0])
            size[1] += int(shear * size[1])
            newImage = image.transform(tuple(size), Image.AFFINE, matrix)
            bbox = list(newImage.split()[1].getbbox())
            bbox[0] = 0
            bbox[2] = size[0]
            newImage = newImage.crop(bbox)
        elif type == 'squeeze_x':
            squeeze = self.minSqueeze - (self.minSqueeze - self.maxSqueeze) * (
                self.difficulty - self.difficulty * 0.3 +
                self.difficulty * 0.3 * self.random.random())
            matrix = (1 / squeeze, 0, 0, 0, 1, 0)
            newImage = ImageChops.offset(
                image.transform(tuple(size), Image.AFFINE, matrix),
                int((size[0] - squeeze * size[0]) / 2), 0)
        elif type == 'squeeze_y':
            squeeze = self.minSqueeze - (self.minSqueeze - self.maxSqueeze) * (
                self.difficulty - self.difficulty * 0.3 +
                self.difficulty * 0.3 * self.random.random())
            matrix = (1, 0, 0, 0, 1 / squeeze, 0)
            newImage = ImageChops.offset(
                image.transform(tuple(size), Image.AFFINE, matrix), 0,
                int((size[1] - squeeze * size[1]) / 2))
        #Appropriate sizing
        if newImage.size[0] > image.size[0] or newImage.size[1] > image.size[1]:
            newImage = newImage.resize(image.size)
        elif newImage.size[1] < image.size[1]:
            retImage = Image.new('LA', image.size)
            retImage.paste(newImage,
                           (0, int((image.size[1] - newImage.size[1]) / 2.0)))
            newImage = retImage
        elif newImage.size[0] < image.size[0]:
            retImage = Image.new('LA', image.size)
            retImage.paste(newImage,
                           (0, int((image.size[0] - newImage.size[0]) / 2.0)))
        return newImage
Пример #44
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """
    # Get our random state back
    saveState = numpy.random.get_state()
    numpy.random.set_state(self._randomState)

    # Send through parent class first
    BaseFilter.process(self, image)

    alpha = image.split()[1]
    # -----------------------------------------------------------------------
    # black and white
    if self.mode == 'bw':
      # For black and white images, our doBackground pixels are 255 and our figure pixels
      #  are 0.
      assert self.noiseThickness != 0, "ImageSensor parameter noiseThickness cannot be 0"
      pixels = numpy.array(image.split()[0].getdata(), dtype=int)
      (imgWidth,imgHeight) = image.size
      pixels2d = (numpy.array(pixels)).reshape(imgHeight, imgWidth)
      noiseArrayW = numpy.floor(imgWidth/float(self.noiseThickness))
      noiseArrayH = numpy.floor(imgHeight/float(self.noiseThickness))
      thickNoise = numpy.random.random((noiseArrayH, noiseArrayW))
      thickNoise = 255*(thickNoise < self.noiseLevel)
      idxW = numpy.array([int(self.noiseThickness*i) for i in xrange(noiseArrayW)])
      idxH = numpy.array([int(self.noiseThickness*i) for i in xrange(noiseArrayH)])
      for nt1 in xrange(self.noiseThickness):
        for nt2 in xrange(self.noiseThickness):
          submatIdx = numpy.ix_(idxH + nt1, idxW + nt2)
          if self.doForeground and self.doBackground:
            pixels2d[submatIdx] ^= thickNoise
          elif self.doForeground:
            pixels2d[submatIdx] = (pixels2d[submatIdx]^thickNoise) | pixels2d[submatIdx]
          elif self.doBackground:
            pixels2d[submatIdx] = (pixels2d[submatIdx]^thickNoise) & pixels2d[submatIdx]
        pixels2d = numpy.abs(pixels2d)
        pixels = pixels2d.reshape(1,imgWidth*imgHeight)[0]

    # -----------------------------------------------------------------------
    # gray-scale
    elif self.mode == 'gray':
      pixels = numpy.array(image.split()[0].getdata(), dtype=int)
      noise = numpy.random.random(len(pixels))  # get array of floats from 0 to 1

      # Add +/- self.noiseLevel to each pixel
      noise = (noise - 0.5) * 2 * self.noiseLevel * 255
      mask = numpy.array(alpha.getdata(), dtype=int) != self.background
      if self.doForeground and self.doBackground:
        pixels += noise
      elif self.doForeground:
        pixels[mask!=0] += noise[mask!=0]
      elif self.doBackground:
        pixels[mask==0] += noise[mask==0]
      pixels = pixels.clip(min=0, max=255)

    else:
      raise ValueError("This image mode not supported")

    # write out the new pixels
    #from dbgp.client import brk; brk(port=9049)
    newimage = Image.new(image.mode, image.size)

    #newimage.putdata([uint(p) for p in pixels])
    newimage.putdata(pixels.tolist())
    newimage.putalpha(alpha)

    # If generating dynamic noise, change our random state each time.
    if self.dynamic:
      self._randomState = numpy.random.get_state()

    # Restore random state
    numpy.random.set_state(saveState)

    return newimage
Пример #45
0
      def process(self, image):
        """
        Performs the following operations:
        1. Locates the original bounding box of the image as defined by the
           image's alpha mask.  It is assumed that the alpha mask will consist
           of a single rectangular, in which case the resulting bbox will
           be exactly equivalent to the mask representation.  However, if for
           some reason the positive regions of the alpha mask is not a single
           rectangle, things will still work.
        2. Fit the bounding box to the target dimensions, scaling as needed,
           and filling in padding regions if needed (if the aspect ratio of
           the bounding box does not match that of the target dimensions
           which, in general, will be True.)  If padding is needed, we fill
           from the original image pixels around the bounding box if
           fillFromImageWherePossible is True and we're not outside the original
           image bounds, otherwise, we use 'fillValue'.
        3. Apply each scale in 'scales' to the resulting cropped image, and
           pad each side by 'padding' (pulling from the real image pixels
           when possible, and filling with 'fillValue' where not.)
        4. Return the list of cropped images.
        """

        BaseFilter.process(self, image)

        assert image.mode == "LA"

        # Pull bbox of the alpha mask
        if 'tracking' in image.info:
          bbox = image.info['tracking']
        else:
          bbox = image.split()[1].getbbox()
        # If alpha channel is completely empty, we will end up
        # with a bbox of 'None'.  Nothing much we can do
        if bbox is None:
          bbox = (0, 0, image.size[0], image.size[1])
          print 'WARNING: empty alpha channel'

        # Ascertain the original raw size of the tracking box
        width  = bbox[2] - bbox[0]
        height = bbox[3] - bbox[1]

        newImages = []
        for scaleIdx, scale in enumerate(self._scales):

          # Target dimensions depend on the scale at which we're operating
          targetDims = (self._targetDims[0] * scale,
                        self._targetDims[1] * scale)

          scaleFactorX = float(targetDims[0]) / float(width)
          scaleFactorY = float(targetDims[1]) / float(height)

          # Determine the scaling factors needed to map the
          # bounding box to the target dimensions (prior to
          # padding be accounted for)
          if self._preservationMode is None:
            pass
          elif self._preservationMode == "aspect":
            scaleFactor = min(scaleFactorX, scaleFactorY)
            scaleFactorX = scaleFactor
            scaleFactorY = scaleFactor
          else:
            assert self._preservationMode == "size"
            scaleFactorX = scale
            scaleFactorY = scale

          # Now, holding the scaling factor constant, compute the
          # size of the src box in the original image that will
          # produce the correctly padded target size
          targetWidth  = int(round(targetDims[0])) + 2*self._padding
          targetHeight = int(round(targetDims[1])) + 2*self._padding
          srcWidth  = float(targetWidth)  / scaleFactorX
          srcHeight = float(targetHeight) / scaleFactorY

          # Compute the exact coordinates of the source box
          if self._fillFromImageWherePossible:
            origCenterX = float(bbox[0] + bbox[2]) * 0.5
            origCenterY = float(bbox[1] + bbox[3]) * 0.5
            halfWidth  = srcWidth  * 0.5
            halfHeight = srcHeight * 0.5
            srcBox = (int(round(origCenterX - halfWidth)),
                      int(round(origCenterY - halfHeight)),
                      int(round(origCenterX + halfWidth)),
                      int(round(origCenterY + halfHeight)))

            # take into account clipping off the image boundary
            clipBox = (max(srcBox[0], 0),
                       max(srcBox[1], 0),
                       min(srcBox[2], image.size[0]),
                       min(srcBox[3], image.size[1]))
            clipOffset = (clipBox[0] - srcBox[0],
                          clipBox[1] - srcBox[1])

          else:
            # extend the bbox to include padding pixels on all sides
            paddedBBox = (int(bbox[0] - self._padding/scaleFactorX),
                          int(bbox[1] - self._padding/scaleFactorY),
                          int(bbox[2] + self._padding/scaleFactorX),
                          int(bbox[3] + self._padding/scaleFactorY))

            # take into account clipping off the image boundary
            clipBox = (max(paddedBBox[0], 0),
                       max(paddedBBox[1], 0),
                       min(paddedBBox[2], image.size[0]),
                       min(paddedBBox[3], image.size[1]))

            # The srcBox is the correct aspect ratio, and either taller or wider than the
            # bbox, but not both.
            srcBox = (0, 0, srcWidth, srcHeight)
            clipBoxWidth = clipBox[2] - clipBox[0]
            clipBoxHeight = clipBox[3] - clipBox[1]
            clipOffset = (int((srcWidth - clipBoxWidth)/2),
                          int((srcHeight - clipBoxHeight)/2))


          # Copy the source rect
          croppedImage = image.crop(clipBox)
          croppedImage.load()

          # New development
          croppedImage.putalpha(Image.new(mode='L', size=croppedImage.size, color=255))

          if self._fillValue is None:
            [gray, alpha] = image.split()
            hist = numpy.array(gray.histogram(alpha), dtype='float')
            mean = (hist * self._histWeights).sum() / hist.sum()
            if mean < 127.5:
              fillValue = 255
            else:
              fillValue = 0
          else:
            fillValue = self._fillValue

          # Paste into a new image
          newImage = Image.new(mode='LA', size=(srcBox[2]-srcBox[0],
                                               srcBox[3]-srcBox[1]), color=fillValue)
          newImage.paste(croppedImage, clipOffset)

          # Resize the cropped image to the (padded) target size
          scaledImage = newImage.resize((targetWidth, targetHeight), self._resizingFilter)

          # Convert and save the scaled image as the output
          assert scaledImage.mode == 'LA'
          newImages += [scaledImage]

          # Dump debugging images to disk
          if self._dumpDebugImages:
            self._handleDebug(scaledImage, scaleIdx)

        return [newImages]
Пример #46
0
        def process(self, image):
            """
        Performs the following operations:
        1. Locates the original bounding box of the image as defined by the
           image's alpha mask.  It is assumed that the alpha mask will consist
           of a single rectangular, in which case the resulting bbox will
           be exactly equivalent to the mask representation.  However, if for
           some reason the positive regions of the alpha mask is not a single
           rectangle, things will still work.
        2. Fit the bounding box to the target dimensions, scaling as needed,
           and filling in padding regions if needed (if the aspect ratio of
           the bounding box does not match that of the target dimensions
           which, in general, will be True.)  If padding is needed, we fill
           from the original image pixels around the bounding box if
           fillFromImageWherePossible is True and we're not outside the original
           image bounds, otherwise, we use 'fillValue'.
        3. Apply each scale in 'scales' to the resulting cropped image, and
           pad each side by 'padding' (pulling from the real image pixels
           when possible, and filling with 'fillValue' where not.)
        4. Return the list of cropped images.
        """

            BaseFilter.process(self, image)

            assert image.mode == "LA"

            # Pull bbox of the alpha mask
            if 'tracking' in image.info:
                bbox = image.info['tracking']
            else:
                bbox = image.split()[1].getbbox()
            # If alpha channel is completely empty, we will end up
            # with a bbox of 'None'.  Nothing much we can do
            if bbox is None:
                bbox = (0, 0, image.size[0], image.size[1])
                print 'WARNING: empty alpha channel'

            # Ascertain the original raw size of the tracking box
            width = bbox[2] - bbox[0]
            height = bbox[3] - bbox[1]

            newImages = []
            for scaleIdx, scale in enumerate(self._scales):

                # Target dimensions depend on the scale at which we're operating
                targetDims = (self._targetDims[0] * scale,
                              self._targetDims[1] * scale)

                scaleFactorX = float(targetDims[0]) / float(width)
                scaleFactorY = float(targetDims[1]) / float(height)

                # Determine the scaling factors needed to map the
                # bounding box to the target dimensions (prior to
                # padding be accounted for)
                if self._preservationMode is None:
                    pass
                elif self._preservationMode == "aspect":
                    scaleFactor = min(scaleFactorX, scaleFactorY)
                    scaleFactorX = scaleFactor
                    scaleFactorY = scaleFactor
                else:
                    assert self._preservationMode == "size"
                    scaleFactorX = scale
                    scaleFactorY = scale

                # Now, holding the scaling factor constant, compute the
                # size of the src box in the original image that will
                # produce the correctly padded target size
                targetWidth = int(round(targetDims[0])) + 2 * self._padding
                targetHeight = int(round(targetDims[1])) + 2 * self._padding
                srcWidth = float(targetWidth) / scaleFactorX
                srcHeight = float(targetHeight) / scaleFactorY

                # Compute the exact coordinates of the source box
                if self._fillFromImageWherePossible:
                    origCenterX = float(bbox[0] + bbox[2]) * 0.5
                    origCenterY = float(bbox[1] + bbox[3]) * 0.5
                    halfWidth = srcWidth * 0.5
                    halfHeight = srcHeight * 0.5
                    srcBox = (int(round(origCenterX - halfWidth)),
                              int(round(origCenterY - halfHeight)),
                              int(round(origCenterX + halfWidth)),
                              int(round(origCenterY + halfHeight)))

                    # take into account clipping off the image boundary
                    clipBox = (max(srcBox[0], 0), max(srcBox[1], 0),
                               min(srcBox[2],
                                   image.size[0]), min(srcBox[3],
                                                       image.size[1]))
                    clipOffset = (clipBox[0] - srcBox[0],
                                  clipBox[1] - srcBox[1])

                else:
                    # extend the bbox to include padding pixels on all sides
                    paddedBBox = (int(bbox[0] - self._padding / scaleFactorX),
                                  int(bbox[1] - self._padding / scaleFactorY),
                                  int(bbox[2] + self._padding / scaleFactorX),
                                  int(bbox[3] + self._padding / scaleFactorY))

                    # take into account clipping off the image boundary
                    clipBox = (max(paddedBBox[0], 0), max(paddedBBox[1], 0),
                               min(paddedBBox[2], image.size[0]),
                               min(paddedBBox[3], image.size[1]))

                    # The srcBox is the correct aspect ratio, and either taller or wider than the
                    # bbox, but not both.
                    srcBox = (0, 0, srcWidth, srcHeight)
                    clipBoxWidth = clipBox[2] - clipBox[0]
                    clipBoxHeight = clipBox[3] - clipBox[1]
                    clipOffset = (int((srcWidth - clipBoxWidth) / 2),
                                  int((srcHeight - clipBoxHeight) / 2))

                # Copy the source rect
                croppedImage = image.crop(clipBox)
                croppedImage.load()

                # New development
                croppedImage.putalpha(
                    Image.new(mode='L', size=croppedImage.size, color=255))

                if self._fillValue is None:
                    [gray, alpha] = image.split()
                    hist = numpy.array(gray.histogram(alpha), dtype='float')
                    mean = (hist * self._histWeights).sum() / hist.sum()
                    if mean < 127.5:
                        fillValue = 255
                    else:
                        fillValue = 0
                else:
                    fillValue = self._fillValue

                # Paste into a new image
                newImage = Image.new(mode='LA',
                                     size=(srcBox[2] - srcBox[0],
                                           srcBox[3] - srcBox[1]),
                                     color=fillValue)
                newImage.paste(croppedImage, clipOffset)

                # Resize the cropped image to the (padded) target size
                scaledImage = newImage.resize((targetWidth, targetHeight),
                                              self._resizingFilter)

                # Convert and save the scaled image as the output
                assert scaledImage.mode == 'LA'
                newImages += [scaledImage]

                # Dump debugging images to disk
                if self._dumpDebugImages:
                    self._handleDebug(scaledImage, scaleIdx)

            return [newImages]
Пример #47
0
    def process(self, image):
        """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

        BaseFilter.process(self, image)

        # If no background image, just return the input image as-is
        if self.bgPath is None:
            return image

        # ---------------------------------------------------------------------------
        # Open the background image(s) if we haven't done so already
        if self.bgImgs is None:

            # If given a relative path, make it relative to the vision data directory
            if not os.path.isabs(self.bgPath):
                basePath = os.path.abspath(os.curdir)
                basePath = os.path.split(basePath)
                while (basePath[0]):
                    if basePath[1] == 'vision':
                        break
                    basePath = os.path.split(basePath[0])

                # Did we find the vision directory?
                if basePath[1] == 'vision':
                    fullPath = VisionUtils.findData(
                        os.path.join(basePath[0], 'vision'), self.bgPath,
                        'backgound', 'background images', True)
                    #basePath = os.path.join(basePath[0], 'vision', 'data')
                else:
                    fullPath = self.bgPath
            else:
                fullPath = self.bgPath

            # If given a filename, we only have 1 image
            if os.path.isfile(fullPath):
                self.bgImgs = [Image.open(fullPath).convert('LA')]

            # Else, open up all images in this directory
            else:
                self.bgImgs = []
                w = os.walk(fullPath)
                while True:
                    try:
                        dirpath, dirnames, filenames = w.next()
                    except StopIteration:
                        break

                    # Don't enter directories that begin with '.'
                    for d in dirnames[:]:
                        if d.startswith('.'):
                            dirnames.remove(d)
                    dirnames.sort()

                    # Ignore files that begin with '.'
                    filenames = [f for f in filenames if not f.startswith('.')]
                    filenames.sort()
                    imageFilenames = [
                        os.path.join(dirpath, f) for f in filenames
                    ]

                    # Process each image
                    for filename in imageFilenames:
                        self.bgImgs.append(Image.open(filename).convert('L'))

            # Keep a cache of all images, scaled to the input image size
            self.scaledBGImgs = [x.copy() for x in self.bgImgs]

        # Pick a background at random.
        idx = self._rng.randint(0, len(self.bgImgs) - 1)
        bgImg = self.scaledBGImgs[idx]

        # ---------------------------------------------------------------------------
        # re-scale the background to the source image if necessary
        if bgImg.size != image.size:
            bgImg = self.scaledBGImgs[idx] = self.bgImgs[idx].resize(
                image.size, Image.ANTIALIAS)

        # ---------------------------------------------------------------------------
        # Create the mask around the source image
        mask = image.split()[-1]
        if image.mode[-1] != 'A' or isSimpleBBox(mask):
            mask = createMask(image,
                              threshold=self._threshold,
                              fillHoles=True,
                              backgroundColor=self.background,
                              blurRadius=self._blurRadius,
                              maskScale=self._maskScale)

        # ---------------------------------------------------------------------------
        # Paste the image onto the background
        newImage = bgImg.copy()
        newImage.paste(image, (0, 0), mask)

        # Put an "all-on" alpha channel because we now want the network to consider the entire
        #  image
        newImage.putalpha(ImageChops.constant(newImage, 255))

        return newImage
Пример #48
0
  def process(self, image):
    """
    @param image -- The image to process.

    Returns a single image, or a list containing one or more images.
    """

    BaseFilter.process(self, image)

    sizes = []
    for i, size in enumerate(self.sizes):
      if len(size) == 1:
        # Convert scalar sizes to absolute sizes in pixels
        sizes.append((int(round(image.size[0]*float(size[0]))),
                      int(round(image.size[1]*float(size[0])))))
      else:
        sizes.append((int(size[0]), int(size[1])))

    newImages = []
    for size in sizes:
      if image.size == size:
        newImage = image

      elif self.method == 'fit':
        # Resize the image to fit in the target size, preserving aspect ratio
        targetRatio = size[0] / float(size[1])
        imageRatio = image.size[0] / float(image.size[1])
        if imageRatio > targetRatio:
          xSize = size[0]
          scale = size[0] / float(image.size[0])
          ySize = int(scale * image.size[1])
        else:
          ySize = size[1]
          scale = size[1] / float(image.size[1])
          xSize = int(scale * image.size[0])
        newImage = self._resize(image, (xSize, ySize))
        # Pad with the background color if necessary
        if newImage.size != size:
          paddedImage = Image.new('LA', size, self.background)
          paddedImage.paste(newImage,
                           ((size[0] - newImage.size[0])/2,
                            (size[1] - newImage.size[1])/2))
          newImage = paddedImage

      elif self.method == 'crop':
        # Resize the image to fill the new size
        targetRatio = size[0] / float(size[1])
        imageRatio = image.size[0] / float(image.size[1])
        if imageRatio > targetRatio:
          # Original image is too wide
          scale = size[1] / float(image.size[1])
          newSize = (int(scale * image.size[0]), size[1])
          cropStart = ((newSize[0] - size[0]) / 2, 0)
        else:
          # Original image is too tall
          scale = size[0] / float(image.size[0])
          newSize = (size[0], int(scale * image.size[1]))
          cropStart = (0, (newSize[1] - size[1]) / 2)

        newImage = self._resize(image, newSize)
        # Crop if necessary
        if newSize != size:
          newImage = newImage.crop((cropStart[0], cropStart[1],
            cropStart[0] + size[0], cropStart[1] + size[1]))

      elif self.method == 'stretch':
        # Resize the image to each target size, ignoring aspect ratio
        newImage = self._resize(image, size)

      elif self.method == 'center':
        # Center the original image in the new image without rescaling it
        newImage = Image.new('LA', size, self.background)
        x = (size[0] - image.size[0]) / 2
        y = (size[1] - image.size[1]) / 2
        newImage.paste(image, (x, y))

      newImages.append(newImage)

    if not self.simultaneous:
      if len(newImages) == 1:
        return newImages[0]
      else:
        return newImages
    else:
      return [newImages]