Exemple #1
0
    def process(self, image):
    """
    Args:
        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
Exemple #2
0
    def process(self, image):
    """
    Args:
        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)
Exemple #3
0
    def process(self, image):
    """
    Args:
        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 range(self.level):
        sharpness_enhancer = ImageEnhance.Sharpness(image.split()[0])
        image = sharpness_enhancer.enhance(0.0)
    image.putalpha(mask)
    return image
Exemple #4
0
    def process(self, image):
    """
    Args:
        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(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
Exemple #5
0
    def process(self, image):
    """
    Args:
        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
Exemple #6
0
    def process(self, image):
        """
        TODO check bounding box
        """
        BaseFilter.process(self, image)

        image = image.convert('LA')

        matrix = [1, 0, self.x_axis, 0, 1, self.y_axis, 0, 0, 1]
        translated_image = image.transform(image.size, Image.AFFINE, matrix)

        # Create a new larger image to hold the translated image
        # It is filled with the background color and an alpha value of 0
        outputImage = Image.new('LA', translated_image.size, (self.background, 0))

        # Paste the translated image into the new image, using the 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 translated image
        outputImage.paste(translated_image, None, translated_image.split()[1])
        outputImage = outputImage.convert('L')

        return outputImage
Exemple #7
0
    def process(self, image):
        """
        TODO check bounding box
        """
        BaseFilter.process(self, image)

        image = image.convert("LA")

        matrix = [1, 0, self.x_axis, 0, 1, self.y_axis, 0, 0, 1]
        translated_image = image.transform(image.size, Image.AFFINE, matrix)

        # Create a new larger image to hold the translated image
        # It is filled with the background color and an alpha value of 0
        outputImage = Image.new("LA", translated_image.size, (self.background, 0))

        # Paste the translated image into the new image, using the 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 translated image
        outputImage.paste(translated_image, None, translated_image.split()[1])
        outputImage = outputImage.convert("L")

        return outputImage
Exemple #8
0
    def process(self, image):
    """
    Args:
        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]

    def getOutputCount(self):
    """Return the number of images returned by each call to process().

    If the filter creates multiple simultaneous outputs, return a tuple:
    (outputCount, simultaneousOutputCount).
    """

    if not self.simultaneous:
        return len(self.sizes)
    else:
        return 1, len(self.sizes)

    def _resize(self, image, size):
    """Resize the image with the appropriate sampling method.
    """
    if self.highQuality:
        if size < image.size:
            return image.resize(size, Image.ANTIALIAS)
        else:
            return image.resize(size, Image.BICUBIC)
    else:
        return image.resize(size)
Exemple #9
0
    def process(self, image):
    """
    Args:
        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.
        pixels = numpy.array(image.split()[0].getdata(), dtype=int)

        noise = numpy.random.random(len(pixels))  # get array of floats from 0 to 1

        if self.doForeground and self.doBackground:
            noise = numpy.array(noise < self.noiseLevel, dtype=int) * 255
            pixels -= noise
            pixels = numpy.abs(pixels)

        else:
            # "Flip" self.noiseLevel percent of the foreground pixels
            # We only want to add noise to the figure, so we will flip some percent of the
            #  0 pixels.
            if self.doForeground:
                noise = numpy.array(noise < self.noiseLevel, dtype=int) * 255
                pixels |= noise

            # "Flip" self.noiseLevel percent of the background pixels
            # We only want to add noise to the background, so we will flip some percent of the
            #  255 pixels.
            if self.doBackground:
                noise = numpy.array(noise > self.noiseLevel, dtype=int) * 255
                pixels &= noise

    # -----------------------------------------------------------------------
    # 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 * 256
        mask = numpy.array(alpha.getdata(), dtype=int) != 0
        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 "AddNoise Filter: this image mode not supported"

    # write out the new pixels
    newimage = Image.new(image.mode, image.size)
    newimage.putdata(pixels)
    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
Exemple #10
0
    def process(self, image):
    """
    Args:
        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

        image = image.convert('LA')
        # 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.convert('L'))

    return outputs

    def getOutputCount(self):
    """
    Return the number of images returned by each call to process().

    If the filter creates multiple simultaneous outputs, return a tuple:
    (outputCount, simultaneousOutputCount).
    """
    return len(self.angles)