# Non-cyclic smoothing of a 2D image

I was wondering if there was a simple approach to smooth images, e.g using a Gaussian Kernel without introducing boundary effects which are also present when using Discrete Fourier Transforms? For both approaches, the missing pixels at the left-hand side will be taken from the right-hand side and vice versa.

Right now I have a 5x5 Gaussian Kernel which I move iteratively over my MxN image. Up to now, in case I reach the last pixel of the image, the operator automatically uses the first pixel and so on. Since my picture is not periodic I get artifacts even if I pad my picture on all sides with the intensity values of the corresponding adjacent column or row.

Do you gus have any suggestions?

Thanks!

• How much did you pad by? If the image is $N \times N$ and the kernel is $M \times M$, then the result will be of size $N + M - 1 \times N + M - 1$... so you need to zero-pad (not copy the pixel values) your image by M pixels in each direction.
– Peter K.
May 21, 2014 at 11:46
• the thing is when you zeropad your image, you would decrease the amplitude of your sides apparently. since I need the smoothed image for calculating some gradients this does not work. May 21, 2014 at 12:47
• I'm not sure what you mean by "decrease the amplitudes of your sides" ? Sure, the extra $M$ samples will be lower (just smearing the edges of the image), but you can just take the "centre" $N\times N$ pixels as the processed image, which should not have the problem you're saying.
– Peter K.
May 21, 2014 at 13:00
• What I was referring to is that when you zero-pad the boundaries but only smooth your original $N x N$ image, you still lower the amplitudes gradually starting from the side at each iteration. Say, I'd use a 3x3 kernel for smoothing. As soon as the center of my kernel reaches a boundary at $N$, the $0$ value from the padded boundary would contribute to that pixel in my original image. For the next step, this contribution would also contribute to the $N-1$ pixel and so on. May 21, 2014 at 13:13
• OK, I see. The solution might be as tbirdal suggests (adapt the kernel size near the edges) or another approach might be to re-scale the kernel (but keep it the same size) by the number of pixels that "fall off" the edge of the original image. That should get around your example. In the $3 \times 3$ case, centering the kernel on an edge (not corner) pixel would scale it by 9/6. For a corner pixel, it'd be 9/4... for a uniform-value kernel. You'll need to modify it based on the actual kernel values you're using.
– Peter K.
May 21, 2014 at 13:27

Make image of value 1 same size as original. Pad and smooth:

Divide original image by '1' image:

And crop:

MATLAB demo code:

I = double(imread('lena.tif'));
g = fspecial('gaussian',60,10);
A = ones(size(I));
imagesc(IA); colormap gray(256); pause;
I = IA(11:end-10,11:end-10);
imagesc(I); colormap gray(256); pause;


*Note: * MATLAB imfilter already does zero padding. The pad array step is not needed, it is just for demonstration. Actual code would be:

I = double(imread('lena.tif'));
g = fspecial('gaussian',60,10);
Ig = imfilter(I,g);
A = ones(size(I));
Ag = imfilter(A,g);;
Ismooth = Ig./Ag;


Well, padding is mainly the only option. However, what you could do is to shrink the size of the Gaussian Kernel as you approach the boundary. With this adaptive way of adjusting your kernel, you will lose smoothness as you approach the borders, but this could give you what you need in terms of smoothing. At least it doesn't introduce non-meaningful boundary conditions. Of course the smallest kernel size you could get down to is 3 and so you will have 1 column/row of junk values (you could also solve this problem a little bit by padding).

If you would like to get crazier, I would advice the following:

Copy your image into a padded one and inpaint the outer boundaries. Do it with an exampler approach such as PatchMatch(http://gfx.cs.princeton.edu/pubs/Barnes_2009_PAR/index.php). This way, you will be inpainting your image with reasonable values and then you could apply a standard Gaussian convolution.