Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/scipy/ndimage/filters.py : 15%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Copyright (C) 2003-2005 Peter J. Verveer
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6#
7# 1. Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9#
10# 2. Redistributions in binary form must reproduce the above
11# copyright notice, this list of conditions and the following
12# disclaimer in the documentation and/or other materials provided
13# with the distribution.
14#
15# 3. The name of the author may not be used to endorse or promote
16# products derived from this software without specific prior
17# written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31from collections.abc import Iterable
32import warnings
33import numpy
34import operator
35from numpy.core.multiarray import normalize_axis_index
36from . import _ni_support
37from . import _nd_image
38from . import _ni_docstrings
40__all__ = ['correlate1d', 'convolve1d', 'gaussian_filter1d', 'gaussian_filter',
41 'prewitt', 'sobel', 'generic_laplace', 'laplace',
42 'gaussian_laplace', 'generic_gradient_magnitude',
43 'gaussian_gradient_magnitude', 'correlate', 'convolve',
44 'uniform_filter1d', 'uniform_filter', 'minimum_filter1d',
45 'maximum_filter1d', 'minimum_filter', 'maximum_filter',
46 'rank_filter', 'median_filter', 'percentile_filter',
47 'generic_filter1d', 'generic_filter']
50def _invalid_origin(origin, lenw):
51 return (origin < -(lenw // 2)) or (origin > (lenw - 1) // 2)
54@_ni_docstrings.docfiller
55def correlate1d(input, weights, axis=-1, output=None, mode="reflect",
56 cval=0.0, origin=0):
57 """Calculate a 1-D correlation along the given axis.
59 The lines of the array along the given axis are correlated with the
60 given weights.
62 Parameters
63 ----------
64 %(input)s
65 weights : array
66 1-D sequence of numbers.
67 %(axis)s
68 %(output)s
69 %(mode)s
70 %(cval)s
71 %(origin)s
73 Examples
74 --------
75 >>> from scipy.ndimage import correlate1d
76 >>> correlate1d([2, 8, 0, 4, 1, 9, 9, 0], weights=[1, 3])
77 array([ 8, 26, 8, 12, 7, 28, 36, 9])
78 """
79 input = numpy.asarray(input)
80 if numpy.iscomplexobj(input):
81 raise TypeError('Complex type not supported')
82 output = _ni_support._get_output(output, input)
83 weights = numpy.asarray(weights, dtype=numpy.float64)
84 if weights.ndim != 1 or weights.shape[0] < 1:
85 raise RuntimeError('no filter weights given')
86 if not weights.flags.contiguous:
87 weights = weights.copy()
88 axis = normalize_axis_index(axis, input.ndim)
89 if _invalid_origin(origin, len(weights)):
90 raise ValueError('Invalid origin; origin must satisfy '
91 '-(len(weights) // 2) <= origin <= '
92 '(len(weights)-1) // 2')
93 mode = _ni_support._extend_mode_to_code(mode)
94 _nd_image.correlate1d(input, weights, axis, output, mode, cval,
95 origin)
96 return output
99@_ni_docstrings.docfiller
100def convolve1d(input, weights, axis=-1, output=None, mode="reflect",
101 cval=0.0, origin=0):
102 """Calculate a 1-D convolution along the given axis.
104 The lines of the array along the given axis are convolved with the
105 given weights.
107 Parameters
108 ----------
109 %(input)s
110 weights : ndarray
111 1-D sequence of numbers.
112 %(axis)s
113 %(output)s
114 %(mode)s
115 %(cval)s
116 %(origin)s
118 Returns
119 -------
120 convolve1d : ndarray
121 Convolved array with same shape as input
123 Examples
124 --------
125 >>> from scipy.ndimage import convolve1d
126 >>> convolve1d([2, 8, 0, 4, 1, 9, 9, 0], weights=[1, 3])
127 array([14, 24, 4, 13, 12, 36, 27, 0])
128 """
129 weights = weights[::-1]
130 origin = -origin
131 if not len(weights) & 1:
132 origin -= 1
133 return correlate1d(input, weights, axis, output, mode, cval, origin)
136def _gaussian_kernel1d(sigma, order, radius):
137 """
138 Computes a 1-D Gaussian convolution kernel.
139 """
140 if order < 0:
141 raise ValueError('order must be non-negative')
142 exponent_range = numpy.arange(order + 1)
143 sigma2 = sigma * sigma
144 x = numpy.arange(-radius, radius+1)
145 phi_x = numpy.exp(-0.5 / sigma2 * x ** 2)
146 phi_x = phi_x / phi_x.sum()
148 if order == 0:
149 return phi_x
150 else:
151 # f(x) = q(x) * phi(x) = q(x) * exp(p(x))
152 # f'(x) = (q'(x) + q(x) * p'(x)) * phi(x)
153 # p'(x) = -1 / sigma ** 2
154 # Implement q'(x) + q(x) * p'(x) as a matrix operator and apply to the
155 # coefficients of q(x)
156 q = numpy.zeros(order + 1)
157 q[0] = 1
158 D = numpy.diag(exponent_range[1:], 1) # D @ q(x) = q'(x)
159 P = numpy.diag(numpy.ones(order)/-sigma2, -1) # P @ q(x) = q(x) * p'(x)
160 Q_deriv = D + P
161 for _ in range(order):
162 q = Q_deriv.dot(q)
163 q = (x[:, None] ** exponent_range).dot(q)
164 return q * phi_x
167@_ni_docstrings.docfiller
168def gaussian_filter1d(input, sigma, axis=-1, order=0, output=None,
169 mode="reflect", cval=0.0, truncate=4.0):
170 """1-D Gaussian filter.
172 Parameters
173 ----------
174 %(input)s
175 sigma : scalar
176 standard deviation for Gaussian kernel
177 %(axis)s
178 order : int, optional
179 An order of 0 corresponds to convolution with a Gaussian
180 kernel. A positive order corresponds to convolution with
181 that derivative of a Gaussian.
182 %(output)s
183 %(mode)s
184 %(cval)s
185 truncate : float, optional
186 Truncate the filter at this many standard deviations.
187 Default is 4.0.
189 Returns
190 -------
191 gaussian_filter1d : ndarray
193 Examples
194 --------
195 >>> from scipy.ndimage import gaussian_filter1d
196 >>> gaussian_filter1d([1.0, 2.0, 3.0, 4.0, 5.0], 1)
197 array([ 1.42704095, 2.06782203, 3. , 3.93217797, 4.57295905])
198 >>> gaussian_filter1d([1.0, 2.0, 3.0, 4.0, 5.0], 4)
199 array([ 2.91948343, 2.95023502, 3. , 3.04976498, 3.08051657])
200 >>> import matplotlib.pyplot as plt
201 >>> np.random.seed(280490)
202 >>> x = np.random.randn(101).cumsum()
203 >>> y3 = gaussian_filter1d(x, 3)
204 >>> y6 = gaussian_filter1d(x, 6)
205 >>> plt.plot(x, 'k', label='original data')
206 >>> plt.plot(y3, '--', label='filtered, sigma=3')
207 >>> plt.plot(y6, ':', label='filtered, sigma=6')
208 >>> plt.legend()
209 >>> plt.grid()
210 >>> plt.show()
211 """
212 sd = float(sigma)
213 # make the radius of the filter equal to truncate standard deviations
214 lw = int(truncate * sd + 0.5)
215 # Since we are calling correlate, not convolve, revert the kernel
216 weights = _gaussian_kernel1d(sigma, order, lw)[::-1]
217 return correlate1d(input, weights, axis, output, mode, cval, 0)
220@_ni_docstrings.docfiller
221def gaussian_filter(input, sigma, order=0, output=None,
222 mode="reflect", cval=0.0, truncate=4.0):
223 """Multidimensional Gaussian filter.
225 Parameters
226 ----------
227 %(input)s
228 sigma : scalar or sequence of scalars
229 Standard deviation for Gaussian kernel. The standard
230 deviations of the Gaussian filter are given for each axis as a
231 sequence, or as a single number, in which case it is equal for
232 all axes.
233 order : int or sequence of ints, optional
234 The order of the filter along each axis is given as a sequence
235 of integers, or as a single number. An order of 0 corresponds
236 to convolution with a Gaussian kernel. A positive order
237 corresponds to convolution with that derivative of a Gaussian.
238 %(output)s
239 %(mode_multiple)s
240 %(cval)s
241 truncate : float
242 Truncate the filter at this many standard deviations.
243 Default is 4.0.
245 Returns
246 -------
247 gaussian_filter : ndarray
248 Returned array of same shape as `input`.
250 Notes
251 -----
252 The multidimensional filter is implemented as a sequence of
253 1-D convolution filters. The intermediate arrays are
254 stored in the same data type as the output. Therefore, for output
255 types with a limited precision, the results may be imprecise
256 because intermediate results may be stored with insufficient
257 precision.
259 Examples
260 --------
261 >>> from scipy.ndimage import gaussian_filter
262 >>> a = np.arange(50, step=2).reshape((5,5))
263 >>> a
264 array([[ 0, 2, 4, 6, 8],
265 [10, 12, 14, 16, 18],
266 [20, 22, 24, 26, 28],
267 [30, 32, 34, 36, 38],
268 [40, 42, 44, 46, 48]])
269 >>> gaussian_filter(a, sigma=1)
270 array([[ 4, 6, 8, 9, 11],
271 [10, 12, 14, 15, 17],
272 [20, 22, 24, 25, 27],
273 [29, 31, 33, 34, 36],
274 [35, 37, 39, 40, 42]])
276 >>> from scipy import misc
277 >>> import matplotlib.pyplot as plt
278 >>> fig = plt.figure()
279 >>> plt.gray() # show the filtered result in grayscale
280 >>> ax1 = fig.add_subplot(121) # left side
281 >>> ax2 = fig.add_subplot(122) # right side
282 >>> ascent = misc.ascent()
283 >>> result = gaussian_filter(ascent, sigma=5)
284 >>> ax1.imshow(ascent)
285 >>> ax2.imshow(result)
286 >>> plt.show()
287 """
288 input = numpy.asarray(input)
289 output = _ni_support._get_output(output, input)
290 orders = _ni_support._normalize_sequence(order, input.ndim)
291 sigmas = _ni_support._normalize_sequence(sigma, input.ndim)
292 modes = _ni_support._normalize_sequence(mode, input.ndim)
293 axes = list(range(input.ndim))
294 axes = [(axes[ii], sigmas[ii], orders[ii], modes[ii])
295 for ii in range(len(axes)) if sigmas[ii] > 1e-15]
296 if len(axes) > 0:
297 for axis, sigma, order, mode in axes:
298 gaussian_filter1d(input, sigma, axis, order, output,
299 mode, cval, truncate)
300 input = output
301 else:
302 output[...] = input[...]
303 return output
306@_ni_docstrings.docfiller
307def prewitt(input, axis=-1, output=None, mode="reflect", cval=0.0):
308 """Calculate a Prewitt filter.
310 Parameters
311 ----------
312 %(input)s
313 %(axis)s
314 %(output)s
315 %(mode_multiple)s
316 %(cval)s
318 Examples
319 --------
320 >>> from scipy import ndimage, misc
321 >>> import matplotlib.pyplot as plt
322 >>> fig = plt.figure()
323 >>> plt.gray() # show the filtered result in grayscale
324 >>> ax1 = fig.add_subplot(121) # left side
325 >>> ax2 = fig.add_subplot(122) # right side
326 >>> ascent = misc.ascent()
327 >>> result = ndimage.prewitt(ascent)
328 >>> ax1.imshow(ascent)
329 >>> ax2.imshow(result)
330 >>> plt.show()
331 """
332 input = numpy.asarray(input)
333 axis = normalize_axis_index(axis, input.ndim)
334 output = _ni_support._get_output(output, input)
335 modes = _ni_support._normalize_sequence(mode, input.ndim)
336 correlate1d(input, [-1, 0, 1], axis, output, modes[axis], cval, 0)
337 axes = [ii for ii in range(input.ndim) if ii != axis]
338 for ii in axes:
339 correlate1d(output, [1, 1, 1], ii, output, modes[ii], cval, 0,)
340 return output
343@_ni_docstrings.docfiller
344def sobel(input, axis=-1, output=None, mode="reflect", cval=0.0):
345 """Calculate a Sobel filter.
347 Parameters
348 ----------
349 %(input)s
350 %(axis)s
351 %(output)s
352 %(mode_multiple)s
353 %(cval)s
355 Examples
356 --------
357 >>> from scipy import ndimage, misc
358 >>> import matplotlib.pyplot as plt
359 >>> fig = plt.figure()
360 >>> plt.gray() # show the filtered result in grayscale
361 >>> ax1 = fig.add_subplot(121) # left side
362 >>> ax2 = fig.add_subplot(122) # right side
363 >>> ascent = misc.ascent()
364 >>> result = ndimage.sobel(ascent)
365 >>> ax1.imshow(ascent)
366 >>> ax2.imshow(result)
367 >>> plt.show()
368 """
369 input = numpy.asarray(input)
370 axis = normalize_axis_index(axis, input.ndim)
371 output = _ni_support._get_output(output, input)
372 modes = _ni_support._normalize_sequence(mode, input.ndim)
373 correlate1d(input, [-1, 0, 1], axis, output, modes[axis], cval, 0)
374 axes = [ii for ii in range(input.ndim) if ii != axis]
375 for ii in axes:
376 correlate1d(output, [1, 2, 1], ii, output, modes[ii], cval, 0)
377 return output
380@_ni_docstrings.docfiller
381def generic_laplace(input, derivative2, output=None, mode="reflect",
382 cval=0.0,
383 extra_arguments=(),
384 extra_keywords=None):
385 """
386 N-D Laplace filter using a provided second derivative function.
388 Parameters
389 ----------
390 %(input)s
391 derivative2 : callable
392 Callable with the following signature::
394 derivative2(input, axis, output, mode, cval,
395 *extra_arguments, **extra_keywords)
397 See `extra_arguments`, `extra_keywords` below.
398 %(output)s
399 %(mode_multiple)s
400 %(cval)s
401 %(extra_keywords)s
402 %(extra_arguments)s
403 """
404 if extra_keywords is None:
405 extra_keywords = {}
406 input = numpy.asarray(input)
407 output = _ni_support._get_output(output, input)
408 axes = list(range(input.ndim))
409 if len(axes) > 0:
410 modes = _ni_support._normalize_sequence(mode, len(axes))
411 derivative2(input, axes[0], output, modes[0], cval,
412 *extra_arguments, **extra_keywords)
413 for ii in range(1, len(axes)):
414 tmp = derivative2(input, axes[ii], output.dtype, modes[ii], cval,
415 *extra_arguments, **extra_keywords)
416 output += tmp
417 else:
418 output[...] = input[...]
419 return output
422@_ni_docstrings.docfiller
423def laplace(input, output=None, mode="reflect", cval=0.0):
424 """N-D Laplace filter based on approximate second derivatives.
426 Parameters
427 ----------
428 %(input)s
429 %(output)s
430 %(mode_multiple)s
431 %(cval)s
433 Examples
434 --------
435 >>> from scipy import ndimage, misc
436 >>> import matplotlib.pyplot as plt
437 >>> fig = plt.figure()
438 >>> plt.gray() # show the filtered result in grayscale
439 >>> ax1 = fig.add_subplot(121) # left side
440 >>> ax2 = fig.add_subplot(122) # right side
441 >>> ascent = misc.ascent()
442 >>> result = ndimage.laplace(ascent)
443 >>> ax1.imshow(ascent)
444 >>> ax2.imshow(result)
445 >>> plt.show()
446 """
447 def derivative2(input, axis, output, mode, cval):
448 return correlate1d(input, [1, -2, 1], axis, output, mode, cval, 0)
449 return generic_laplace(input, derivative2, output, mode, cval)
452@_ni_docstrings.docfiller
453def gaussian_laplace(input, sigma, output=None, mode="reflect",
454 cval=0.0, **kwargs):
455 """Multidimensional Laplace filter using Gaussian second derivatives.
457 Parameters
458 ----------
459 %(input)s
460 sigma : scalar or sequence of scalars
461 The standard deviations of the Gaussian filter are given for
462 each axis as a sequence, or as a single number, in which case
463 it is equal for all axes.
464 %(output)s
465 %(mode_multiple)s
466 %(cval)s
467 Extra keyword arguments will be passed to gaussian_filter().
469 Examples
470 --------
471 >>> from scipy import ndimage, misc
472 >>> import matplotlib.pyplot as plt
473 >>> ascent = misc.ascent()
475 >>> fig = plt.figure()
476 >>> plt.gray() # show the filtered result in grayscale
477 >>> ax1 = fig.add_subplot(121) # left side
478 >>> ax2 = fig.add_subplot(122) # right side
480 >>> result = ndimage.gaussian_laplace(ascent, sigma=1)
481 >>> ax1.imshow(result)
483 >>> result = ndimage.gaussian_laplace(ascent, sigma=3)
484 >>> ax2.imshow(result)
485 >>> plt.show()
486 """
487 input = numpy.asarray(input)
489 def derivative2(input, axis, output, mode, cval, sigma, **kwargs):
490 order = [0] * input.ndim
491 order[axis] = 2
492 return gaussian_filter(input, sigma, order, output, mode, cval,
493 **kwargs)
495 return generic_laplace(input, derivative2, output, mode, cval,
496 extra_arguments=(sigma,),
497 extra_keywords=kwargs)
500@_ni_docstrings.docfiller
501def generic_gradient_magnitude(input, derivative, output=None,
502 mode="reflect", cval=0.0,
503 extra_arguments=(), extra_keywords=None):
504 """Gradient magnitude using a provided gradient function.
506 Parameters
507 ----------
508 %(input)s
509 derivative : callable
510 Callable with the following signature::
512 derivative(input, axis, output, mode, cval,
513 *extra_arguments, **extra_keywords)
515 See `extra_arguments`, `extra_keywords` below.
516 `derivative` can assume that `input` and `output` are ndarrays.
517 Note that the output from `derivative` is modified inplace;
518 be careful to copy important inputs before returning them.
519 %(output)s
520 %(mode_multiple)s
521 %(cval)s
522 %(extra_keywords)s
523 %(extra_arguments)s
524 """
525 if extra_keywords is None:
526 extra_keywords = {}
527 input = numpy.asarray(input)
528 output = _ni_support._get_output(output, input)
529 axes = list(range(input.ndim))
530 if len(axes) > 0:
531 modes = _ni_support._normalize_sequence(mode, len(axes))
532 derivative(input, axes[0], output, modes[0], cval,
533 *extra_arguments, **extra_keywords)
534 numpy.multiply(output, output, output)
535 for ii in range(1, len(axes)):
536 tmp = derivative(input, axes[ii], output.dtype, modes[ii], cval,
537 *extra_arguments, **extra_keywords)
538 numpy.multiply(tmp, tmp, tmp)
539 output += tmp
540 # This allows the sqrt to work with a different default casting
541 numpy.sqrt(output, output, casting='unsafe')
542 else:
543 output[...] = input[...]
544 return output
547@_ni_docstrings.docfiller
548def gaussian_gradient_magnitude(input, sigma, output=None,
549 mode="reflect", cval=0.0, **kwargs):
550 """Multidimensional gradient magnitude using Gaussian derivatives.
552 Parameters
553 ----------
554 %(input)s
555 sigma : scalar or sequence of scalars
556 The standard deviations of the Gaussian filter are given for
557 each axis as a sequence, or as a single number, in which case
558 it is equal for all axes.
559 %(output)s
560 %(mode_multiple)s
561 %(cval)s
562 Extra keyword arguments will be passed to gaussian_filter().
564 Returns
565 -------
566 gaussian_gradient_magnitude : ndarray
567 Filtered array. Has the same shape as `input`.
569 Examples
570 --------
571 >>> from scipy import ndimage, misc
572 >>> import matplotlib.pyplot as plt
573 >>> fig = plt.figure()
574 >>> plt.gray() # show the filtered result in grayscale
575 >>> ax1 = fig.add_subplot(121) # left side
576 >>> ax2 = fig.add_subplot(122) # right side
577 >>> ascent = misc.ascent()
578 >>> result = ndimage.gaussian_gradient_magnitude(ascent, sigma=5)
579 >>> ax1.imshow(ascent)
580 >>> ax2.imshow(result)
581 >>> plt.show()
582 """
583 input = numpy.asarray(input)
585 def derivative(input, axis, output, mode, cval, sigma, **kwargs):
586 order = [0] * input.ndim
587 order[axis] = 1
588 return gaussian_filter(input, sigma, order, output, mode,
589 cval, **kwargs)
591 return generic_gradient_magnitude(input, derivative, output, mode,
592 cval, extra_arguments=(sigma,),
593 extra_keywords=kwargs)
596def _correlate_or_convolve(input, weights, output, mode, cval, origin,
597 convolution):
598 input = numpy.asarray(input)
599 if numpy.iscomplexobj(input):
600 raise TypeError('Complex type not supported')
601 origins = _ni_support._normalize_sequence(origin, input.ndim)
602 weights = numpy.asarray(weights, dtype=numpy.float64)
603 wshape = [ii for ii in weights.shape if ii > 0]
604 if len(wshape) != input.ndim:
605 raise RuntimeError('filter weights array has incorrect shape.')
606 if convolution:
607 weights = weights[tuple([slice(None, None, -1)] * weights.ndim)]
608 for ii in range(len(origins)):
609 origins[ii] = -origins[ii]
610 if not weights.shape[ii] & 1:
611 origins[ii] -= 1
612 for origin, lenw in zip(origins, wshape):
613 if _invalid_origin(origin, lenw):
614 raise ValueError('Invalid origin; origin must satisfy '
615 '-(weights.shape[k] // 2) <= origin[k] <= '
616 '(weights.shape[k]-1) // 2')
618 if not weights.flags.contiguous:
619 weights = weights.copy()
620 output = _ni_support._get_output(output, input)
621 temp_needed = numpy.may_share_memory(input, output)
622 if temp_needed:
623 # input and output arrays cannot share memory
624 temp = output
625 output = _ni_support._get_output(output.dtype, input)
626 if not isinstance(mode, str) and isinstance(mode, Iterable):
627 raise RuntimeError("A sequence of modes is not supported")
628 mode = _ni_support._extend_mode_to_code(mode)
629 _nd_image.correlate(input, weights, output, mode, cval, origins)
630 if temp_needed:
631 temp[...] = output
632 output = temp
633 return output
636@_ni_docstrings.docfiller
637def correlate(input, weights, output=None, mode='reflect', cval=0.0,
638 origin=0):
639 """
640 Multidimensional correlation.
642 The array is correlated with the given kernel.
644 Parameters
645 ----------
646 %(input)s
647 weights : ndarray
648 array of weights, same number of dimensions as input
649 %(output)s
650 %(mode)s
651 %(cval)s
652 %(origin_multiple)s
654 Returns
655 -------
656 result : ndarray
657 The result of correlation of `input` with `weights`.
659 See Also
660 --------
661 convolve : Convolve an image with a kernel.
663 Examples
664 --------
665 Correlation is the process of moving a filter mask often referred to
666 as kernel over the image and computing the sum of products at each location.
668 >>> from scipy.ndimage import correlate
669 >>> input_img = np.arange(25).reshape(5,5)
670 >>> print(input_img)
671 [[ 0 1 2 3 4]
672 [ 5 6 7 8 9]
673 [10 11 12 13 14]
674 [15 16 17 18 19]
675 [20 21 22 23 24]]
677 Define a kernel (weights) for correlation. In this example, it is for sum of
678 center and up, down, left and right next elements.
680 >>> weights = [[0, 1, 0],
681 ... [1, 1, 1],
682 ... [0, 1, 0]]
684 We can calculate a correlation result:
685 For example, element ``[2,2]`` is ``7 + 11 + 12 + 13 + 17 = 60``.
687 >>> correlate(input_img, weights)
688 array([[ 6, 10, 15, 20, 24],
689 [ 26, 30, 35, 40, 44],
690 [ 51, 55, 60, 65, 69],
691 [ 76, 80, 85, 90, 94],
692 [ 96, 100, 105, 110, 114]])
694 """
695 return _correlate_or_convolve(input, weights, output, mode, cval,
696 origin, False)
699@_ni_docstrings.docfiller
700def convolve(input, weights, output=None, mode='reflect', cval=0.0,
701 origin=0):
702 """
703 Multidimensional convolution.
705 The array is convolved with the given kernel.
707 Parameters
708 ----------
709 %(input)s
710 weights : array_like
711 Array of weights, same number of dimensions as input
712 %(output)s
713 %(mode)s
714 cval : scalar, optional
715 Value to fill past edges of input if `mode` is 'constant'. Default
716 is 0.0
717 %(origin_multiple)s
719 Returns
720 -------
721 result : ndarray
722 The result of convolution of `input` with `weights`.
724 See Also
725 --------
726 correlate : Correlate an image with a kernel.
728 Notes
729 -----
730 Each value in result is :math:`C_i = \\sum_j{I_{i+k-j} W_j}`, where
731 W is the `weights` kernel,
732 j is the N-D spatial index over :math:`W`,
733 I is the `input` and k is the coordinate of the center of
734 W, specified by `origin` in the input parameters.
736 Examples
737 --------
738 Perhaps the simplest case to understand is ``mode='constant', cval=0.0``,
739 because in this case borders (i.e., where the `weights` kernel, centered
740 on any one value, extends beyond an edge of `input`) are treated as zeros.
742 >>> a = np.array([[1, 2, 0, 0],
743 ... [5, 3, 0, 4],
744 ... [0, 0, 0, 7],
745 ... [9, 3, 0, 0]])
746 >>> k = np.array([[1,1,1],[1,1,0],[1,0,0]])
747 >>> from scipy import ndimage
748 >>> ndimage.convolve(a, k, mode='constant', cval=0.0)
749 array([[11, 10, 7, 4],
750 [10, 3, 11, 11],
751 [15, 12, 14, 7],
752 [12, 3, 7, 0]])
754 Setting ``cval=1.0`` is equivalent to padding the outer edge of `input`
755 with 1.0's (and then extracting only the original region of the result).
757 >>> ndimage.convolve(a, k, mode='constant', cval=1.0)
758 array([[13, 11, 8, 7],
759 [11, 3, 11, 14],
760 [16, 12, 14, 10],
761 [15, 6, 10, 5]])
763 With ``mode='reflect'`` (the default), outer values are reflected at the
764 edge of `input` to fill in missing values.
766 >>> b = np.array([[2, 0, 0],
767 ... [1, 0, 0],
768 ... [0, 0, 0]])
769 >>> k = np.array([[0,1,0], [0,1,0], [0,1,0]])
770 >>> ndimage.convolve(b, k, mode='reflect')
771 array([[5, 0, 0],
772 [3, 0, 0],
773 [1, 0, 0]])
775 This includes diagonally at the corners.
777 >>> k = np.array([[1,0,0],[0,1,0],[0,0,1]])
778 >>> ndimage.convolve(b, k)
779 array([[4, 2, 0],
780 [3, 2, 0],
781 [1, 1, 0]])
783 With ``mode='nearest'``, the single nearest value in to an edge in
784 `input` is repeated as many times as needed to match the overlapping
785 `weights`.
787 >>> c = np.array([[2, 0, 1],
788 ... [1, 0, 0],
789 ... [0, 0, 0]])
790 >>> k = np.array([[0, 1, 0],
791 ... [0, 1, 0],
792 ... [0, 1, 0],
793 ... [0, 1, 0],
794 ... [0, 1, 0]])
795 >>> ndimage.convolve(c, k, mode='nearest')
796 array([[7, 0, 3],
797 [5, 0, 2],
798 [3, 0, 1]])
800 """
801 return _correlate_or_convolve(input, weights, output, mode, cval,
802 origin, True)
805@_ni_docstrings.docfiller
806def uniform_filter1d(input, size, axis=-1, output=None,
807 mode="reflect", cval=0.0, origin=0):
808 """Calculate a 1-D uniform filter along the given axis.
810 The lines of the array along the given axis are filtered with a
811 uniform filter of given size.
813 Parameters
814 ----------
815 %(input)s
816 size : int
817 length of uniform filter
818 %(axis)s
819 %(output)s
820 %(mode)s
821 %(cval)s
822 %(origin)s
824 Examples
825 --------
826 >>> from scipy.ndimage import uniform_filter1d
827 >>> uniform_filter1d([2, 8, 0, 4, 1, 9, 9, 0], size=3)
828 array([4, 3, 4, 1, 4, 6, 6, 3])
829 """
830 input = numpy.asarray(input)
831 if numpy.iscomplexobj(input):
832 raise TypeError('Complex type not supported')
833 axis = normalize_axis_index(axis, input.ndim)
834 if size < 1:
835 raise RuntimeError('incorrect filter size')
836 output = _ni_support._get_output(output, input)
837 if (size // 2 + origin < 0) or (size // 2 + origin >= size):
838 raise ValueError('invalid origin')
839 mode = _ni_support._extend_mode_to_code(mode)
840 _nd_image.uniform_filter1d(input, size, axis, output, mode, cval,
841 origin)
842 return output
845@_ni_docstrings.docfiller
846def uniform_filter(input, size=3, output=None, mode="reflect",
847 cval=0.0, origin=0):
848 """Multidimensional uniform filter.
850 Parameters
851 ----------
852 %(input)s
853 size : int or sequence of ints, optional
854 The sizes of the uniform filter are given for each axis as a
855 sequence, or as a single number, in which case the size is
856 equal for all axes.
857 %(output)s
858 %(mode_multiple)s
859 %(cval)s
860 %(origin_multiple)s
862 Returns
863 -------
864 uniform_filter : ndarray
865 Filtered array. Has the same shape as `input`.
867 Notes
868 -----
869 The multidimensional filter is implemented as a sequence of
870 1-D uniform filters. The intermediate arrays are stored
871 in the same data type as the output. Therefore, for output types
872 with a limited precision, the results may be imprecise because
873 intermediate results may be stored with insufficient precision.
875 Examples
876 --------
877 >>> from scipy import ndimage, misc
878 >>> import matplotlib.pyplot as plt
879 >>> fig = plt.figure()
880 >>> plt.gray() # show the filtered result in grayscale
881 >>> ax1 = fig.add_subplot(121) # left side
882 >>> ax2 = fig.add_subplot(122) # right side
883 >>> ascent = misc.ascent()
884 >>> result = ndimage.uniform_filter(ascent, size=20)
885 >>> ax1.imshow(ascent)
886 >>> ax2.imshow(result)
887 >>> plt.show()
888 """
889 input = numpy.asarray(input)
890 output = _ni_support._get_output(output, input)
891 sizes = _ni_support._normalize_sequence(size, input.ndim)
892 origins = _ni_support._normalize_sequence(origin, input.ndim)
893 modes = _ni_support._normalize_sequence(mode, input.ndim)
894 axes = list(range(input.ndim))
895 axes = [(axes[ii], sizes[ii], origins[ii], modes[ii])
896 for ii in range(len(axes)) if sizes[ii] > 1]
897 if len(axes) > 0:
898 for axis, size, origin, mode in axes:
899 uniform_filter1d(input, int(size), axis, output, mode,
900 cval, origin)
901 input = output
902 else:
903 output[...] = input[...]
904 return output
907@_ni_docstrings.docfiller
908def minimum_filter1d(input, size, axis=-1, output=None,
909 mode="reflect", cval=0.0, origin=0):
910 """Calculate a 1-D minimum filter along the given axis.
912 The lines of the array along the given axis are filtered with a
913 minimum filter of given size.
915 Parameters
916 ----------
917 %(input)s
918 size : int
919 length along which to calculate 1D minimum
920 %(axis)s
921 %(output)s
922 %(mode)s
923 %(cval)s
924 %(origin)s
926 Notes
927 -----
928 This function implements the MINLIST algorithm [1]_, as described by
929 Richard Harter [2]_, and has a guaranteed O(n) performance, `n` being
930 the `input` length, regardless of filter size.
932 References
933 ----------
934 .. [1] http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.42.2777
935 .. [2] http://www.richardhartersworld.com/cri/2001/slidingmin.html
938 Examples
939 --------
940 >>> from scipy.ndimage import minimum_filter1d
941 >>> minimum_filter1d([2, 8, 0, 4, 1, 9, 9, 0], size=3)
942 array([2, 0, 0, 0, 1, 1, 0, 0])
943 """
944 input = numpy.asarray(input)
945 if numpy.iscomplexobj(input):
946 raise TypeError('Complex type not supported')
947 axis = normalize_axis_index(axis, input.ndim)
948 if size < 1:
949 raise RuntimeError('incorrect filter size')
950 output = _ni_support._get_output(output, input)
951 if (size // 2 + origin < 0) or (size // 2 + origin >= size):
952 raise ValueError('invalid origin')
953 mode = _ni_support._extend_mode_to_code(mode)
954 _nd_image.min_or_max_filter1d(input, size, axis, output, mode, cval,
955 origin, 1)
956 return output
959@_ni_docstrings.docfiller
960def maximum_filter1d(input, size, axis=-1, output=None,
961 mode="reflect", cval=0.0, origin=0):
962 """Calculate a 1-D maximum filter along the given axis.
964 The lines of the array along the given axis are filtered with a
965 maximum filter of given size.
967 Parameters
968 ----------
969 %(input)s
970 size : int
971 Length along which to calculate the 1-D maximum.
972 %(axis)s
973 %(output)s
974 %(mode)s
975 %(cval)s
976 %(origin)s
978 Returns
979 -------
980 maximum1d : ndarray, None
981 Maximum-filtered array with same shape as input.
982 None if `output` is not None
984 Notes
985 -----
986 This function implements the MAXLIST algorithm [1]_, as described by
987 Richard Harter [2]_, and has a guaranteed O(n) performance, `n` being
988 the `input` length, regardless of filter size.
990 References
991 ----------
992 .. [1] http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.42.2777
993 .. [2] http://www.richardhartersworld.com/cri/2001/slidingmin.html
995 Examples
996 --------
997 >>> from scipy.ndimage import maximum_filter1d
998 >>> maximum_filter1d([2, 8, 0, 4, 1, 9, 9, 0], size=3)
999 array([8, 8, 8, 4, 9, 9, 9, 9])
1000 """
1001 input = numpy.asarray(input)
1002 if numpy.iscomplexobj(input):
1003 raise TypeError('Complex type not supported')
1004 axis = normalize_axis_index(axis, input.ndim)
1005 if size < 1:
1006 raise RuntimeError('incorrect filter size')
1007 output = _ni_support._get_output(output, input)
1008 if (size // 2 + origin < 0) or (size // 2 + origin >= size):
1009 raise ValueError('invalid origin')
1010 mode = _ni_support._extend_mode_to_code(mode)
1011 _nd_image.min_or_max_filter1d(input, size, axis, output, mode, cval,
1012 origin, 0)
1013 return output
1016def _min_or_max_filter(input, size, footprint, structure, output, mode,
1017 cval, origin, minimum):
1018 if (size is not None) and (footprint is not None):
1019 warnings.warn("ignoring size because footprint is set", UserWarning, stacklevel=3)
1020 if structure is None:
1021 if footprint is None:
1022 if size is None:
1023 raise RuntimeError("no footprint provided")
1024 separable = True
1025 else:
1026 footprint = numpy.asarray(footprint, dtype=bool)
1027 if not footprint.any():
1028 raise ValueError("All-zero footprint is not supported.")
1029 if footprint.all():
1030 size = footprint.shape
1031 footprint = None
1032 separable = True
1033 else:
1034 separable = False
1035 else:
1036 structure = numpy.asarray(structure, dtype=numpy.float64)
1037 separable = False
1038 if footprint is None:
1039 footprint = numpy.ones(structure.shape, bool)
1040 else:
1041 footprint = numpy.asarray(footprint, dtype=bool)
1042 input = numpy.asarray(input)
1043 if numpy.iscomplexobj(input):
1044 raise TypeError('Complex type not supported')
1045 output = _ni_support._get_output(output, input)
1046 temp_needed = numpy.may_share_memory(input, output)
1047 if temp_needed:
1048 # input and output arrays cannot share memory
1049 temp = output
1050 output = _ni_support._get_output(output.dtype, input)
1051 origins = _ni_support._normalize_sequence(origin, input.ndim)
1052 if separable:
1053 sizes = _ni_support._normalize_sequence(size, input.ndim)
1054 modes = _ni_support._normalize_sequence(mode, input.ndim)
1055 axes = list(range(input.ndim))
1056 axes = [(axes[ii], sizes[ii], origins[ii], modes[ii])
1057 for ii in range(len(axes)) if sizes[ii] > 1]
1058 if minimum:
1059 filter_ = minimum_filter1d
1060 else:
1061 filter_ = maximum_filter1d
1062 if len(axes) > 0:
1063 for axis, size, origin, mode in axes:
1064 filter_(input, int(size), axis, output, mode, cval, origin)
1065 input = output
1066 else:
1067 output[...] = input[...]
1068 else:
1069 fshape = [ii for ii in footprint.shape if ii > 0]
1070 if len(fshape) != input.ndim:
1071 raise RuntimeError('footprint array has incorrect shape.')
1072 for origin, lenf in zip(origins, fshape):
1073 if (lenf // 2 + origin < 0) or (lenf // 2 + origin >= lenf):
1074 raise ValueError('invalid origin')
1075 if not footprint.flags.contiguous:
1076 footprint = footprint.copy()
1077 if structure is not None:
1078 if len(structure.shape) != input.ndim:
1079 raise RuntimeError('structure array has incorrect shape')
1080 if not structure.flags.contiguous:
1081 structure = structure.copy()
1082 if not isinstance(mode, str) and isinstance(mode, Iterable):
1083 raise RuntimeError(
1084 "A sequence of modes is not supported for non-separable "
1085 "footprints")
1086 mode = _ni_support._extend_mode_to_code(mode)
1087 _nd_image.min_or_max_filter(input, footprint, structure, output,
1088 mode, cval, origins, minimum)
1089 if temp_needed:
1090 temp[...] = output
1091 output = temp
1092 return output
1095@_ni_docstrings.docfiller
1096def minimum_filter(input, size=None, footprint=None, output=None,
1097 mode="reflect", cval=0.0, origin=0):
1098 """Calculate a multidimensional minimum filter.
1100 Parameters
1101 ----------
1102 %(input)s
1103 %(size_foot)s
1104 %(output)s
1105 %(mode_multiple)s
1106 %(cval)s
1107 %(origin_multiple)s
1109 Returns
1110 -------
1111 minimum_filter : ndarray
1112 Filtered array. Has the same shape as `input`.
1114 Notes
1115 -----
1116 A sequence of modes (one per axis) is only supported when the footprint is
1117 separable. Otherwise, a single mode string must be provided.
1119 Examples
1120 --------
1121 >>> from scipy import ndimage, misc
1122 >>> import matplotlib.pyplot as plt
1123 >>> fig = plt.figure()
1124 >>> plt.gray() # show the filtered result in grayscale
1125 >>> ax1 = fig.add_subplot(121) # left side
1126 >>> ax2 = fig.add_subplot(122) # right side
1127 >>> ascent = misc.ascent()
1128 >>> result = ndimage.minimum_filter(ascent, size=20)
1129 >>> ax1.imshow(ascent)
1130 >>> ax2.imshow(result)
1131 >>> plt.show()
1132 """
1133 return _min_or_max_filter(input, size, footprint, None, output, mode,
1134 cval, origin, 1)
1137@_ni_docstrings.docfiller
1138def maximum_filter(input, size=None, footprint=None, output=None,
1139 mode="reflect", cval=0.0, origin=0):
1140 """Calculate a multidimensional maximum filter.
1142 Parameters
1143 ----------
1144 %(input)s
1145 %(size_foot)s
1146 %(output)s
1147 %(mode_multiple)s
1148 %(cval)s
1149 %(origin_multiple)s
1151 Returns
1152 -------
1153 maximum_filter : ndarray
1154 Filtered array. Has the same shape as `input`.
1156 Notes
1157 -----
1158 A sequence of modes (one per axis) is only supported when the footprint is
1159 separable. Otherwise, a single mode string must be provided.
1161 Examples
1162 --------
1163 >>> from scipy import ndimage, misc
1164 >>> import matplotlib.pyplot as plt
1165 >>> fig = plt.figure()
1166 >>> plt.gray() # show the filtered result in grayscale
1167 >>> ax1 = fig.add_subplot(121) # left side
1168 >>> ax2 = fig.add_subplot(122) # right side
1169 >>> ascent = misc.ascent()
1170 >>> result = ndimage.maximum_filter(ascent, size=20)
1171 >>> ax1.imshow(ascent)
1172 >>> ax2.imshow(result)
1173 >>> plt.show()
1174 """
1175 return _min_or_max_filter(input, size, footprint, None, output, mode,
1176 cval, origin, 0)
1179@_ni_docstrings.docfiller
1180def _rank_filter(input, rank, size=None, footprint=None, output=None,
1181 mode="reflect", cval=0.0, origin=0, operation='rank'):
1182 if (size is not None) and (footprint is not None):
1183 warnings.warn("ignoring size because footprint is set", UserWarning, stacklevel=3)
1184 input = numpy.asarray(input)
1185 if numpy.iscomplexobj(input):
1186 raise TypeError('Complex type not supported')
1187 origins = _ni_support._normalize_sequence(origin, input.ndim)
1188 if footprint is None:
1189 if size is None:
1190 raise RuntimeError("no footprint or filter size provided")
1191 sizes = _ni_support._normalize_sequence(size, input.ndim)
1192 footprint = numpy.ones(sizes, dtype=bool)
1193 else:
1194 footprint = numpy.asarray(footprint, dtype=bool)
1195 fshape = [ii for ii in footprint.shape if ii > 0]
1196 if len(fshape) != input.ndim:
1197 raise RuntimeError('filter footprint array has incorrect shape.')
1198 for origin, lenf in zip(origins, fshape):
1199 if (lenf // 2 + origin < 0) or (lenf // 2 + origin >= lenf):
1200 raise ValueError('invalid origin')
1201 if not footprint.flags.contiguous:
1202 footprint = footprint.copy()
1203 filter_size = numpy.where(footprint, 1, 0).sum()
1204 if operation == 'median':
1205 rank = filter_size // 2
1206 elif operation == 'percentile':
1207 percentile = rank
1208 if percentile < 0.0:
1209 percentile += 100.0
1210 if percentile < 0 or percentile > 100:
1211 raise RuntimeError('invalid percentile')
1212 if percentile == 100.0:
1213 rank = filter_size - 1
1214 else:
1215 rank = int(float(filter_size) * percentile / 100.0)
1216 if rank < 0:
1217 rank += filter_size
1218 if rank < 0 or rank >= filter_size:
1219 raise RuntimeError('rank not within filter footprint size')
1220 if rank == 0:
1221 return minimum_filter(input, None, footprint, output, mode, cval,
1222 origins)
1223 elif rank == filter_size - 1:
1224 return maximum_filter(input, None, footprint, output, mode, cval,
1225 origins)
1226 else:
1227 output = _ni_support._get_output(output, input)
1228 temp_needed = numpy.may_share_memory(input, output)
1229 if temp_needed:
1230 # input and output arrays cannot share memory
1231 temp = output
1232 output = _ni_support._get_output(output.dtype, input)
1233 if not isinstance(mode, str) and isinstance(mode, Iterable):
1234 raise RuntimeError(
1235 "A sequence of modes is not supported by non-separable rank "
1236 "filters")
1237 mode = _ni_support._extend_mode_to_code(mode)
1238 _nd_image.rank_filter(input, rank, footprint, output, mode, cval,
1239 origins)
1240 if temp_needed:
1241 temp[...] = output
1242 output = temp
1243 return output
1246@_ni_docstrings.docfiller
1247def rank_filter(input, rank, size=None, footprint=None, output=None,
1248 mode="reflect", cval=0.0, origin=0):
1249 """Calculate a multidimensional rank filter.
1251 Parameters
1252 ----------
1253 %(input)s
1254 rank : int
1255 The rank parameter may be less then zero, i.e., rank = -1
1256 indicates the largest element.
1257 %(size_foot)s
1258 %(output)s
1259 %(mode)s
1260 %(cval)s
1261 %(origin_multiple)s
1263 Returns
1264 -------
1265 rank_filter : ndarray
1266 Filtered array. Has the same shape as `input`.
1268 Examples
1269 --------
1270 >>> from scipy import ndimage, misc
1271 >>> import matplotlib.pyplot as plt
1272 >>> fig = plt.figure()
1273 >>> plt.gray() # show the filtered result in grayscale
1274 >>> ax1 = fig.add_subplot(121) # left side
1275 >>> ax2 = fig.add_subplot(122) # right side
1276 >>> ascent = misc.ascent()
1277 >>> result = ndimage.rank_filter(ascent, rank=42, size=20)
1278 >>> ax1.imshow(ascent)
1279 >>> ax2.imshow(result)
1280 >>> plt.show()
1281 """
1282 rank = operator.index(rank)
1283 return _rank_filter(input, rank, size, footprint, output, mode, cval,
1284 origin, 'rank')
1287@_ni_docstrings.docfiller
1288def median_filter(input, size=None, footprint=None, output=None,
1289 mode="reflect", cval=0.0, origin=0):
1290 """
1291 Calculate a multidimensional median filter.
1293 Parameters
1294 ----------
1295 %(input)s
1296 %(size_foot)s
1297 %(output)s
1298 %(mode)s
1299 %(cval)s
1300 %(origin_multiple)s
1302 Returns
1303 -------
1304 median_filter : ndarray
1305 Filtered array. Has the same shape as `input`.
1307 Examples
1308 --------
1309 >>> from scipy import ndimage, misc
1310 >>> import matplotlib.pyplot as plt
1311 >>> fig = plt.figure()
1312 >>> plt.gray() # show the filtered result in grayscale
1313 >>> ax1 = fig.add_subplot(121) # left side
1314 >>> ax2 = fig.add_subplot(122) # right side
1315 >>> ascent = misc.ascent()
1316 >>> result = ndimage.median_filter(ascent, size=20)
1317 >>> ax1.imshow(ascent)
1318 >>> ax2.imshow(result)
1319 >>> plt.show()
1320 """
1321 return _rank_filter(input, 0, size, footprint, output, mode, cval,
1322 origin, 'median')
1325@_ni_docstrings.docfiller
1326def percentile_filter(input, percentile, size=None, footprint=None,
1327 output=None, mode="reflect", cval=0.0, origin=0):
1328 """Calculate a multidimensional percentile filter.
1330 Parameters
1331 ----------
1332 %(input)s
1333 percentile : scalar
1334 The percentile parameter may be less then zero, i.e.,
1335 percentile = -20 equals percentile = 80
1336 %(size_foot)s
1337 %(output)s
1338 %(mode)s
1339 %(cval)s
1340 %(origin_multiple)s
1342 Returns
1343 -------
1344 percentile_filter : ndarray
1345 Filtered array. Has the same shape as `input`.
1347 Examples
1348 --------
1349 >>> from scipy import ndimage, misc
1350 >>> import matplotlib.pyplot as plt
1351 >>> fig = plt.figure()
1352 >>> plt.gray() # show the filtered result in grayscale
1353 >>> ax1 = fig.add_subplot(121) # left side
1354 >>> ax2 = fig.add_subplot(122) # right side
1355 >>> ascent = misc.ascent()
1356 >>> result = ndimage.percentile_filter(ascent, percentile=20, size=20)
1357 >>> ax1.imshow(ascent)
1358 >>> ax2.imshow(result)
1359 >>> plt.show()
1360 """
1361 return _rank_filter(input, percentile, size, footprint, output, mode,
1362 cval, origin, 'percentile')
1365@_ni_docstrings.docfiller
1366def generic_filter1d(input, function, filter_size, axis=-1,
1367 output=None, mode="reflect", cval=0.0, origin=0,
1368 extra_arguments=(), extra_keywords=None):
1369 """Calculate a 1-D filter along the given axis.
1371 `generic_filter1d` iterates over the lines of the array, calling the
1372 given function at each line. The arguments of the line are the
1373 input line, and the output line. The input and output lines are 1-D
1374 double arrays. The input line is extended appropriately according
1375 to the filter size and origin. The output line must be modified
1376 in-place with the result.
1378 Parameters
1379 ----------
1380 %(input)s
1381 function : {callable, scipy.LowLevelCallable}
1382 Function to apply along given axis.
1383 filter_size : scalar
1384 Length of the filter.
1385 %(axis)s
1386 %(output)s
1387 %(mode)s
1388 %(cval)s
1389 %(origin)s
1390 %(extra_arguments)s
1391 %(extra_keywords)s
1393 Notes
1394 -----
1395 This function also accepts low-level callback functions with one of
1396 the following signatures and wrapped in `scipy.LowLevelCallable`:
1398 .. code:: c
1400 int function(double *input_line, npy_intp input_length,
1401 double *output_line, npy_intp output_length,
1402 void *user_data)
1403 int function(double *input_line, intptr_t input_length,
1404 double *output_line, intptr_t output_length,
1405 void *user_data)
1407 The calling function iterates over the lines of the input and output
1408 arrays, calling the callback function at each line. The current line
1409 is extended according to the border conditions set by the calling
1410 function, and the result is copied into the array that is passed
1411 through ``input_line``. The length of the input line (after extension)
1412 is passed through ``input_length``. The callback function should apply
1413 the filter and store the result in the array passed through
1414 ``output_line``. The length of the output line is passed through
1415 ``output_length``. ``user_data`` is the data pointer provided
1416 to `scipy.LowLevelCallable` as-is.
1418 The callback function must return an integer error status that is zero
1419 if something went wrong and one otherwise. If an error occurs, you should
1420 normally set the python error status with an informative message
1421 before returning, otherwise a default error message is set by the
1422 calling function.
1424 In addition, some other low-level function pointer specifications
1425 are accepted, but these are for backward compatibility only and should
1426 not be used in new code.
1428 """
1429 if extra_keywords is None:
1430 extra_keywords = {}
1431 input = numpy.asarray(input)
1432 if numpy.iscomplexobj(input):
1433 raise TypeError('Complex type not supported')
1434 output = _ni_support._get_output(output, input)
1435 if filter_size < 1:
1436 raise RuntimeError('invalid filter size')
1437 axis = normalize_axis_index(axis, input.ndim)
1438 if (filter_size // 2 + origin < 0) or (filter_size // 2 + origin >=
1439 filter_size):
1440 raise ValueError('invalid origin')
1441 mode = _ni_support._extend_mode_to_code(mode)
1442 _nd_image.generic_filter1d(input, function, filter_size, axis, output,
1443 mode, cval, origin, extra_arguments,
1444 extra_keywords)
1445 return output
1448@_ni_docstrings.docfiller
1449def generic_filter(input, function, size=None, footprint=None,
1450 output=None, mode="reflect", cval=0.0, origin=0,
1451 extra_arguments=(), extra_keywords=None):
1452 """Calculate a multidimensional filter using the given function.
1454 At each element the provided function is called. The input values
1455 within the filter footprint at that element are passed to the function
1456 as a 1-D array of double values.
1458 Parameters
1459 ----------
1460 %(input)s
1461 function : {callable, scipy.LowLevelCallable}
1462 Function to apply at each element.
1463 %(size_foot)s
1464 %(output)s
1465 %(mode)s
1466 %(cval)s
1467 %(origin_multiple)s
1468 %(extra_arguments)s
1469 %(extra_keywords)s
1471 Notes
1472 -----
1473 This function also accepts low-level callback functions with one of
1474 the following signatures and wrapped in `scipy.LowLevelCallable`:
1476 .. code:: c
1478 int callback(double *buffer, npy_intp filter_size,
1479 double *return_value, void *user_data)
1480 int callback(double *buffer, intptr_t filter_size,
1481 double *return_value, void *user_data)
1483 The calling function iterates over the elements of the input and
1484 output arrays, calling the callback function at each element. The
1485 elements within the footprint of the filter at the current element are
1486 passed through the ``buffer`` parameter, and the number of elements
1487 within the footprint through ``filter_size``. The calculated value is
1488 returned in ``return_value``. ``user_data`` is the data pointer provided
1489 to `scipy.LowLevelCallable` as-is.
1491 The callback function must return an integer error status that is zero
1492 if something went wrong and one otherwise. If an error occurs, you should
1493 normally set the python error status with an informative message
1494 before returning, otherwise a default error message is set by the
1495 calling function.
1497 In addition, some other low-level function pointer specifications
1498 are accepted, but these are for backward compatibility only and should
1499 not be used in new code.
1501 """
1502 if (size is not None) and (footprint is not None):
1503 warnings.warn("ignoring size because footprint is set", UserWarning, stacklevel=2)
1504 if extra_keywords is None:
1505 extra_keywords = {}
1506 input = numpy.asarray(input)
1507 if numpy.iscomplexobj(input):
1508 raise TypeError('Complex type not supported')
1509 origins = _ni_support._normalize_sequence(origin, input.ndim)
1510 if footprint is None:
1511 if size is None:
1512 raise RuntimeError("no footprint or filter size provided")
1513 sizes = _ni_support._normalize_sequence(size, input.ndim)
1514 footprint = numpy.ones(sizes, dtype=bool)
1515 else:
1516 footprint = numpy.asarray(footprint, dtype=bool)
1517 fshape = [ii for ii in footprint.shape if ii > 0]
1518 if len(fshape) != input.ndim:
1519 raise RuntimeError('filter footprint array has incorrect shape.')
1520 for origin, lenf in zip(origins, fshape):
1521 if (lenf // 2 + origin < 0) or (lenf // 2 + origin >= lenf):
1522 raise ValueError('invalid origin')
1523 if not footprint.flags.contiguous:
1524 footprint = footprint.copy()
1525 output = _ni_support._get_output(output, input)
1526 mode = _ni_support._extend_mode_to_code(mode)
1527 _nd_image.generic_filter(input, function, footprint, output, mode,
1528 cval, origins, extra_arguments, extra_keywords)
1529 return output