Пример #1
0
    def __init__(self, image_path: str, destination_path: str, factor: int):
        self.min_factor = 0
        self.max_factor = int(get_greyscale(
            255, 255, 255))  # max greyscale valaue for #FFFFFF

        if not self.min_factor < factor < self.max_factor:
            raise ValueError(
                f"Factor value should be from 0 to {self.max_factor}")

        self.image = Image(image_path)
        self.factor = factor

        self.destination_path = destination_path

        #  raw error table and output image
        self.width, self.height = self.image.get_size()
        self.greyscale_image = self.image2greyscale()
        # error size + 1 than input image because of lack of if statements
        self.error_table = [[0 for _ in range(self.height + 2)]
                            for __ in range(self.width + 2)]

        self.output_image = PillowImage.new("RGB", (self.width, self.height),
                                            self.WHITE)
        self.output_pixels = self.output_image.load()
        self.output_image_name = "output_floyd_steinberg.jpg"
Пример #2
0
    def __init__(self,
                 image_path: str,
                 destination_path: str,
                 min_blur: float,
                 max_blur: float,
                 sharpen_area_size: List = None):

        self.image_path = image_path
        self.destination_path = destination_path
        self.input_image = Image(self.image_path)
        self.pixels = self.input_image.pixels

        if not sharpen_area_size:
            sharpen_area_size = [0, 0]

        self.sharpen_min_h, self.sharpen_max_h = sharpen_area_size[
            0], sharpen_area_size[1]
        self.sharpen_size = self.sharpen_max_h - self.sharpen_min_h
        self.sharpen_center = self.sharpen_min_h + self.sharpen_size // 2

        self.filter_elements = []

        self.min_factor = 0.003
        self.max_factor = 0.003

        self.min_blur = min_blur
        self.max_blur = max_blur
Пример #3
0
def make_negative(image_path: str, dest_path: str):
    image = Image(image_path)
    width, height = image.get_size()
    output = create_empty_image(width, height)
    output_pixels = output.load()
    for x in range(width):
        for y in range(height):
            red, green, blue = image.pixels[x, y]
            output_pixels[x, y] = (255 - red, 255 - green, 255 - blue)

    output.save(dest_path)
Пример #4
0
def make_sepia(image_path: str, dest_path: str, factor: int):
    image = Image(image_path)
    width, height = image.get_size()
    output = create_empty_image(width, height)
    output_pixels = output.load()
    for x in range(width):
        for y in range(height):
            red, green, blue = image.pixels[x, y]
            grey_red = int(get_greyscale(red, green, blue))
            grey_green = int(get_greyscale(red, green, blue))
            grey_blue = int(get_greyscale(red, green, blue))

            output_pixels[x, y] = (grey_red + 2 * factor, grey_green + factor,
                                   grey_blue)

    output.save(dest_path)
Пример #5
0
class FloydSteinberg:
    """
    Floyd Stainberg algorithm using for reducng grayscale image to black and white.
    Source: https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering
    """

    BLACK = "#000000"
    WHITE = "#FFFFFF"

    def __init__(self, image_path: str, destination_path: str, factor: int):
        self.min_factor = 0
        self.max_factor = int(get_greyscale(255, 255, 255))  # max greyscale vlaue for #FFFFFF

        if not self.min_factor < factor < self.max_factor:
            raise ValueError(f"Factor value should be from 0 to {self.max_factor}")

        self.image = Image(image_path)
        self.factor = factor

        self.destination_path = destination_path

        #  raw error table and output image
        self.width, self.height = self.image.get_size()
        self.greyscale_image = self.image2greyscale()
        # error size + 1 than input image because of lack of if statements
        self.error_table = [[0 for _ in range(self.height + 2)] for __ in range(self.width + 2)]

        self.output_image = PillowImage.new("RGB", (self.width, self.height), self.WHITE)
        self.output_pixels = self.output_image.load()
        self.output_image_name = "output_floyd_steinberg.jpg"

    def image2greyscale(self):
        greyscale_image = PillowImage.new("RGB", (self.width, self.height), self.WHITE)
        pixels = greyscale_image.load()

        for x in range(self.width):
            for y in range(self.height):
                grey_value = int(get_greyscale(*self.image.pixels[x, y]))
                pixels[x, y] = (grey_value, grey_value, grey_value)

        greyscale_image.save(os.path.join(self.destination_path, "output_greyscale.jpg"))
        return greyscale_image

    def process(self):
        input_pixels = self.greyscale_image.load()

        for x in range(self.width):
            for y in range(self.height):
                if self.factor > input_pixels[x, y][0] + self.error_table[x][y]:
                    self.output_pixels[x, y] = (0, 0, 0)
                    current_error = input_pixels[x, y][0] + self.error_table[x][y]
                else:
                    self.output_pixels[x, y] = (255, 255, 255)
                    current_error = input_pixels[x, y][0] + self.error_table[x][y] - 255

                # error propagation
                self._propagate_error(x, y, current_error)

        self.output_image.save(os.path.join(self.destination_path, self.output_image_name))

    def _propagate_error(self, x, y, current_error):
        self.error_table[x + 1][y] += + 7 / 16 * current_error
        self.error_table[x + 1][y + 1] += 3 / 16 * current_error
        self.error_table[x][y + 1] += 5 / 16 * current_error
        self.error_table[x - 1][y + 1] += 1 / 16 * current_error
