# CS425 Lab: Intensity Transformation and Spatial Filtering

## 1. Intensity Transformation Functions

### 1.1 Basic Idea

When you are working with gray-scale images, sometimes you want to modify the intensity values. For instance, you may want to reverse the black and the white intensities or you may want to make the darks darker and the lights lighter. An application of intensity transformations is to increase the contrast between certain intensity values so that you can pick out things in an image. For instance, the following two images show an image before and after an intensity transformation. Originally, the camera man's jacket looked black, but with an intensity transformation, the difference between the black intensity values, which were too close before, was increased so that the buttons and pockets became viewable. (This example is from the Image Processing Toolbox, User's Guide, Version 5 (MATLAB's documentation)--available through MATLAB's help menu or online at:
http://www.mathworks.com/access/helpdesk/help/toolbox/images/ ).

Original After Intensity Transformation

Generally, making changes in the intensity is done through Intensity Transformation Functions. The next sections talk about four main intensity transformation functions:

1. photographic negative (using `imcomplement`)
2. gamma transformation (using `imadjust`)
3. logarithmic transformations (using `c*log(1+f)`)
4. contrast-stretching transformations (using `1./(1+(m./(double(f)+eps)).^E`)

### 1.2 Photographic Negative

The Photographic Negative is probably the easiest of the intensity transformations to describe. Assume that we are working with grayscale double arrays where black is 0 and white is 1. The idea is that 0's become 1's, 1's become 0's, and any gradients in between are also reversed. In intensity, this means that the true black becomes true white and vise versa. MATLAB has a function to create photographic negatives--`imcomplement(f)`. The below shows a graph of the mapping between the original values (x-axis) and the `imcomplement` function.

The following is an example of a photographic negative. Notice how you can now see the writing in the middle of the tire better than before:

Original Photographic Negative

The MATLAB code that created these two images is:

```I=imread('tire.tif');
imshow(I)
J=imcomplement(I);
figure, imshow(J)
```

### 1.3 Gamma Transformations

With Gamma Transformations, you can curve the grayscale components either to brighten the intensity (when `gamma` is less than one) or darken the intensity (when `gamma` is greater than one). The MATLAB function that creates these `gamma` transformations is: ``` imadjust(f, [low_in high_in], [low_out high_out], gamma)```
`f` is the input image, `gamma` controls the curve, and `[low_in high_in]` and `[low_out high_out]` are used for clipping. Values below `low_in` are clipped to `low_out` and values above `high_in` are clipped to `high_out`. For the purposes of this lab, we use [] for both `[low_in high_in`] and `[low_out high_out]`. This means that the full range of the input is mapped to the full range of the output. The following plots the gamma transformations with varying gamma. Notice that the red line has gamma=0.4, which creates an upwards curve and will brighten the image.

The following shows the results of the three gamma transformations displayed in the plot above. Notice how the second one creates a darker image, whereas the last one creates an image with more contrast so that you can see the details of the tire.

Original (and gamma=1) gamma=3 gamma=0.4

The MATLAB code that created these three images is:

```I=imread('tire.tif');

imshow(J);
figure,imshow(J2);
figure,imshow(J3);
```

### 1.4 Logarithmic Transformations

Logarithmic Transformations can be used to brighten the intensities of an image (like the Gamma Transformation, where gamma <1). More often, it is used to increase the detail (or contrast) of lower intensity values. In MATLAB, the function used for Logarithmic transformations is:
`g = c*log(1 + double(f))`
The higher the `c`, the brighter the image will appear. The log function can produce values greater than one. The plot below shows three different plots of `c` with the y-values clipped at 1 for the plot of c=2 and c=5 (green and red lines, respectively).

The following shows the original image and the results of applying the three transformations from above. Notice that when c=5, the image is the brightest and you can see the radial lines on the inside of the tire (these lines are barely viewable in the original because there is not enough contrast in the lower intensities).

Original C=1
C=2 C=5

The MATLAB code that created these images is:

