Revision 56951127715517cc9c5575fe800547352fe5823f (click the page title to view the current version)
Changes from 56951127715517cc9c5575fe800547352fe5823f to 4156203a63dc2a24f3a91b5bcb488d914186d12b
---
title: Image Filters
categories: tutorial
---
**Briefing** [Filters]()
# A simple blurring filter.
In addition to OpenCV, we need numpy for arrays and the signal
processing library from SciPy.
```python
import cv2 as cv
import numpy as np
import scipy.signal as sig
```
We need a test image which we convert to greyscale.
Here we use [lenna.ppm](http://www.hlevkin.com/hlevkin/TestImages/lenna.ppm),
which you have to download and place in your working directory.
```python
frame =cv.imread( "lenna.ppm" )
grey = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
```
Other test images can be found at the
[same source](http://www.hlevkin.com/hlevkin/06testimages.htm).
We display the image to check that everything works:
```python
cv.imshow("img",grey)
cv.waitKey(0)
```
## Averaging pixels
1. Consider the following python code. What does it do?
```python
(n,m) = grey.shape
new = np.zeros((n-6,m-6),dtype=np.uint8)
for i in range(n-6):
for j in range(m-6):
orig = grey[i:i+7,j:j+7]
new[i,j] = round(sum(orig.flatten())/49)
```
2. Run the python code. What does the matrix `new` look like?
3. Display `new` as an image and compare it to the original `grey`.
What is the visual effect?
What you should observe is a blurring effect.
Contours are smoothened by averaging a neighbourhood.
## Using a signal processing library
What we did above is such a standard operation that we have an API
therefore.
We can define a $7\times7$ averaging filter like this.
```python
f7 = np.ones((7,7)) / 49
```
+ What does this look like as a matrix?
To apply the filter to the image, we can use the standard
convolution operator as follows:
```python
g7 = sig.convolve2d(grey,f7).astype(np.uint8)
```
Note that we have to convert the result to integers explicitly,
lest OpenCV will not interpret it as an image.
The result can be displayed as
```python
cv.imshow("filtered",g7)
cv.waitKey(0)
```
+ Compare the two images. What does the filter do?
+ Compare the filtered image to the image `new` from
your manual averaging. Do they look different in any way?
The API has different methods to handle the boundaries.
We simply cropped a few pixel around the border, and thus `new`
may be smaller than images filtered with the API.
We can do the same thing using the OpenCV library, like this.
```python
c7 = cv.filter2D(grey,-1,f7)
```
The second argument (-1) specifies the colour depth of the output
which should be the same as for the input.
##
## Other test images
1. Download a couple of other test images that you can use.
It is instructive to use a few with very sharp edges, such as text,
as well as smoother images.
2. Using the procedures above, test how the filter works on different
images.
## Other smoothing filters
Test a couple of different filters in the same way, such as the following.
### Averaging filters
1. We can make square averaging filters with different sizes.
```python
f3 = np.ones((3,3)) / 9
f5 = np.ones((5,5)) / 25
f3 = np.ones((3,3)) / 9 # 3x3 averaging
f5 = np.ones((5,5)) / 25 # 5x5 averaging
f9 = np.ones((5,5)) / 81 # 9x9 averaging
```
2. We could make a circular averaging filter, such as this:
```python
circle = np.array([[0,0,1,1,1,0,0],
[0,1,1,1,1,1,0],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[0,1,1,1,1,1,0],
[0,0,1,1,1,0,0]])/37
```
Note that the divisor, 37, is the number of ones in the matrix.
3. Test different filters on different images. What do you see?
### A Gaussian filter
The Gaussian filter is a little trickier to implement, since we
want to be able to vary its parameters.
We use the Gaussian function
$$g(x,y) = \frac{1}{2\pi\sigma^2}\exp\frac{-(x^2+y^2)}{2\sigma^2},$$
where $\sigma$ is the standard deviation and $(x,y)$ is the pixel co-ordinates
with $(0,0)$ in the centre of the filter.
Firstly, the Gaussian function in `python` becomes
```python
def gauss(x,y,sigma=1):
c1 = 1/(2*np.pi*sigma**2)
c2 = 2*sigma**2
return c1*np.exp(-(x**2+y**2)/c2)
```
1. Check that the above code matches the mathematical formula.
We can make a list of lists of Gaussian coefficients in a simple
one-liner:
```python
B = [ [ gauss(x,y) for x in range(-t,t+1) ] for y in range(-t,t+1) ]
```
where `t` is an integer and the resulting filter is $(2t+1)\times(2t+1)$.
2. How does the above code work?
To turn `B` into a matrix, we do
```python
A = np.array(B)
```
3. Make the matrix `A`. What does the matrix look like?
4. The elements of the filter should add to one, to maintain the
luminence of the image.
You can check this by calculating
`sum(A.flatten()`.
What do you think, is this sufficiently close to one?
Why is it less than one?
5. We can normalise the filter by calculating
`AA = A/sum(A.flatten())`.
Why does this give unit sum?
6. Now, test the Gaussian filter on your test images.
Use a couple of different sizes, e.g. $t=3,7,11$,
and a couple of different standard deviations,
e.g. $\sigma=0.5,1,2$.
What do you observe?
## Noisy images