Пример #6
0
 def __init__(self, image_path: str, scale: float):
     self.image = Image(image_path)
     self.scale = scale
     self.new_image = None
Пример #7
0
class TiltShift:
    """ Tilt-shift technique """
    def __init__(self,
                 image_path: str,
                 destination_path: str,
                 min_blur: float,
                 max_blur: float,
                 sharpen_area_size: List = None):

        self.image_path = image_path
        self.destination_path = destination_path
        self.input_image = Image(self.image_path)
        self.pixels = self.input_image.pixels

        if not sharpen_area_size:
            sharpen_area_size = [0, 0]

        self.sharpen_min_h, self.sharpen_max_h = sharpen_area_size[
            0], sharpen_area_size[1]
        self.sharpen_size = self.sharpen_max_h - self.sharpen_min_h
        self.sharpen_center = self.sharpen_min_h + self.sharpen_size // 2

        self.filter_elements = []

        self.min_factor = 0.003
        self.max_factor = 0.003

        self.min_blur = min_blur
        self.max_blur = max_blur

    @classmethod
    def _make_filter_factor(cls, blur: float, index: int):
        return (1 / (sqrt(2 * pi) * blur)) * exp(-pow(index, 2) /
                                                 (2 * pow(blur, 2)))

    def _make_blur(self, distance: int, sharp_area_size: int):
        """
        :param distance: distance between point and sharp area
        :param sharp_area_size: sharp area size height/width
        :return: blur value
        """
        return abs(self.min_blur + (self.max_blur - self.min_blur) * distance /
                   sharp_area_size)

    def generate_filter_elements(self, blur: float, max_factor: int):
        self.filter_elements = list(
            itertools.takewhile(
                self.is_gt_min_factor,
                [self._make_filter_factor(blur, i)
                 for i in range(max_factor)]))

    def is_gt_min_factor(self, value: float):
        return value >= self.min_factor

    def process(self):
        width, height = self.input_image.get_size()
        output = create_empty_image(width, height)
        output_pixels = output.load()

        for x in range(width):
            for y in range(height):

                if self.sharpen_min_h < y < self.sharpen_max_h:
                    output_pixels[x, y] = self.pixels[x, y]
                    continue

                blur = self._make_blur(self.sharpen_center - y,
                                       self.sharpen_size)
                self.generate_filter_elements(blur, 7)
                red = self.process_horizontal(0, x, y, width - 1)
                green = self.process_horizontal(1, x, y, width - 1)
                blue = self.process_horizontal(2, x, y, width - 1)
                output_pixels[x, y] = (red, green, blue)

        for x in range(width):
            for y in range(height):
                if self.sharpen_min_h < y < self.sharpen_max_h:
                    output_pixels[x, y] = self.pixels[x, y]
                    continue

                blur = self._make_blur(self.sharpen_center - y,
                                       self.sharpen_size)
                self.generate_filter_elements(blur, 7)
                red = self.process_vertical(0, x, y, height - 1)
                green = self.process_vertical(1, x, y, height - 1)
                blue = self.process_vertical(2, x, y, height - 1)
                output_pixels[x, y] = (red, green, blue)

        output.save(
            os.path.join(self.destination_path, 'output_tilt_shift.jpg'))

    def process_horizontal(self, index, x, y, max_value):
        num = self.filter_elements[0] * self.pixels[x, y][index]
        denum = self.filter_elements[0]

        for i, value in enumerate(self.filter_elements[1:]):
            num += value * self.pixels[abs(x - i), y][
                index] + value * self.pixels[min(x + 1, max_value), y][index]
            denum += 2 * value

        return int(num / denum)

    def process_vertical(self, index, x, y, max_index):
        num = self.filter_elements[0] * self.pixels[x, y][index]
        denum = self.filter_elements[0]

        for i, value in enumerate(self.filter_elements[1:]):
            num += value * self.pixels[x, abs(y - i)][
                index] + value * self.pixels[x, min(y + i, max_index)][index]
            denum += 2 * value

        return int(num / denum)