```I=imread('tire.tif');
imshow(I)
I2=im2double(I);
J=1*log(1+I2);
J2=2*log(1+I2);
J3=5*log(1+I2);
figure, imshow(J)
figure, imshow(J2)
figure, imshow(J3)
```

Any values greater than one, produced from the logarithmic transformation, are displayed as having a value of 1 (full intensity)

### 1.5 Contrast-Stretching Transformations

Contrast-Stretching Transformations result in increasing the contrast between the darks and the lights. Effectively, what you end up with is the darks being darker and the lights being lighter, with only a few levels of gray in between. To create a Contrast-Stretching Transformation in MATLAB, you can use the following function:
`g=1./(1 + (m./(double(f) + eps)).^E) `
`E` controls the slope of the function and `m` is the mid-line where you want to switch from dark values to light values. eps is a MATLAB constant that is the distance between 1.0 and the next largest number that can be represented in double-precision floating point. There are two plot/diagram sets below to represent the results of changing both `m` and `E`. The below plot shows different values of `E`.

The following shows the original image and the results of applying the three transformations from above. The `m` value used below is the mean of the image intensities (0.2104). Notice that at the highest `E` value (the red line above), the function becomes more like a thresholding function--the resulting image is more black and white than grayscale.

Original E=4
E=5 E=10

The MATLAB code that created these images is:

```I=imread('tire.tif');
I2=im2double(I);
m=mean2(I2)
contrast1=1./(1+(m./(I2+eps)).^4);
contrast2=1./(1+(m./(I2+eps)).^5);
contrast3=1./(1+(m./(I2+eps)).^10);
imshow(I2)
figure,imshow(contrast1)
figure,imshow(contrast2)
figure,imshow(contrast3)```

This second set plot/diagram shows how changes to `m` (using `E=4`) modifies the resulting images

The following shows the original image and the results of applying the three transformations from above. The `m` value used below is 0.2, 0.5, and 0.7. Notice that 0.7 produces a darker image with fewer details for this tire image.

Original m=0.2
m=0.5 m=0.7

The MATLAB code that created these images is:

```I=imread('tire.tif');
I2=im2double(I);
contrast1=1./(1+(0.2./(I2+eps)).^4)
contrast2=1./(1+(0.5./(I2+eps)).^4);
contrast3=1./(1+(0.7./(I2+eps)).^4);
imshow(I2)
figure,imshow(contrast1)
figure,imshow(contrast2)
figure,imshow(contrast3)```

## 2. Spatial Filtering

### 2.1. Why Use Spatial Filtering?

Spatial filtering is a technique that you can use to smooth, blur, sharpen, or find the edges of an image. The following four images are meant to demonstrate what spatial filtering can do. The original image is shown in the upper left-hand corner.

### 2.2. Basic Idea

First, it is good to know a little about the "spatial" aspect of "spatial filtering". There are two main types of filtering applied to images:

• spatial domain filtering
• frequency domain filtering

In a subsequent lab, we will talk about frequency domain filtering, which makes use of the Fourier Transform. For spatial domain filtering, we are performing filtering operations directly on the the pixels of an image.

Spatial Filtering is sometimes also known as neighborhood processing. Neighborhood processing is an appropriate name because you define a center point and perform an operation (or apply a filter) to only those pixels in predetermined neighborhood of that center point. The result of the operation is one value, which becomes the value at the center point's location in the modified image. Each point in the image is processed with its neighbors. The general idea is shown below as a "sliding filter" that moves throughout the image to calculate the value at the center location.

The following diagram is meant to illustrate in further details how the filter is applied. The filter (an averaging filter) is applied to location 2,2.

Notice how the resulting value is placed at location 2,2 in the filtered image.

The breakdown of how the resulting value of 251 (rounded up from 250.66) was calculated mathematically is:

`= 251*0.1111 + 255*0.1111 + 250*0.1111 + 251*0.1111 + 244*0.1111 + 255*0.1111 + 255*0.1111 + 255*0.1111 + 240*0.1111`

`= 27.88888 + 28.33333 + 27.77777 + 27.88888 + 27.11111 + 28.33333 + 28.33333 + 28.33333 + 26.66666 `

`= 250.66`

The following illustrates the averaging filter applied to location 4,4.

Once again, the mathematical breakdown of how 125 (rounded up from 124.55) was calculated is below:

`= 240*0.1111 + 183*0.1111 + 0*0.1111 + 250*0.1111 + 12*0.1111 + 87*0.1111 + 255*0.1111 + 0*0.1111 + 94*0.1111`

`= 26.6666 + 20.3333 + 0 + 27.7777 + 1.3333 + 9.6666 + 28.3333 + 0 + 10.4444`

`= 124.55 `

To further give you an idea of how spatial filtering is applied to an image, the following MATLAB code was written by Nova Scheidt:

```function img = myfilter(f, w)
%MYFILTER Performs spatial correlation
%   I=MYFILTER(f, w) produces an image that has undergone correlation.
%   f is the original image
%   w is the filter (assumed to be 3x3)
%   The original image is padded with 0's

% check that w is 3x3
[m,n]=size(w);
if m~=3 | n~=3
error('Filter must be 3x3')
end

%get size of f
[x,y]=size(f);

%create padded f (called g)
%first, fill with zeros
g=zeros(x+2,y+2);
%then, store f within g
for i=1:x
for j=1:y
g(i+1,j+1)=f(i,j);
end
end

%cycle through the array and apply the filter
for i=1:x
for j=1:y
img(i,j)=g(i,j)*w(1,1)+g(i+1,j)*w(2,1)+g(i+2,j)*w(3,1) ... %first column
+ g(i,j+1)*w(1,2)+g(i+1,j+1)*w(2,2)+g(i+2,j+1)*w(3,2)... %second column
+ g(i,j+2)*w(1,3)+g(i+1,j+2)*w(2,3)+g(i+2,j+2)*w(3,3);
end
end

%Convert to uint--otherwise there are double values and the expected
%range is [0, 1] when the image is displayed
img=uint8(img); ```

To apply the filter to the example above, the following calls were made:
(The 'stock_cut' image was modified from the gnome 2.14 icon set, available under GPL 2.0)

```w=[1/9 1/9 1/9
1/9 1/9 1/9
1/9 1/9 1/9]
results=myfilter(stock_cut,w);
imtool(results)```

### 2.3. Using imfilter

Instead of using the M-File from above, you can use a function that comes as part of the Image Processing Toolkit. You can call it in the same way that `myfilter` was called above:

`results=imfilter(stock_cut, w); `

`imfilter` is more powerful than the simple `myfilter`. The following table, modified from page 94 of Digital Image Processing, Using MATLAB, by Rafael C. Gonzalez, Richard E. Woods, and Steven L. Eddins, summarizes the additional options available with `imfilter`.

Options Description
Filtering mode
'corr' Filtering is done using correlation. This is the default.
'conv' Filtering is done using convolution.
Boundary Options
P The boundaries of the input image are extended by padding with a value, P (written without quotes). This is the default, with value 0.
'replicate' The size of the image is extended by replicating the values in its outer border.
'symmetric' The size of the image is extended by mirror-reflecting it across its border.
'circular' The size of the image is extended by treating the image as one period a 2-D periodic function.
Size Options
'full' The output is of the same size as the extended (padded) image.
'same' The output is of the same size as the output. This is achieved by limiting the excursions of the center of the filter mask to points contained in the original image. This is the default.

The following subsections discuss the `imfilter` options.

#### 2.3.1 Imfilter--Boundary Options

The example above deliberately applied the filter at location 2,2. This is because there is an inherent problem when you are working with the corners and edges. The problem is that some of the "neighbors" are missing. Consider location 1,1:

In this case, there are no upper neighbors or neighbors to the left. Two solutions, zero padding and replicating, are shown below. The pixels highlighted in blue have been added to the original image:

Zero padding is the default. You can also specify a value other than zero to use as a padding value.

Another solution is replicating the pixel values along the edges:

As a note, if your filter were larger than 3x3, then the "border padding" would have to be extended. For a filter of size 3x3, 'replicate' and 'symmetric' yield the same results.

The following images show the results of the four different boundary options. The filter used below is a 5x5 averaging filter that was created with the following syntax:
`h=fspecial('average',5)`

 ```results1=imfilter(cat,h); figure,imshow(results1) title('Zero-Padded')``` ```results2=imfilter(cat,h,'replicate'); figure,imshow(results2) title('Replicate')``` ```results3=imfilter(cat,h,'symmetric'); figure,imshow(results3) title('Symmetric')``` ```results4=imfilter(cat,h,'circular'); figure,imshow(results4) title('Circular')```

The disadvantage of zero padding is that it leaves dark artifacts around the edges of the filtered image (with white background). You can see this as a dark border along the bottom and right-hand edge in the zero-padded image above.

#### 2.3.2 Imfilter--Filtering Mode (Correlation versus Convolution)

With `imfilter`, you can choose one of two filtering modes: correlation or convolution. The difference between the two is that convolution rotates the filter by 180o before performing multiplication. The following diagram is meant to demonstrate the two operations for position 3, 3 of the image:

This example is for demonstration purposes only. You will notice that the resulting values are not in the range of [0, 255]. To get better results, you can normalize the filter (in this case, divide by 45).

The following MATLAB code demonstrates correlation and convolution:

```h=[1 2 3
4 5 6
7 8 9];
h=h/45;
result_corr=imfilter(cat,h);   %correlation is the default, you can also send 'corr' as an argument
result_conv=imfilter(cat,h,'conv');

```

#### 2.3.3 Imfilter--Size Options

There are two size options 'full' and 'same'. The 'full' will be as large as the padded image, where as 'same' will be the same size as the input image.

To create a 'full' and 'same' image, you can use the following MATLAB syntax:

```h =[0.1111 0.1111 0.1111
0.1111 0.1111 0.1111
0.1111 0.1111 0.1111];
stock_cut_same=imfilter(stock_cut,h);  %'same' is the default, but you can also include it as an argument
stock_cut_full=imfilter(stock_cut,h,'full');```
If you use `imtool` to view both of these images, you will note that the 'same' is 16x16, whereas 'full' is 18x18.

### 2.4. Creating Special Filters

You can define the filters for spatial filtering manually or you can call a function that will create the filter matrices. The function, called `fspecial`, requires an argument that specifies the kind of filter you would like. A full description of `fspecial` is available in MATLAB help--type: ``` doc fspecia```l

The following table is meant to show you three filters, created by `fspecial`, and the results on an image of a cat:

MATLAB Code Resulting Image
```%original picture
figure, imshow(cat) ```
```%motion blur
h=fspecial('motion', 20, 45);
cat_motion=imfilter(cat,h);
figure, imshow(cat_motion)
```
```%sharpening
h=fspecial('unsharp');
cat_sharp=imfilter(cat,h);
figure, imshow(cat_sharp)
```
```%horizontal edge-detection
h=fspecial('sobel');
cat_sobel=imfilter(cat,h);
figure, imshow(cat_sobel)
```

## 4. Exercises

### Part 1

Given the image of the liftingbody.png:

`lifting = imread('liftingbody.png');`

Identify which intensity transformation created the following images. Try to create these images by using the individual intensity transformations or the `intrans` function on `lifting`:

Note: you can click on the individual images to see a larger, more detailed version of the transformed image.

### Part 2: Spatial Filtering

1. Download the following image "two_cats.jpg" and store it in MATLAB's "Current Directory".
2. Load the image data.
3. Use a spatial filter to get the horizontal edge of the image.
4. Use a spatial filter to get the vertical edge of the image (read the MATLAB documentation on fspecial).
5. Add the horizontal edge matrix to the vertical edge matrix to yield the following results:

#### Deliverables:

• image of horizontal edge
• image of vertical edge
• image of horizontal and vertical edge combined