Skip to content

Commit bb13a00

Browse files
Merge pull request #2 from davidnabergoj/bernarda
Changes to how images are averaged
2 parents 2716f1f + 23a28d6 commit bb13a00

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+218
-142
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@
88
!logo.svg
99
!docs/images/*
1010
docs/build
11+
__pycache__/
12+
.ipynb_checkpoints/
13+
.DS_Store
14+
*.egg-info
15+

LICENSE

100644100755
File mode changed.

README.md

100644100755
File mode changed.

bootplot/__init__.py

100644100755
File mode changed.

bootplot/__version__.py

100644100755
File mode changed.

bootplot/backend/__init__.py

100644100755
File mode changed.

bootplot/backend/base.py

100644100755
File mode changed.

bootplot/backend/matplotlib.py

100644100755
File mode changed.

bootplot/base.py

100644100755
Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
import numpy as np
55
import imageio
66
import pandas as pd
7+
from matplotlib import pyplot as plt
8+
from scipy.ndimage import gaussian_filter
79
from tqdm import tqdm
8-
from PIL import Image
10+
from PIL import Image, ImageFilter
11+
from scipy.stats import beta
912

1013
from bootplot.backend.base import Backend, create_backend
1114
from bootplot.sorting import sort_images
15+
from collections import Counter
1216

1317

1418
def plot(plot_function: callable,
@@ -21,21 +25,42 @@ def plot(plot_function: callable,
2125
else:
2226
plot_function(data[indices], data, *backend.plot_args, **kwargs)
2327

28+
def symmetric_transformation_new(x, k=0.5, threshold = 0.3):
29+
y = beta.cdf(x, k, k)
30+
return (1-2*threshold) * y + threshold
31+
32+
def adjust_relative_frequencies_opt(relative_frequencies):
33+
dominant_color = max(relative_frequencies, key=relative_frequencies.get)
34+
transformed_dominant = symmetric_transformation_new(relative_frequencies[dominant_color])
35+
sum_other = 1-relative_frequencies[dominant_color]
36+
transformed_other = 1-transformed_dominant
37+
return {
38+
color: transformed_other * rel_freq / sum_other if color != dominant_color else
39+
transformed_dominant
40+
for color, rel_freq in relative_frequencies.items()
41+
}
42+
43+
def merge_images(images: np.ndarray) -> np.ndarray:
44+
num_images, rows, cols, _ = images.shape
45+
new_image = np.zeros((rows, cols, 3), dtype=np.uint8)
46+
47+
# Iterate over each pixel location
48+
for i in range(rows):
49+
for j in range(cols):
50+
# Extract the colors at the current pixel location across all images
51+
pixel_colors = [tuple(images[img, i, j]) for img in range(num_images)]
52+
# Count the occurrence of each color in this list of colors
53+
color_counts = Counter(pixel_colors)
54+
percentages_old = {color: count / sum(color_counts.values()) for color, count in color_counts.items()}
55+
if len(percentages_old) > 1:
56+
percentages = adjust_relative_frequencies_opt(percentages_old)
57+
new_color = np.sum([np.array(c) * p for c, p in percentages.items()], axis=0)
58+
new_color = np.clip(new_color, 0, 255).astype(np.uint8)
59+
new_image[i, j] = new_color
60+
else:
61+
new_image[i,j] = list(percentages_old.keys())[0]
62+
return new_image
2463

25-
def merge_images(images: np.ndarray, power: float = 1.0) -> np.ndarray:
26-
"""
27-
Merge images into a static image (averaged image).
28-
The shape of images is (batch_size, width, height, channels).
29-
This operation overwrites input images.
30-
31-
:param images: images corresponding to different bootstrap samples.
32-
:param power: raise the merged image pixels to the specified power to increase contrast.
33-
:return: merged image.
34-
"""
35-
images = images.astype(np.float32) / 255 # Cast to float
36-
merged = np.mean(images, axis=0) ** power
37-
merged = (merged * 255).astype(np.uint8)
38-
return merged
3964

4065

4166
def decay_images(images: np.ndarray,
@@ -67,7 +92,6 @@ def bootplot(f: callable,
6792
output_size_px: Tuple[int, int] = (512, 512),
6893
output_image_path: Union[str, Path] = None,
6994
output_animation_path: Union[str, Path] = None,
70-
contrast_modifier: float = 1.0,
7195
sort_type: str = 'tsp',
7296
sort_kwargs: dict = None,
7397
decay: int = 0,
@@ -104,10 +128,6 @@ def bootplot(f: callable,
104128
filename extension. If None, the animation is not created. Default: ``None``.
105129
:type output_animation_path: str or pathlib.Path
106130
107-
:param contrast_modifier: modify the contrast in the static image. Setting this to 1 keeps the same contrast,
108-
setting this to less than 1 reduces contrast, setting this to greater than 1 increases contrast. Default: ``1``.
109-
:type contrast_modifier: float
110-
111131
:param sort_type: method to sort images when constructing the animation. Should be one of the following:
112132
"tsp" (traveling salesman method on the image similarity graph), "pca" (image projection onto the real line
113133
using PCA), "hm" (order using center mass in the horizontal direction), "none" (no sorting; random order).
@@ -183,7 +203,7 @@ def bootplot(f: callable,
183203
backend.close_figure()
184204
images = np.stack(images)
185205

186-
merged_image = merge_images(images, power=contrast_modifier)[..., :3] # Do not use the alpha channel
206+
merged_image = merge_images(images[..., :3])
187207

188208
if output_image_path is not None:
189209
if verbose:

bootplot/image_features.py

100644100755
File mode changed.

0 commit comments

Comments
 (0)