Skip to content

Commit

Permalink
refactor: add Byakugan class (#2)
Browse files Browse the repository at this point in the history
* add Byakugan class and adjust the README

* update README and add newline at the end of the file
  • Loading branch information
HokageM authored Apr 3, 2024
1 parent e10697a commit a36ce0a
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 60 deletions.
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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.
Expand Down Expand Up @@ -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
```

<img src="tests/test_images/diff/Diff_naruto_naruto_modified_yellow.jpg" style="width: 200px">
<img src="tests/test_images/diff/Diff_naruto_naruto_modified_yellow.jpg" style="width: 200px">

## 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.
97 changes: 97 additions & 0 deletions src/byakuganvisualizer/Byakugan.py
Original file line number Diff line number Diff line change
@@ -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}')
74 changes: 15 additions & 59 deletions src/byakuganvisualizer/main.py
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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():
Expand Down

0 comments on commit a36ce0a

Please sign in to comment.