Hide keyboard shortcuts

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. 

30 

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 

39 

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'] 

48 

49 

50def _invalid_origin(origin, lenw): 

51 return (origin < -(lenw // 2)) or (origin > (lenw - 1) // 2) 

52 

53 

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. 

58 

59 The lines of the array along the given axis are correlated with the 

60 given weights. 

61 

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 

72 

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 

97 

98 

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. 

103 

104 The lines of the array along the given axis are convolved with the 

105 given weights. 

106 

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 

117 

118 Returns 

119 ------- 

120 convolve1d : ndarray 

121 Convolved array with same shape as input 

122 

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) 

134 

135 

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() 

147 

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 

165 

166 

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. 

171 

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. 

188 

189 Returns 

190 ------- 

191 gaussian_filter1d : ndarray 

192 

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) 

218 

219 

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. 

224 

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. 

244 

245 Returns 

246 ------- 

247 gaussian_filter : ndarray 

248 Returned array of same shape as `input`. 

249 

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. 

258 

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]]) 

275 

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 

304 

305 

306@_ni_docstrings.docfiller 

307def prewitt(input, axis=-1, output=None, mode="reflect", cval=0.0): 

308 """Calculate a Prewitt filter. 

309 

310 Parameters 

311 ---------- 

312 %(input)s 

313 %(axis)s 

314 %(output)s 

315 %(mode_multiple)s 

316 %(cval)s 

317 

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 

341 

342 

343@_ni_docstrings.docfiller 

344def sobel(input, axis=-1, output=None, mode="reflect", cval=0.0): 

345 """Calculate a Sobel filter. 

346 

347 Parameters 

348 ---------- 

349 %(input)s 

350 %(axis)s 

351 %(output)s 

352 %(mode_multiple)s 

353 %(cval)s 

354 

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 

378 

379 

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. 

387 

388 Parameters 

389 ---------- 

390 %(input)s 

391 derivative2 : callable 

392 Callable with the following signature:: 

393 

394 derivative2(input, axis, output, mode, cval, 

395 *extra_arguments, **extra_keywords) 

396 

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 

420 

421 

422@_ni_docstrings.docfiller 

423def laplace(input, output=None, mode="reflect", cval=0.0): 

424 """N-D Laplace filter based on approximate second derivatives. 

425 

426 Parameters 

427 ---------- 

428 %(input)s 

429 %(output)s 

430 %(mode_multiple)s 

431 %(cval)s 

432 

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) 

450 

451 

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. 

456 

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(). 

468 

469 Examples 

470 -------- 

471 >>> from scipy import ndimage, misc 

472 >>> import matplotlib.pyplot as plt 

473 >>> ascent = misc.ascent() 

474 

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 

479 

480 >>> result = ndimage.gaussian_laplace(ascent, sigma=1) 

481 >>> ax1.imshow(result) 

482 

483 >>> result = ndimage.gaussian_laplace(ascent, sigma=3) 

484 >>> ax2.imshow(result) 

485 >>> plt.show() 

486 """ 

487 input = numpy.asarray(input) 

488 

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) 

494 

495 return generic_laplace(input, derivative2, output, mode, cval, 

496 extra_arguments=(sigma,), 

497 extra_keywords=kwargs) 

498 

499 

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. 

505 

506 Parameters 

507 ---------- 

508 %(input)s 

509 derivative : callable 

510 Callable with the following signature:: 

511 

512 derivative(input, axis, output, mode, cval, 

513 *extra_arguments, **extra_keywords) 

514 

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 

545 

546 

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. 

551 

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(). 

563 

564 Returns 

565 ------- 

566 gaussian_gradient_magnitude : ndarray 

567 Filtered array. Has the same shape as `input`. 

568 

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) 

584 

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) 

590 

591 return generic_gradient_magnitude(input, derivative, output, mode, 

592 cval, extra_arguments=(sigma,), 

593 extra_keywords=kwargs) 

594 

595 

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') 

617 

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 

634 

635 

636@_ni_docstrings.docfiller 

637def correlate(input, weights, output=None, mode='reflect', cval=0.0, 

638 origin=0): 

639 """ 

640 Multidimensional correlation. 

641 

642 The array is correlated with the given kernel. 

643 

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 

653 

654 Returns 

655 ------- 

656 result : ndarray 

657 The result of correlation of `input` with `weights`. 

658 

659 See Also 

660 -------- 

661 convolve : Convolve an image with a kernel. 

662 

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. 

667 

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]] 

676 

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. 

679 

680 >>> weights = [[0, 1, 0], 

681 ... [1, 1, 1], 

682 ... [0, 1, 0]] 

683 

684 We can calculate a correlation result: 

685 For example, element ``[2,2]`` is ``7 + 11 + 12 + 13 + 17 = 60``. 

686 

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]]) 

693 

694 """ 

