Esempio n. 1
0
    def __init__(self, box):
    """
    Args:
        box: 4-tuple specifying the left, top, right, and bottom coords.
    """
    BaseFilter.__init__(self)

    if box[2] <= box[0] or box[3] <= box[1]:
        raise RuntimeError('Specified box has zero width or height')

    self.box = box

    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)
Esempio n. 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)

    # 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
Esempio n. 3
0
    def __init__(self, level=1):
    """
    Args:
        level: Number of times to blur.
    """
    BaseFilter.__init__(self)

    self.level = level

    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
Esempio n. 4
0
    def __init__(self, value=None, threshold=10, maskScale=1.0, blurRadius=0.0):
    """
    Args:
        value: If None, the background is filled in with the background color.
               Otherwise, it is filled with value. If value is a list, then
               this filter will return multiple images, one for each value
    """
    BaseFilter.__init__(self)

    if hasattr(value, '__len__'):
        self._values = value
    else:
        self._values = [value]
    self._threshold = threshold
    self._maskScale = maskScale
    self._blurRadius = blurRadius

    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._values)

    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
Esempio n. 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.box[2] > image.size[0] or self.box[3] > image.size[1]:
        raise RuntimeError('Crop coordinates exceed image bounds')

    return image.crop(self.box)
Esempio n. 6
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
Esempio n. 7
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
Esempio n. 8
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
Esempio n. 9
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
Esempio n. 10
0
    def __init__(self, region='all', mode=None):
    """
    Args:
        region: Options are 'all' (equalize the entire image), 'bbox'
      (equalize just the portion of the image within the bounding box), and
      'mask' (equalize just the portion of the image within the mask).
      mode: ** DEPRECATED ** Alias for 'region'.
    """
    BaseFilter.__init__(self)

    if mode is not None:
        region = mode

    if region not in ('all', 'bbox', 'mask'):
        raise RuntimeError("Not a supported region (options are 'all', 'bbox', and 'mask')")

    self.region = region

    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
Esempio n. 11
0
    def __init__(self, x_axis=0, y_axis=0):

        BaseFilter.__init__(self)

        self.x_axis = x_axis  # horizontal
        self.y_axis = y_axis  # vertical
Esempio n. 12
0
    def __init__(self, size=None, sizes=None, method='fit', simultaneous=False,
                 highQuality=False):
    """
    Args:
        size: Target size. Either a tuple (width, height), specifying an
              absolute size in pixels, or a single value, specifying a scale
              factor to apply to the current size.
        sizes: List of target sizes, for creating multiple output images
               for each input image. Each entry in the list must satisfy the
               requirements for the 'size' parameter, above. 'size' and 'sizes'
               may not be used together.
      method: Method to use for generating new images, one of:
      'fit'     : scale and pad to match new size, preserving aspect ratio
      'crop'    : scale and crop the image to fill the new size
      'stretch' : stretch the image to fill new size, ignoring aspect ratio
      'center'  : center the original image in the new size without scaling
      simultaneous: Whether the images should be sent out of the sensor
                    simultaneously.
      highQuality: Whether to use high-quality sampling for resizing instead of
                   nearest neighbor. If highQuality is True, antialiasing is
                   used for downsampling and bicubic interpolation is used for
                   upsampling.

    Example usage:

    Resize the incoming image to fit within (320, 240) by scaling so that
    the image fits exactly within (320, 240) but the aspect ratio is
    maintained, and padding with the sensor's background color:
      Resize(size=(320, 240))

    Scale the image to three different sizes: 100% of the original size,
    50% of the original size, and 25% of the original size, and send the
    three images out of the sensor simultaneously as multiple scales:
      Resize(sizes=(1.0, 0.5, 0.25), simultaneous=True)

    Pad the image to fit in a larger image of size (640, 480), centering it
    in the new image:
      Resize(size=(640, 480), method='center')
    """
    BaseFilter.__init__(self)

    if (not size and not sizes) or (size and sizes):
        raise RuntimeError("Must specify either 'size' or 'sizes'")

    if size:
        sizes = [size]

    if type(sizes) not in (list, tuple):
        raise ValueError("Sizes must be a list or tuple")

    if type(sizes) is tuple:
        sizes = list(sizes)

    for i, size in enumerate(sizes):
        if type(size) in (list, tuple):
            if len(size) > 2:
                raise ValueError("Size is too long (must be a scalar or 2-tuple)")
        elif type(size) in (int, float):
            if size <= 0:
                raise ValueError("Sizes must be positive numbers")
            sizes[i] = [size]
        else:
            raise TypeError("Sizes must be positive numbers")

    if method not in ('fit', 'crop', 'stretch', 'center'):
        raise ValueError("Unknown method "
                         "(options are 'fit', 'crop', 'stretch', and 'center')")

    self.sizes = sizes
    self.method = method
    self.simultaneous = simultaneous
    self.highQuality = highQuality

    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)
Esempio n. 13
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)
Esempio n. 14
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)
Esempio n. 15
0
    def __init__(self, region='all', cutoff=0):
    """
    Args:
        region: Options are 'all' (equalize the entire image), 'bbox'
                (equalize just the portion of the image within the bounding
                box), and 'mask' (equalize just the portion of the image within
                the mask)
        cutoff: Number of pixels to clip from each end of the histogram
                before rescaling it
    """
    BaseFilter.__init__(self)

    if region not in ('all', 'bbox', 'mask'):
        raise RuntimeError("Not a supported region (options are 'all', 'bbox', and 'mask')")
    if type(cutoff) != int or cutoff < 0:
        raise RuntimeError("'cutoff' must be a positive integer")

    self.region = region
    self.cutoff = cutoff

    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
Esempio n. 16
0
    def __init__(self, x_axis=0, y_axis=0):

        BaseFilter.__init__(self)

        self.x_axis = x_axis  # horizontal
        self.y_axis = y_axis  # vertical
Esempio n. 17
0
    def __init__(self, angles=[0], expand=False, targetRatio=None,
                 highQuality=True):
    """
    Args:
        angles: List of angles by which to rotate, in degrees.
        expand: Whether to expand the output image to contain the entire
                rotated image. If False, the output image will match the
                dimensions of the input image, but cropping may occur.
        targetRatio: Ratio of the sensor. If specified, used if expand == False
                     to grow the image to the target ratio to avoid unnecessary
                     clipping.
        highQuality: Whether to use bicubic interpolation for rotating.
                     instead of nearest neighbor.
    """
    BaseFilter.__init__(self)

    self.angles = angles
    self.expand = expand
    self.targetRatio = targetRatio
    self.highQuality = highQuality
    if not expand:
        for i, angle in enumerate(angles):
            if angle != 0 and angle % 90 == 0:
                angles[i] -= .01  # Oh, PIL...

    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)
Esempio n. 18
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