diff --git a/README.md b/README.md index da088c0..18db87b 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ pip install byakuganvisualizer ## Usage +### Command Line Interface + ``` usage: byakugan_vision [-h] [--version] [--diff DIFF] [--filter {red,blue,green,yellow}] [--images IMAGES] [--deuteranomaly DEUTERANOMALY] [--protanomaly PROTANOMALY] [--out_dir OUT_DIR] @@ -37,9 +39,21 @@ options: --out_dir OUT_DIR Output directory for the difference images ``` +### Python API + +Please read the API documentation for the classes `Byakugan` and `ImageFilter` for more information. +You can simply import the classes as follows: + +```python +from byakuganvisualizer.Byakugan import Byakugan +from byakuganvisualizer.ImageFilter import ImageFilter +``` + + ## Image Correction for Color Blind People In the following examples the image is corrected for deuteranomaly and protanomaly. +Correction in this context means that the image is adjusted to be more distinguishable for color-blind people. **Note:** The float values for deuteranomaly and protanomaly are between 0 and 10. The default value is 1. The used algorithm is based on the following paper: https://arxiv.org/abs/1711.10662. @@ -147,4 +161,15 @@ byakugan_vision --diff "tests/test_images/naruto.jpg,tests/test_images/naruto_mo byakugan_vision --diff "tests/test_images/naruto.jpg,tests/test_images/naruto_modified.jpg" --filter yellow --out_dir tests/test_images/diff ``` - \ No newline at end of file + + +## Byakugan + +The [Bykugan](https://naruto.fandom.com/wiki/Byakugan) from Naruto is a powerful ability that grants users the ability +to see through objects, detect chakra, and perceive long distances, but users are born blind, relying solely on this +special vision. + + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. \ No newline at end of file diff --git a/src/byakuganvisualizer/Byakugan.py b/src/byakuganvisualizer/Byakugan.py new file mode 100644 index 0000000..6b0b94b --- /dev/null +++ b/src/byakuganvisualizer/Byakugan.py @@ -0,0 +1,97 @@ +import numpy as np +import os + +from PIL import Image + +from byakuganvisualizer.ImageFilter import ImageFilter + + +class Byakugan: + """ + This class is used to process images by applying filters and calculating differences between pairs of images. + """ + + def __init__(self, out_dir='.', filter='', deuteranomaly=0, protanomaly=0): + self.out_dir = out_dir + self.filter = filter + self.protanomaly = protanomaly + self.deuteranomaly = deuteranomaly + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + pass + + def apply_filters(self, image_data): + """ + Apply filters to the image data. + :param image_data: The image data to apply the filters to. + :return: Tuple consisting of filtered image data and the suffix representing the filters applied. + """ + suffix = '' + if self.filter == 'red': + image_data = ImageFilter.apply_red_filter(image_data) + suffix += '_red' + if self.filter == 'blue': + image_data = ImageFilter.apply_blue_filter(image_data) + suffix += '_blue' + if self.filter == 'green': + image_data = ImageFilter.apply_green_filter(image_data) + suffix += '_green' + if self.filter == 'yellow': + image_data = ImageFilter.apply_yellow_filter(image_data) + suffix += '_yellow' + if self.protanomaly > 0 or self.deuteranomaly > 0: + image_data = ImageFilter.correction_for_colorblindness(image_data, self.protanomaly, self.deuteranomaly) + suffix += f'_deuteranomaly_{self.deuteranomaly}_protanomaly_{self.protanomaly}' + return image_data, suffix + + def calculate_diffs(self, diff_pairs): + """ + Calculate the differences between pairs of images. + :param diff_pairs: + :return: + """ + for pair in diff_pairs: + pair_name = os.path.basename(pair[0]).split('.')[0] + '_' + os.path.basename(pair[1]).split('.')[0] + file_extension_1 = os.path.basename(pair[0]).split('.')[1] + file_extension_2 = os.path.basename(pair[1]).split('.')[1] + + if file_extension_1 != file_extension_2: + raise ValueError(f"Images must have the same file extension. {file_extension_1} != {file_extension_2}") + + image1 = Image.open(pair[0]) + image2 = Image.open(pair[1]) + + array1 = np.array(image1) + array2 = np.array(image2) + + if array1.shape != array2.shape: + raise ValueError(f"Images must be of the same size. {array1.shape} != {array2.shape}") + + difference_array = np.abs(array1 - array2) + + difference_array, suffix = self.apply_filters(difference_array) + pair_name += suffix + + difference_image = Image.fromarray(difference_array.astype('uint8')) + difference_image.save(f'{self.out_dir}/Diff_{pair_name}.{file_extension_1}') + + def process_images(self, images): + """ + Process images by applying filters. + :param images: + :return: + """ + for img in images: + image_name, file_extension = os.path.basename(img).split('.') + + image = Image.open(img) + rgb_array = np.array(image) + + rgb_array, suffix = self.apply_filters(rgb_array) + image_name += suffix + + filtered_image = Image.fromarray(rgb_array.astype('uint8')) + filtered_image.save(f'{self.out_dir}/Filtered_{image_name}.{file_extension}') diff --git a/src/byakuganvisualizer/main.py b/src/byakuganvisualizer/main.py index cd5202e..874542c 100644 --- a/src/byakuganvisualizer/main.py +++ b/src/byakuganvisualizer/main.py @@ -1,12 +1,9 @@ import argparse import sys -import numpy as np import os -from PIL import Image - from byakuganvisualizer import __version__ -from byakuganvisualizer.ImageFilter import ImageFilter +from byakuganvisualizer.Byakugan import Byakugan __author__ = "HokageM" __copyright__ = "HokageM" @@ -93,61 +90,20 @@ def main(args): os.makedirs(args.out_dir) print(f"Output Directory: '{args.out_dir}' created.") - if args.diff: - for pair in args.diff: - pair_name = os.path.basename(pair[0]).split('.')[0] + '_' + os.path.basename(pair[1]).split('.')[0] - - image1 = Image.open(pair[0]) - image2 = Image.open(pair[1]) - - array1 = np.array(image1) - array2 = np.array(image2) - - # Calculate the absolute difference between the two arrays - difference_array = np.abs(array1 - array2) - - if args.filter == 'red': - difference_array = ImageFilter.apply_red_filter(difference_array) - pair_name += '_red' - if args.filter == 'blue': - difference_array = ImageFilter.apply_blue_filter(difference_array) - pair_name += '_blue' - if args.filter == 'green': - difference_array = ImageFilter.apply_green_filter(difference_array) - pair_name += '_green' - if args.filter == 'yellow': - difference_array = ImageFilter.apply_yellow_filter(difference_array) - pair_name += '_yellow' - - difference_image = Image.fromarray(difference_array.astype('uint8')) - difference_image.save(f'{args.out_dir}/Diff_{pair_name}.jpg') - - if args.images: - args.images = args.images.split(',') - for img in args.images: - image_name = os.path.basename(img).split('.')[0] - - image = Image.open(img) - rgb_array = np.array(image) - - if args.filter == 'red': - rgb_array = ImageFilter.apply_red_filter(rgb_array) - image_name += '_red' - if args.filter == 'blue': - rgb_array = ImageFilter.apply_blue_filter(rgb_array) - image_name += '_blue' - if args.filter == 'green': - rgb_array = ImageFilter.apply_green_filter(rgb_array) - image_name += '_green' - if args.filter == 'yellow': - rgb_array = ImageFilter.apply_yellow_filter(rgb_array) - image_name += '_yellow' - if args.protanomaly > 0 or args.deuteranomaly > 0: - rgb_array = ImageFilter.correction_for_colorblindness(rgb_array, args.protanomaly, args.deuteranomaly) - image_name += f'_deuteranomaly_{args.deuteranomaly}_protanomaly_{args.protanomaly}' - - filtered_image = Image.fromarray(rgb_array.astype('uint8')) - filtered_image.save(f'{args.out_dir}/Filtered_{image_name}.jpg') + if args.diff is None and args.images is None: + print("No images to process.") + return + + if args.diff and args.images: + raise ValueError("Please do not use --diff and --images at the same time.") + + with Byakugan(args.out_dir, args.filter, args.deuteranomaly, args.protanomaly) as byakugan: + print("BYAKUGAN ACTIVATED!") + if args.diff: + byakugan.calculate_diffs(args.diff) + if args.images: + args.images = args.images.split(',') + byakugan.process_images(args.images) def run():