695 return _correlate_or_convolve(input, weights, output, mode, cval, 

696 origin, False) 

697 

698 

699@_ni_docstrings.docfiller 

700def convolve(input, weights, output=None, mode='reflect', cval=0.0, 

701 origin=0): 

702 """ 

703 Multidimensional convolution. 

704 

705 The array is convolved with the given kernel. 

706 

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 

718 

719 Returns 

720 ------- 

721 result : ndarray 

722 The result of convolution of `input` with `weights`. 

723 

724 See Also 

725 -------- 

726 correlate : Correlate an image with a kernel. 

727 

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. 

735 

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. 

741 

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]]) 

753 

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). 

756 

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]]) 

762 

763 With ``mode='reflect'`` (the default), outer values are reflected at the 

764 edge of `input` to fill in missing values. 

765 

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]]) 

774 

775 This includes diagonally at the corners. 

776 

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]]) 

782 

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`. 

786 

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]]) 

799 

800 """ 

801 return _correlate_or_convolve(input, weights, output, mode, cval, 

802 origin, True) 

803 

804 

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. 

809 

810 The lines of the array along the given axis are filtered with a 

811 uniform filter of given size. 

812 

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 

823 

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 

843 

844 

845@_ni_docstrings.docfiller 

846def uniform_filter(input, size=3, output=None, mode="reflect", 

847 cval=0.0, origin=0): 

848 """Multidimensional uniform filter. 

849 

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 

861 

862 Returns 

863 ------- 

864 uniform_filter : ndarray 

865 Filtered array. Has the same shape as `input`. 

866 

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. 

874 

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 

905 

906 

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. 

911 

912 The lines of the array along the given axis are filtered with a 

913 minimum filter of given size. 

914 

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 

925 

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. 

931 

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 

936 

937 

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 

957 

958 

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. 

963 

964 The lines of the array along the given axis are filtered with a 

965 maximum filter of given size. 

966 

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 

977 

978 Returns 

979 ------- 

980 maximum1d : ndarray, None 

981 Maximum-filtered array with same shape as input. 

982 None if `output` is not None 

983 

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. 

989 

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 

994 

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 

1014 

1015 

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 

1093 

1094 

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. 

1099 

1100 Parameters 

1101 ---------- 

1102 %(input)s 

1103 %(size_foot)s 

1104 %(output)s 

1105 %(mode_multiple)s 

1106 %(cval)s 

1107 %(origin_multiple)s 

1108 

1109 Returns 

1110 ------- 

1111 minimum_filter : ndarray 

1112 Filtered array. Has the same shape as `input`. 

1113 

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. 

1118 

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) 

1135 

1136 

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. 

1141 

1142 Parameters 

1143 ---------- 

1144 %(input)s 

1145 %(size_foot)s 

1146 %(output)s 

1147 %(mode_multiple)s 

1148 %(cval)s 

1149 %(origin_multiple)s 

1150 

1151 Returns 

1152 ------- 

1153 maximum_filter : ndarray 

1154 Filtered array. Has the same shape as `input`. 

1155 

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. 

1160 

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) 

1177 

1178 

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 

1244 

1245 

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. 

1250 

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 

1262 

1263 Returns 

1264 ------- 

1265 rank_filter : ndarray 

1266 Filtered array. Has the same shape as `input`. 

1267 

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') 

1285 

1286 

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. 

1292 

1293 Parameters 

1294 ---------- 

1295 %(input)s 

1296 %(size_foot)s 

1297 %(output)s 

1298 %(mode)s 

1299 %(cval)s 

1300 %(origin_multiple)s 

1301 

1302 Returns 

1303 ------- 

1304 median_filter : ndarray 

1305 Filtered array. Has the same shape as `input`. 

1306 

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') 

1323 

1324 

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. 

1329 

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 

1341 

1342 Returns 

1343 ------- 

1344 percentile_filter : ndarray 

1345 Filtered array. Has the same shape as `input`. 

1346 

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') 

1363 

1364 

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. 

1370 

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. 

1377 

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 

1392 

1393 Notes 

1394 ----- 

1395 This function also accepts low-level callback functions with one of 

1396 the following signatures and wrapped in `scipy.LowLevelCallable`: 

1397 

1398 .. code:: c 

1399 

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) 

1406 

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. 

1417 

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. 

1423 

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. 

1427 

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 

1446 

1447 

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. 

1453 

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. 

1457 

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 

1470 

1471 Notes 

1472 ----- 

1473 This function also accepts low-level callback functions with one of 

1474 the following signatures and wrapped in `scipy.LowLevelCallable`: 

1475 

1476 .. code:: c 

1477 

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) 

1482 

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. 

1490 

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. 

1496 

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. 

1500 

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