# Documentation

## Basic Image Enhancement and Analysis Techniques

This example shows how to enhance an image as a preprocessing step before analysis. In this example, you correct the nonuniform background illumination and convert the image into a binary image so that you can perform analysis of the image foreground objects.

### Step 1: Read the Image into the Workspace

Read and display the grayscale image `rice.png` .

```I = imread('rice.png'); imshow(I) ```

### Step 2: Prepocess the Image to Enable Analysis

In the sample image, the background illumination is brighter in the center of the image than at the bottom. As a preprocessing step before analysis, make the background uniform and then convert the image into a binary image. To make the background illumination more uniform, create an approximation of the background as a separate image and then subtract this approximation from the original image.

As a first step to creating a background approximation image, remove all the foreground (rice grains) using morphological opening. The opening operation has the effect of removing objects that cannot completely contain the structuring element. To remove the rice grains from the image, the structuring element must be sized so that it cannot fit entirely inside a single grain of rice. The example calls the `strel` function to create a disk-shaped structuring element with a radius of 15.

```background = imopen(I,strel('disk',15)); ```

View the background approximation image as a surface to see where illumination varies. The `surf` command creates colored parametric surfaces that enable you to view mathematical functions over a rectangular region. Because the `surf` function requires data of class `double` , you first need to convert `background` using the `double` command. The example uses indexing syntax to view only 1 out of 8 pixels in each direction; otherwise, the surface plot would be too dense. The example also sets the scale of the plot to better match the range of the `uint8` data and reverses the y-axis of the display to provide a better view of the data. (The pixels at the bottom of the image appear at the front of the surface plot.) In the surface display, [0, 0] represents the origin, or upper-left corner of the image. The highest part of the curve indicates that the highest pixel values of background (and consequently `rice.png` ) occur near the middle rows of the image. The lowest pixel values occur at the bottom of the image.

```figure surf(double(background(1:8:end,1:8:end))),zlim([0 255]); set(gca,'ydir','reverse'); ```

Subtract the background approximation image, `background` , from the original image, `I`, and view the resulting image. After subtracting the adjusted background image from the original image, the resulting image has a uniform background but is now a bit dark for analysis

```I2 = I - background; imshow(I2) ```

Use `imadjust` to increase the contrast of the processed image `I2` by saturating 1% of the data at both low and high intensities and by stretching the intensity values to fill the `uint8` dynamic range.

```I3 = imadjust(I2); imshow(I3); ```

Create a binary version of the processed image so you can use toolbox functions for analysis. Use the `im2bw` function to convert the grayscale image into a binary image by using thresholding. The function `graythresh` automatically computes an appropriate threshold to use to convert the grayscale image to binary. Remove background noise with the `bwareaopen` function.

```level = graythresh(I3); bw = im2bw(I3,level); bw = bwareaopen(bw, 50); imshow(bw) ```

### Step 3: Perform Analysis of Objects in the Image

Now that you have created a binary version of the original image you can perform analysis of objects in the image.

Find all the connected components (objects) in the binary image. The accuracy of your results depends on the size of the objects, the connectivity parameter (4, 8, or arbitrary), and whether or not any objects are touching (in which case they could be labeled as one object). Some of the rice grains in the binary image `bw` are touching.

```cc = bwconncomp(bw, 4) cc.NumObjects ```
```cc = Connectivity: 4 ImageSize: [256 256] NumObjects: 95 PixelIdxList: {1x95 cell} ans = 95 ```

View the rice grain that is labeled 50 in the image.

```grain = false(size(bw)); grain(cc.PixelIdxList{50}) = true; imshow(grain); ```

Visualize all the connected components in the image. First, create a label matrix, and then display the label matrix as a pseudocolor indexed image. Use `labelmatrix` to create a label matrix from the output of `bwconncomp` . Note that `labelmatrix` stores the label matrix in the smallest numeric class necessary for the number of objects. Since `bw` contains only 95 objects, the label matrix can be stored as `uint8` . In the pseudocolor image, the label identifying each object in the label matrix maps to a different color in an associated colormap matrix. Use `label2rgb` to choose the colormap, the background color, and how objects in the label matrix map to colors in the colormap.

```labeled = labelmatrix(cc); RGB_label = label2rgb(labeled, @spring, 'c', 'shuffle'); imshow(RGB_label) ```

Compute the area of each object in the image using `regionprops`. Each rice grain is one connected component in the `cc` structure.

```graindata = regionprops(cc, 'basic') ```
```graindata = 95x1 struct array with fields: Area Centroid BoundingBox ```

Find the area of the 50th component, using dot notation to access the Area field in the 50th element of `graindata` .

```graindata(50).Area ```
```ans = 194 ```

Create a vector `grain_areas` to hold the area measurement of each object (rice grain).

```grain_areas = [graindata.Area]; ```

Find the rice grain with the smallest area.

```[min_area, idx] = min(grain_areas) grain = false(size(bw)); grain(cc.PixelIdxList{idx}) = true; imshow(grain); ```
```min_area = 61 idx = 16 ```

Using the `hist` command to create a histogram of rice grain areas.

```nbins = 20; figure, hist(grain_areas, nbins) title('Histogram of Rice Grain Area'); ```

Was this topic helpful?

Get trial now