• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bethgelab / foolbox / 8137716344

22 Jan 2024 10:53PM UTC coverage: 98.47%. Remained the same
8137716344

push

github

web-flow
Bump pillow from 10.1.0 to 10.2.0 in /tests (#718)

Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.1.0 to 10.2.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.1.0...10.2.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

3475 of 3529 relevant lines covered (98.47%)

7.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/foolbox/attacks/blur.py
1
from typing import Union, Optional, Any
10✔
2
import numpy as np
10✔
3
from scipy.ndimage.filters import gaussian_filter
10✔
4
import eagerpy as ep
10✔
5

6
from ..devutils import atleast_kd
10✔
7

8
from ..models import Model
10✔
9

10
from ..criteria import Criterion
10✔
11

12
from ..distances import Distance
10✔
13

14
from .base import FlexibleDistanceMinimizationAttack
10✔
15
from .base import T
10✔
16
from .base import get_is_adversarial
10✔
17
from .base import get_criterion
10✔
18
from .base import get_channel_axis
10✔
19
from .base import raise_if_kwargs
10✔
20
from .base import verify_input_bounds
10✔
21

22

23
class GaussianBlurAttack(FlexibleDistanceMinimizationAttack):
10✔
24
    """Blurs the inputs using a Gaussian filter with linearly
25
    increasing standard deviation.
26

27
    Args:
28
        steps : Number of sigma values tested between 0 and max_sigma.
29
        channel_axis : Index of the channel axis in the input data.
30
        max_sigma : Maximally allowed sigma value of the Gaussian blur.
31
    """
32

33
    def __init__(
10✔
34
        self,
35
        *,
36
        distance: Optional[Distance] = None,
37
        steps: int = 1000,
38
        channel_axis: Optional[int] = None,
39
        max_sigma: Optional[float] = None,
40
    ):
41
        super().__init__(distance=distance)
10✔
42
        self.steps = steps
10✔
43
        self.channel_axis = channel_axis
10✔
44
        self.max_sigma = max_sigma
10✔
45

46
    def run(
10✔
47
        self,
48
        model: Model,
49
        inputs: T,
50
        criterion: Union[Criterion, T],
51
        *,
52
        early_stop: Optional[float] = None,
53
        **kwargs: Any,
54
    ) -> T:
55
        raise_if_kwargs(kwargs)
10✔
56
        x, restore_type = ep.astensor_(inputs)
10✔
57
        del inputs, kwargs
10✔
58

59
        verify_input_bounds(x, model)
10✔
60

61
        criterion = get_criterion(criterion)
10✔
62
        is_adversarial = get_is_adversarial(criterion, model)
10✔
63

64
        if x.ndim != 4:
10✔
65
            raise NotImplementedError(
66
                "only implemented for inputs with two spatial dimensions (and one channel and one batch dimension)"
67
            )
68

69
        if self.channel_axis is None:
10✔
70
            channel_axis = get_channel_axis(model, x.ndim)
10✔
71
        else:
72
            channel_axis = self.channel_axis % x.ndim
8✔
73

74
        if channel_axis is None:
10✔
75
            raise ValueError(
10✔
76
                "cannot infer the data_format from the model, please specify"
77
                " channel_axis when initializing the attack"
78
            )
79

80
        max_sigma: float
81
        if self.max_sigma is None:
8✔
82
            if channel_axis == 1:
8✔
83
                h, w = x.shape[2:4]
2✔
84
            elif channel_axis == 3:
8✔
85
                h, w = x.shape[1:3]
2✔
86
            else:
87
                raise ValueError(
8✔
88
                    "expected 'channel_axis' to be 1 or 3, got {channel_axis}"
89
                )
90
            max_sigma = max(h, w)
4✔
91
        else:
92
            max_sigma = self.max_sigma
4✔
93

94
        min_, max_ = model.bounds
4✔
95

96
        x0 = x
4✔
97
        x0_ = x0.numpy()
4✔
98

99
        result = x0
4✔
100
        found = is_adversarial(x0)
4✔
101

102
        epsilon = 0.0
4✔
103
        stepsize = 1.0 / self.steps
4✔
104
        for _ in range(self.steps):
4✔
105
            # TODO: reduce the batch size to the ones that haven't been sucessful
106

107
            epsilon += stepsize
4✔
108

109
            sigmas = [epsilon * max_sigma] * x0.ndim
4✔
110
            sigmas[0] = 0
4✔
111
            sigmas[channel_axis] = 0
4✔
112

113
            # TODO: once we can implement gaussian_filter in eagerpy, avoid converting from numpy
114
            x_ = gaussian_filter(x0_, sigmas)
4✔
115
            x_ = np.clip(x_, min_, max_)
4✔
116
            x = ep.from_numpy(x0, x_)
4✔
117

118
            is_adv = is_adversarial(x)
4✔
119
            new_adv = ep.logical_and(is_adv, found.logical_not())
4✔
120
            result = ep.where(atleast_kd(new_adv, x.ndim), x, result)
4✔
121
            found = ep.logical_or(new_adv, found)
4✔
122

123
            if found.all():
4✔
124
                break
4✔
125

126
        return restore_type(result)
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc