Lab: Local Operators
CSC 262 - Computer Vision - Weinman
- Summary:
- We explore local pixel operations including gamma, bias,
and gain adjustments along with the more interesting histogram equalization.
Deliverables
- Script containing the commands used to process the images, and generate
the figures and your report as a single .m file.
- (5 points) Gamma-corrected image and observations (A.4)
- (10 points) Bias altered image, bias amount, and observations (A.6)
- (10 points) Gain altered image, gain amount, and observations (A.8)
- (10 points) Image histogram (B.7 )
- (10 points) Histogram observations (B.8)
- (5 points) Plot of cumulative distribution function (D.2)
- (10 points) Explanation of transfer function (D.3)
- (10 points) Histogram-equalized image and observations (D.8)
- (10 points) Histogram and observations (D.9)
- (10 points) Professionalism of write-up
Note: You may wish to use
subplot to include several images
in one figure box (i.e., the gamma-, bias-, and gain-adjusted images)
for ease of comparision. For example, see Figure 3.2 (p. 110) of Szeliski.
Extra
- (5 points) Plot of equalizing and linear transforms, Extra 4
- (5 points) Partially equalized image, Extra 5
Preparation
- Make sure you have understood the first part of Szeliski Section 3.1.4
"Histogram equalization"
- We will review transfer functions and histograms together at the beginning
of the lab session.
Exercises
A. Pixel Transforms
This first portion of the lab will call on you to make some basic
observations; try not to spend too much time on them just now. You
will want to make sure you have plenty of class time to work through
the remaining technical material. Once you have all the technical
aspects done, you can further explore values and their effects and
reflect on the results for your analysis.
- Matlab has a default search path for some demo images. One of these
is the cameraman.tif. Load this image using imread.
- The image is currently in an 8-bit format (values 0-255), which we'll
need for later. However, we'll also need a double version.
Create a copy that has double values in 0-1. (You learned
how to do this in earlier labs.)
- Create a version of this image (using the double representation)
that uses the gamma correction suggested by Equation (3.7) in Szeliski
and his suggested value for gamma, 2.2.
Recall that you must prepend a "." to explictly vectorize
an operator (such as exponentiation) so that you don't get a matrix
operator (such as matrix exponentiation).
-
Display and inspect this image. What differences
do you notice, if any?
- Equation (3.3) in Szeliski suggests a contrast and brightness adjustment
via a linear transformation. Create a version of the cameraman image
with a bias adjustment to visibly increase the brightness.
-
Display and inspect this image. What (non-obvious)
differences do you notice, if any? (E.g., don't just say "the image
is brighter")
- Create a version of the cameraman image with a gain adjustment
only (no bias) to visibly increase the contrast.
-
Display and inspect this image. What non-obvious
differences do you notice, if any?
B. Computing Histograms
-
Matlab has a built-in function for helping to visualize
histograms of images called imhist. Use this to display a
histogram of the original (8-bit) cameraman image.
- More often we will be creating histograms of quantities besides raw
images, so it is useful to know about the more general hist
function for creating histograms. Use this to display a histogram
of the image. For example,
-
hist(X(:));
Note that hist requires a vector; we can convert our image
to a vector to using the (:) indexing notation. Also, some
versions of Matlab don't like to use uint8 variables in hist,
so you may need to convert the vector to a double, but keeping the
values in the 0-255 range, as in
-
hist(double(X(:)));
Note: You should ignore Matlab's recommendation to use the
histogram command; its interface is strictly less useful
for the ease of our purposes.
- How many bins are used? Where (roughly) are they located?
- If you pass a second vector argument to hist, it will use
the values in the vector as the histogram bin centers. Because the
8-bit image contains numbers 0-255, it is natural to use these as
our bin centers. Create a histogram with the integers 0-255 as the
bin locations. This should look similar to the histogram created in
1, except it does not show you the brightness along
the bottom, only the brightness value (e.g numbers), because
the result is a simple bar chart.
- What if you want to save these values (counts) for processing? Assign
the result to a variable!
-
Xhist = hist(...
Save the histogram using 0-255 as the bins in a variable.
- The command bar(X,Y)
graphs a bar chart of the values in the vector Y at the locations
in the vector X (in the usual x vs. y fashion). Use
this to generate your own graph of the histogram you just saved.
-
Finally, use xlabel and ylabel
to give appropriate titles to the axes; use title to label
the graph.
-
What brightness levels in the histogram appear
to have the most pixels? Where do you expect to see the most detail
emerge from the equalization enhancement?
C. Image Mapping
While adjusting the gain of an image increases the contrast, it may
not necessarily allow us to see the most detail present in an image.
Spreading out the brightness values so that they are used uniformly
is often a useful of way doing this. First, we need to figure out
how to "map" one brightness value to another.
- Use the following commands to create a faint image of a square with
a hole in it.
-
squareImg = zeros(128,'uint8'); % Black background
squareImg(32:96,32:96) = 2; % Square
squareImg(48:80,48:80) = 1; % Hole
- Use imshow to display the image. It should be hard, if not
impossible to see the three levels since they are all very close (0,1
and 2 on a 0-256 scale).
- These pixel values can be used as indices into another array.
Use the following to create the 3-element brightness map
-
map = uint8([0 ; 128 ; 255]);
Notice how we have explicitly made these values 8-bit, so that imshow
interprets them correctly.
- Recall that nearly anything can be used as an index to an array, even
another vector or a matrix. Thus, we can use squareImg as
the index into the array map. What will be the result of
the following expression?
-
squareImgTform = map(squareImg);
Verify your answer. (You probably didn't get what you expect; if not,
read on!)
- There is one caveat: the values in squareImg are 0, 1, and
2, while the valid indices of map should be 1, 2, and 3. Thus, we
would need to add 1 to squareImg in order to index properly
(that is, without getting an error). What should the following produce?
-
squareImgTform = map(int16(squareImg)+1);
Display the result. Does it look as you expect?
Note: We need to convert squareImg to a wider integer
type so we can add one (to serve as an index to map) without
being clipped at 255.
- Experiment with a different set of values for map and construct
a new image. Make sure you understand what is happening before proceeding.
D. Histogram Equalization
Figure 3.7(b) in Szeliski (p. 116) displays the histogram of each
color channel. The plot in (c) contains the cumulative distribution
function (or
CDF), which is just the sum of all the values
to the left of each point in the histogram. Thus, you see the blue
curve ramp up very quickly because there are many values in the histogram
to the left. As we move right (increasing in brightness) there are
very few entries in the histogram. The CDF thus increases slowly because
there is not very much to add. Our end goal is to use the CDF function
to transform the histogram so that it is flat (yielding a CDF that
is a diagonal, straight-line ramp).
- You can calculate the cumulative sum of the elements in a vector (as
described above) using the function cumsum. Use this to create
the cumulative distribution function (CDF) from your histogram counts.
-
Plot the cumulative distribution function using
the plot(X,Y) command. (Don't forget to specify
the correct x-coordinates.) (Don't forget to label your axes!)
- What brightness range(s) have a steep slope? Diagonal slope? Nearly
horizontal slope? How do these CDF regions match the histogram shape?
What effect will they have on the image when the CDF is used as a
transfer function?
- Next, we need to transform the cumulative distribution function into
a proper mapping. That is, the entries should be brightness values
in the range 0-255. What is the smallest value in your cumulative
distribution function? What is the largest value?
- Create a scaled version of your cumulative distribution function so
that the smallest value is zero but the largest value is 255 (the
maximum brightness).
- Your scaled cumulative distribution function is likely a double
(confirm this). Because we want to use this scaled version as a map
like we did in Part C, we will need to cast these values using the
conversion function uint8. Do this to your new map.
- With the same technique you learned in part C, use the original (8-bit)
image as an index into your map (the scaled, 8-bit cumulative distribution
function). The result should be an image that has undergone histogram
equalization.
-
Display and inspect your image. What new
things do you notice, if any?
-
Display and inspect the histogram of your
new image. Does it have the properties you expect?
Extra Credit: Blending Maps
- Szeliski suggests that the result can be "flat" or "muddy"
and suggests creating a linear blend between the cumulative distribution
function and the identity transform (a straight line). Create a map
that is the identity transform.
- Create a new transform function (map) that is the weighted average
of your original map and your identity map (say, with an alpha of
0.75).
- Plot the original map and your blended map on the same axes (use hold
on between plot commands). The following example demonstrates
one way to change the color and line style of a plot
-
plot(X,Y,'k--');
In this case, the last argument indicates to use a black dashed line.
You may examine other options by reading the help for the plot
command.
-
Display your plot. How do the two maps
compare?
-
Display and inspect the image using
this blended map. How does it compare to the first equalized image?
The original image?
Acknowledgments
The cameraman image is owned by MIT and licensed for use in Matlab
demos by the Mathworks. There is an interesting
lengthy
history and layering of Matlab's default images.