# Replicating behavior of scipy.ndimate.gaussian\_filter

**URL:** <https://discourse.julialang.org/t/replicating-behavior-of-scipy-ndimate-gaussian-filter/32809>\
**Category:** General Usage\
**Tags:** images, python\
**Created:** [December 30, 2019, 9:29pm UTC](https://discourse.julialang.org/t/replicating-behavior-of-scipy-ndimate-gaussian-filter/32809 "2019-12-30T21:29:59Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![bensetterholm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bensetterholm/32/12792_2.png) [@bensetterholm](https://discourse.julialang.org/u/bensetterholm)\
**Post date:** [December 30, 2019, 9:29pm UTC](https://discourse.julialang.org/t/replicating-behavior-of-scipy-ndimate-gaussian-filter/32809/1 "2019-12-30T21:29:59Z")

</div>

I am trying to convert an old Python script to Julia. At one point, the script makes a call to `scipy.ndimage.gaussian_filter`, for which I presume the Julia equivalent should be `ImageFiltering.imfilter` with `Kernel.gaussian`. However, I cannot get the latter to replicate the output of the former.

Naively:

```nohighlight
julia> using ImageFiltering, PyCall

julia> a = reshape(1:25, (5,5)) .|> Float64
5×5 Array{Float64,2}:
 1.0 6.0 11.0 16.0 21.0
 2.0 7.0 12.0 17.0 22.0
 3.0 8.0 13.0 18.0 23.0
 4.0 9.0 14.0 19.0 24.0
 5.0 10.0 15.0 20.0 25.0

julia> py_filt = pyimport("scipy.ndimage").gaussian_filter(a, (1,0))
5×5 Array{Float64,2}:
 1.42704 6.42704 11.427 16.427 21.427 
 2.06782 7.06782 12.0678 17.0678 22.0678
 3.0 8.0 13.0 18.0 23.0   
 3.93218 8.93218 13.9322 18.9322 23.9322
 4.57296 9.57296 14.573 19.573 24.573 

julia> jl_naive = imfilter(a, Kernel.gaussian((1,0)))
5×5 Array{Float64,2}:
 1.35318 6.35318 11.3532 16.3532 21.3532
 2.05449 7.05449 12.0545 17.0545 22.0545
 3.0 8.0 13.0 18.0 23.0   
 3.94551 8.94551 13.9455 18.9455 23.9455
 4.64682 9.64682 14.6468 19.6468 24.6468

```

In this example, the first element is different by ~5%! Looking a bit deeper into the documentation for both functions, I notice that the default padding mode for the scipy function is “reflect” whereas Julia’s is “replicate”, however, changing this still does not yield the same array:

```nohighlight
julia> jl_reflect = imfilter(a, Kernel.gaussian((1,0)), "reflect")
5×5 Array{Float64,2}:
 1.70636 6.70636 11.7064 16.7064 21.7064
 2.10898 7.10898 12.109 17.109 22.109 
 3.0 8.0 13.0 18.0 23.0   
 3.89102 8.89102 13.891 18.891 23.891 
 4.29364 9.29364 14.2936 19.2936 24.2936

```

Also Julia’s ImageFiltering `reflect(Kernel.gaussian((1,0)))` has no effect.

These differences seem way too big to be due to floating point errors, so what else am I doing wrong?

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [December 31, 2019, 9:25am UTC](https://discourse.julialang.org/t/replicating-behavior-of-scipy-ndimate-gaussian-filter/32809/2 "2019-12-31T09:25:32Z")

</div>

From what I understand, there isn’t a single standard implementation of a fast discrete Gaussian filter, so neither version is “wrong” – they’re just different approximations:

> **[Gaussian filter | Digital implementation](https://en.wikipedia.org/wiki/Gaussian_filter#Digital_implementation)**
>
> The Gaussian function is for 
>   
>     
>       
> x
> ∈
> (
> −
> ∞
> ,
> ∞
> )
>       
>     
> {\\displaystyle x\\in (-\\infty ,\\infty )}
>   
> and would theoretically require an infinite window length. However, since it decays rapidly, it is often reasonable to truncate the filter window and implement the filter directly for narrow windows, in effect by using a simple rectangular window function. In other cases, the truncation may introduce significant er...

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [December 31, 2019, 2:11pm UTC](https://discourse.julialang.org/t/replicating-behavior-of-scipy-ndimate-gaussian-filter/32809/3 "2019-12-31T14:11:39Z")

</div>

To see if there’s a difference in kernel, filter

```julia
a = zeros(5, 5); a[3, 3] = 1

```

If those are the same, see if the difference can be explained by padding. Pad manually, filter the pre-padded image, and crop back.

---

<div class="post-metadata">

**Author:** ![bensetterholm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bensetterholm/32/12792_2.png) [@bensetterholm](https://discourse.julialang.org/u/bensetterholm)\
**Post date:** [December 31, 2019, 4:49pm UTC](https://discourse.julialang.org/t/replicating-behavior-of-scipy-ndimate-gaussian-filter/32809/4 "2019-12-31T16:49:12Z")

</div>

@GunnarFarneback Thank you very much! Playing around with padding and cropping, I found that what Scipy calls “reflect” padding is what ImageFiltering calls “symmetric”. Thus, setting this and the filter length to 9, I get the same result.

Cheers!

```nohighlight
julia> py_filt = pyimport("scipy.ndimage").gaussian_filter(a, (1,0))
5×5 Array{Float64,2}:
 1.42704 6.42704 11.427 16.427 21.427 
 2.06782 7.06782 12.0678 17.0678 22.0678
 3.0 8.0 13.0 18.0 23.0   
 3.93218 8.93218 13.9322 18.9322 23.9322
 4.57296 9.57296 14.573 19.573 24.573 

julia> jl_filt = imfilter(a, Kernel.gaussian((1,0), (9,1)), "symmetric")
5×5 Array{Float64,2}:
 1.42704 6.42704 11.427 16.427 21.427 
 2.06782 7.06782 12.0678 17.0678 22.0678
 3.0 8.0 13.0 18.0 23.0   
 3.93218 8.93218 13.9322 18.9322 23.9322
 4.57296 9.57296 14.573 19.573 24.573 

```
