From cada48ba603f140b8fb1873bc41c7129911aafa6 Mon Sep 17 00:00:00 2001 From: ElizavetaUv <75488565+ElizavetaUv@users.noreply.github.com> Date: Sun, 14 Nov 2021 15:26:36 +0500 Subject: [PATCH 1/5] refactoring + add gitignore and requiremtns. 0 stage --- .gitignore | 1 + 632.jpg => docs/examples/632.jpg | Bin compile.png => docs/examples/compile.png | Bin img-test.png => docs/examples/img-test.png | Bin img2.jpg => docs/examples/img2.jpg | Bin ...RG8s3SZQlQLnF8bhcnGu6AwzRA5aqi.png_4_1.png | Bin docs/examples/res.jpg | Bin 0 -> 65485 bytes filter.py | 77 ++++++++++++------ requirements.txt | 2 + 9 files changed, 53 insertions(+), 27 deletions(-) create mode 100644 .gitignore rename 632.jpg => docs/examples/632.jpg (100%) rename compile.png => docs/examples/compile.png (100%) rename img-test.png => docs/examples/img-test.png (100%) rename img2.jpg => docs/examples/img2.jpg (100%) rename m0oLR8Tx0zRG8s3SZQlQLnF8bhcnGu6AwzRA5aqi.png_4_1.png => docs/examples/m0oLR8Tx0zRG8s3SZQlQLnF8bhcnGu6AwzRA5aqi.png_4_1.png (100%) create mode 100644 docs/examples/res.jpg create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96403d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/* diff --git a/632.jpg b/docs/examples/632.jpg similarity index 100% rename from 632.jpg rename to docs/examples/632.jpg diff --git a/compile.png b/docs/examples/compile.png similarity index 100% rename from compile.png rename to docs/examples/compile.png diff --git a/img-test.png b/docs/examples/img-test.png similarity index 100% rename from img-test.png rename to docs/examples/img-test.png diff --git a/img2.jpg b/docs/examples/img2.jpg similarity index 100% rename from img2.jpg rename to docs/examples/img2.jpg diff --git a/m0oLR8Tx0zRG8s3SZQlQLnF8bhcnGu6AwzRA5aqi.png_4_1.png b/docs/examples/m0oLR8Tx0zRG8s3SZQlQLnF8bhcnGu6AwzRA5aqi.png_4_1.png similarity index 100% rename from m0oLR8Tx0zRG8s3SZQlQLnF8bhcnGu6AwzRA5aqi.png_4_1.png rename to docs/examples/m0oLR8Tx0zRG8s3SZQlQLnF8bhcnGu6AwzRA5aqi.png_4_1.png diff --git a/docs/examples/res.jpg b/docs/examples/res.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d8d97ffbcda90f190e9bf8b3376be16b3b9a1620 GIT binary patch literal 65485 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 literal 0 HcmV?d00001 diff --git a/filter.py b/filter.py index 4150df2..a378717 100644 --- a/filter.py +++ b/filter.py @@ -1,28 +1,51 @@ -from PIL import Image +from argparse import ArgumentParser, Namespace + import numpy as np -img = Image.open("img2.jpg") -arr = np.array(img) -a = len(arr) -a1 = len(arr[1]) -i = 0 -while i < a - 11: - j = 0 - while j < a1 - 11: - s = 0 - for n in range(i, i + 10): - for n1 in range(j, j + 10): - n1 = arr[n][n1][0] - n2 = arr[n][n1][1] - n3 = arr[n][n1][2] - M = n1 + n2 + n3 - s += M - s = int(s // 100) - for n in range(i, i + 10): - for n1 in range(j, j + 10): - arr[n][n1][0] = int(s // 50) * 50 - arr[n][n1][1] = int(s // 50) * 50 - arr[n][n1][2] = int(s // 50) * 50 - j = j + 10 - i = i + 10 -res = Image.fromarray(arr) -res.save('res.jpg') +from PIL import Image + + +def _create_pixel_art(input_image_path: str, output_image_path: str) -> None: + img = Image.open(input_image_path) + arr = np.array(img, dtype=np.uint8) + a = len(arr) + a1 = len(arr[0]) + i = 0 + + while i < a - 11: + j = 0 + while j < a1 - 11: + s = 0 + for n in range(i, i + 10): + for n1 in range(j, j + 10): + n1 = arr[n][n1][0] + n2 = arr[n][n1][1] + n3 = arr[n][n1][2] + M = n1 + n2 + n3 + s += M + s = int(s // 100) + for n in range(i, i + 10): + for n1 in range(j, j + 10): + arr[n][n1][0] = int(s // 50) * 50 + arr[n][n1][1] = int(s // 50) * 50 + arr[n][n1][2] = int(s // 50) * 50 + j = j + 10 + i = i + 10 + res = Image.fromarray(arr) + res.save(output_image_path) + + +def _parser() -> Namespace: + parser = ArgumentParser(description='Преобразование изображения в пиксель арт') + parser.add_argument('-i', '--input-image', default="./docs/examples/img2.jpg", help='Путь до ихображения которое вы хотите преобразовать') + parser.add_argument('-o', '--output-image', default='./docs/examples/res.jpg', help='Путь, куда вы хотите сохранить изображение') + return parser.parse_args() + + + +def main(): + args = _parser() + _create_pixel_art(args.input_image, args.output_image) + + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b66939e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +numpy==1.21.4 +Pillow==8.4.0 From da5c4b30024b206d8fc38303a7abaa82805b9631 Mon Sep 17 00:00:00 2001 From: ElizavetaUv <75488565+ElizavetaUv@users.noreply.github.com> Date: Sun, 14 Nov 2021 16:27:44 +0500 Subject: [PATCH 2/5] Repair algorithm. Stage 1 --- filter.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/filter.py b/filter.py index a378717..d94288a 100644 --- a/filter.py +++ b/filter.py @@ -11,18 +11,16 @@ def _create_pixel_art(input_image_path: str, output_image_path: str) -> None: a1 = len(arr[0]) i = 0 - while i < a - 11: + while i < a - 9: j = 0 - while j < a1 - 11: + while j < a1 - 9: s = 0 for n in range(i, i + 10): for n1 in range(j, j + 10): - n1 = arr[n][n1][0] - n2 = arr[n][n1][1] - n3 = arr[n][n1][2] - M = n1 + n2 + n3 + red, green, blue = arr[n][n1] + M = int(red) + int(green) + int(blue) s += M - s = int(s // 100) + s = int(s // 300) for n in range(i, i + 10): for n1 in range(j, j + 10): arr[n][n1][0] = int(s // 50) * 50 @@ -30,6 +28,7 @@ def _create_pixel_art(input_image_path: str, output_image_path: str) -> None: arr[n][n1][2] = int(s // 50) * 50 j = j + 10 i = i + 10 + print(arr.dtype) res = Image.fromarray(arr) res.save(output_image_path) From a283b5b40784dd056aaafba3c983ae11c543d8f4 Mon Sep 17 00:00:00 2001 From: ElizavetaUv <75488565+ElizavetaUv@users.noreply.github.com> Date: Sun, 14 Nov 2021 17:49:01 +0500 Subject: [PATCH 3/5] PEP8 formatting + refactoring + rename + split on functions. Stage 2 --- filter.py | 168 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 136 insertions(+), 32 deletions(-) diff --git a/filter.py b/filter.py index d94288a..125681f 100644 --- a/filter.py +++ b/filter.py @@ -1,50 +1,154 @@ from argparse import ArgumentParser, Namespace +from typing import Tuple import numpy as np from PIL import Image -def _create_pixel_art(input_image_path: str, output_image_path: str) -> None: - img = Image.open(input_image_path) - arr = np.array(img, dtype=np.uint8) - a = len(arr) - a1 = len(arr[0]) - i = 0 - - while i < a - 9: - j = 0 - while j < a1 - 9: - s = 0 - for n in range(i, i + 10): - for n1 in range(j, j + 10): - red, green, blue = arr[n][n1] - M = int(red) + int(green) + int(blue) - s += M - s = int(s // 300) - for n in range(i, i + 10): - for n1 in range(j, j + 10): - arr[n][n1][0] = int(s // 50) * 50 - arr[n][n1][1] = int(s // 50) * 50 - arr[n][n1][2] = int(s // 50) * 50 - j = j + 10 - i = i + 10 - print(arr.dtype) - res = Image.fromarray(arr) +class ValidationError(Exception): + pass + + +def _save_image(image_array: np.ndarray, output_image_path: str) -> None: + """ + Сохранить изображение по указанному пути + """ + res = Image.fromarray(image_array) res.save(output_image_path) +def _load_image(input_image_path: str) -> np.ndarray: + """ + Загрузить изображение по указанному пути + """ + img = Image.open(input_image_path) + return np.array(img, dtype=np.uint8) + + +def _get_and_validate_size(pixel_matrix: np.ndarray, segment_size: int) -> Tuple[int, int]: + """ + Получение и валидация размеров матрицы пикселей + """ + rows_count = len(pixel_matrix) + + if not rows_count: + raise ValidationError('Изображение пустое') + + columns_count = len(pixel_matrix[0]) + + if rows_count % segment_size != 0 or columns_count % segment_size != 0: + raise ValidationError( + f"Невозможно разделить изображение размером: ({rows_count}, " + "{columns_count}) на сегменты размером: {segment_size}" + ) + + return rows_count, columns_count + + +def _calculate_mean_by_sector(pixel_matrix: np.ndarray, begin_corrdinates: Tuple[int, int], segment_size: int) -> int: + min_row_number, min_column_number = begin_corrdinates + mean_mosaic_segment_value = 0 + + for current_row_number in range( + min_row_number, min_row_number + segment_size + ): + for current_column_number in range( + min_column_number, min_column_number + segment_size + ): + + red, green, blue = pixel_matrix[current_row_number][ + current_column_number + ] + mean_rgb_value = (int(red) + int(green) + int(blue)) // 3 + mean_mosaic_segment_value += mean_rgb_value + + return int( + mean_mosaic_segment_value // (segment_size ** 2) + ) + + +def _calculate_grayscale_gradation(mean_mosaic_segment_value: int, grayscale_gradation: int) -> int: + return int(mean_mosaic_segment_value // grayscale_gradation) * grayscale_gradation + + +def _insert_grayscale_segment(pixel_matrix: np.ndarray, begin_corrdinates: Tuple[int, int], segment_size: int, grayscale_gradation_value: int) -> None: + min_row_number, min_column_number = begin_corrdinates + for current_row_number in range( + min_row_number, min_row_number + segment_size + ): + for current_column_number in range( + min_column_number, min_column_number + segment_size + ): + pixel_matrix[current_row_number][current_column_number][...] = grayscale_gradation_value + +def _create_pixel_art( + input_image_path: str, + output_image_path: str, + segment_size: int = 10, + grayscale_gradation: int = 50, +) -> None: + pixel_matrix = _load_image(input_image_path) + + rows_count, columns_count = _get_and_validate_size(pixel_matrix, segment_size) + + min_row_number = 0 + + while min_row_number < rows_count: + min_column_number = 0 + + while min_column_number < columns_count: + mean_mosaic_segment_value = _calculate_mean_by_sector(pixel_matrix, (min_row_number, min_column_number), segment_size) + grayscale_gradation_value = _calculate_grayscale_gradation(mean_mosaic_segment_value, grayscale_gradation) + + _insert_grayscale_segment( + pixel_matrix, (min_row_number, min_column_number), segment_size, grayscale_gradation_value + ) + + min_column_number = min_column_number + segment_size + min_row_number = min_row_number + segment_size + + _save_image(pixel_matrix, output_image_path) + + def _parser() -> Namespace: - parser = ArgumentParser(description='Преобразование изображения в пиксель арт') - parser.add_argument('-i', '--input-image', default="./docs/examples/img2.jpg", help='Путь до ихображения которое вы хотите преобразовать') - parser.add_argument('-o', '--output-image', default='./docs/examples/res.jpg', help='Путь, куда вы хотите сохранить изображение') + parser = ArgumentParser(description="Преобразование изображения в пиксель арт") + parser.add_argument( + "-i", + "--input-image", + type=str, + default="./docs/examples/img2.jpg", + help="Путь до ихображения которое вы хотите преобразовать", + ) + parser.add_argument( + "-o", + "--output-image", + type=str, + default="./docs/examples/res.jpg", + help="Путь, куда вы хотите сохранить изображение", + ) + parser.add_argument( + "-s", + "--segment-size", + type=int, + default=10, + help="Размер сегмента мозаики", + ) + parser.add_argument( + "-g", + "--grayscale-gradation", + type=int, + default=50, + help="Градация серого цвета", + ) return parser.parse_args() - def main(): args = _parser() - _create_pixel_art(args.input_image, args.output_image) + _create_pixel_art( + args.input_image, args.output_image, args.segment_size, args.grayscale_gradation + ) -if __name__ == '__main__': +if __name__ == "__main__": main() From 0bd8681805b9a4ecd7d7bfa7a451eb1d5f764dab Mon Sep 17 00:00:00 2001 From: ElizavetaUv <75488565+ElizavetaUv@users.noreply.github.com> Date: Sun, 14 Nov 2021 18:19:39 +0500 Subject: [PATCH 4/5] add matrix operations. Stage 4, 5 --- filter.py | 75 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/filter.py b/filter.py index 125681f..30ee8ee 100644 --- a/filter.py +++ b/filter.py @@ -25,14 +25,16 @@ def _load_image(input_image_path: str) -> np.ndarray: return np.array(img, dtype=np.uint8) -def _get_and_validate_size(pixel_matrix: np.ndarray, segment_size: int) -> Tuple[int, int]: +def _get_and_validate_size( + pixel_matrix: np.ndarray, segment_size: int +) -> Tuple[int, int]: """ Получение и валидация размеров матрицы пикселей """ rows_count = len(pixel_matrix) if not rows_count: - raise ValidationError('Изображение пустое') + raise ValidationError("Изображение пустое") columns_count = len(pixel_matrix[0]) @@ -41,45 +43,43 @@ def _get_and_validate_size(pixel_matrix: np.ndarray, segment_size: int) -> Tuple f"Невозможно разделить изображение размером: ({rows_count}, " "{columns_count}) на сегменты размером: {segment_size}" ) - + return rows_count, columns_count -def _calculate_mean_by_sector(pixel_matrix: np.ndarray, begin_corrdinates: Tuple[int, int], segment_size: int) -> int: +def _calculate_mean_by_sector( + pixel_matrix: np.ndarray, begin_corrdinates: Tuple[int, int], segment_size: int +) -> int: min_row_number, min_column_number = begin_corrdinates - mean_mosaic_segment_value = 0 - - for current_row_number in range( - min_row_number, min_row_number + segment_size - ): - for current_column_number in range( - min_column_number, min_column_number + segment_size - ): - - red, green, blue = pixel_matrix[current_row_number][ - current_column_number - ] - mean_rgb_value = (int(red) + int(green) + int(blue)) // 3 - mean_mosaic_segment_value += mean_rgb_value - return int( - mean_mosaic_segment_value // (segment_size ** 2) + pixel_matrix[ + min_row_number : min_row_number + segment_size, + min_column_number : min_column_number + segment_size, + ].mean() ) -def _calculate_grayscale_gradation(mean_mosaic_segment_value: int, grayscale_gradation: int) -> int: - return int(mean_mosaic_segment_value // grayscale_gradation) * grayscale_gradation +def _calculate_grayscale_gradation( + mean_mosaic_segment_value: int, grayscale_gradation: int +) -> int: + if mean_mosaic_segment_value < grayscale_gradation: + return 0 + + return (mean_mosaic_segment_value // grayscale_gradation) * grayscale_gradation -def _insert_grayscale_segment(pixel_matrix: np.ndarray, begin_corrdinates: Tuple[int, int], segment_size: int, grayscale_gradation_value: int) -> None: +def _insert_grayscale_segment( + pixel_matrix: np.ndarray, + begin_corrdinates: Tuple[int, int], + segment_size: int, + grayscale_gradation_value: int, +) -> None: min_row_number, min_column_number = begin_corrdinates - for current_row_number in range( - min_row_number, min_row_number + segment_size - ): - for current_column_number in range( - min_column_number, min_column_number + segment_size - ): - pixel_matrix[current_row_number][current_column_number][...] = grayscale_gradation_value + pixel_matrix[ + min_row_number : min_row_number + segment_size, + min_column_number : min_column_number + segment_size, + ][...].fill(grayscale_gradation_value) + def _create_pixel_art( input_image_path: str, @@ -97,18 +97,25 @@ def _create_pixel_art( min_column_number = 0 while min_column_number < columns_count: - mean_mosaic_segment_value = _calculate_mean_by_sector(pixel_matrix, (min_row_number, min_column_number), segment_size) - grayscale_gradation_value = _calculate_grayscale_gradation(mean_mosaic_segment_value, grayscale_gradation) + mean_mosaic_segment_value = _calculate_mean_by_sector( + pixel_matrix, (min_row_number, min_column_number), segment_size + ) + grayscale_gradation_value = _calculate_grayscale_gradation( + mean_mosaic_segment_value, grayscale_gradation + ) _insert_grayscale_segment( - pixel_matrix, (min_row_number, min_column_number), segment_size, grayscale_gradation_value + pixel_matrix, + (min_row_number, min_column_number), + segment_size, + grayscale_gradation_value, ) min_column_number = min_column_number + segment_size min_row_number = min_row_number + segment_size _save_image(pixel_matrix, output_image_path) - + def _parser() -> Namespace: parser = ArgumentParser(description="Преобразование изображения в пиксель арт") From 0c64e85109d72b36872e71166ef464fd2f0d9fae Mon Sep 17 00:00:00 2001 From: ElizavetaUv <75488565+ElizavetaUv@users.noreply.github.com> Date: Sun, 14 Nov 2021 18:20:02 +0500 Subject: [PATCH 5/5] add linters and formmatters --- requirements.dev.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 requirements.dev.txt diff --git a/requirements.dev.txt b/requirements.dev.txt new file mode 100644 index 0000000..9d0458a --- /dev/null +++ b/requirements.dev.txt @@ -0,0 +1,7 @@ +# formatters +isort==5.10.1 +black==21.10b0 + +# linters +pylint==2.11.1 +mypy==0.910