Spring 2010 - CS477/577 - An Introduction to Computer Vision

Assignment Two

Due: Tuesday, February 2, 2010, late (i.e., before Wednesday 9am)

Credit: Approximately 4 points (Relative, and very rough absolute weighting)

This assignment must be done individually


You can do this assignment in either Matlab or C/C++.

It is probably a bit easier in Matlab, but doing some of the assignments in C may prove to be a useful exercise. If you think that vision research or programming may be in your future, you might want to consider doing some of the assignments in C/C++. If you are stretched for time, and like Matlab, you may want to stick to Matlab. Your choice!

Information for those working in C/C++.


Assignment specification

This assignment has three parts. The second part is only required for grad students.

To simplify things, you should hard code the file names in the version of your program that you give to the TA. You can assume that the TA will run the program in a directory that has the input files.

Part A

The file
    /cs/www/classes/cs477/spring08/ua_cs_only/assignments/rgb_sensors.txt 
is an ASCII file containing a 101 by 3 matrix representing estimates for the spectral sensitivities of a camera that the instructor used for his PHD work. There are 101 rows because the spectrophotometer used to determine them samples light at wavelengths from 380 to 780 nanometers in steps of 4 nanometers, inclusively.

For this assignment you need to write a program which does the following.

  1. Generate 2000 random light spectra. The standard random number generator is fine. (The spectra need to be positive). They each need to have 101 elements.
  2. Compute the (R,G,B) responses for the 2000 light spectra.

    Scale is arbitrary in this assignment. Real light spectra measured by our spectrophotometer that gives sensor responses in the range of (0,255) have power per wavelength of the order of 1e-4, not of the order of 1.0 as given by rand().

    Determine a scale factor, K, that scales (multiplies) your 2000 (R,G,B) so that the maximum of any of the (R,G,B) is 255. (You do not need to report this value).

    Multiply the randomly generated light spectra by K, and regenerate the (R,G,B). Verify that the max R,G,or B is now 255.

  3. Now simulate measurement error by adding random noise to the (R,G,B). Start with noise of the order 10. Since you scaled the data to (0,255), this is about 2.5%.

    (More specifically, generate random numbers in [-10,10] and add them to your (R,G,B).

  4. You now have a simulation of a camera calibration experiment. You have light spectra, and you have a bunch of responses. Use the least square method developed in class to estimate the camera sensitivities.
  5. Plot the "real" sensors and the estimated ones on the same plot. This is the only real deliverable. The TA will run your program and look at the plot. The TA might only take a brief glance at the code if the plot is reasonable.

Part B (only required for grad students).

Simulation is not reality. The file
    /cs/www/classes/cs477/spring08/ua_cs_only/assignments/light_spectra.txt
is a file of 598 real light energy spectra. Note that wavelength is now across columns (opposite to rgb_sensors.txt). The file
    /cs/www/classes/cs477/spring08/ua_cs_only/assignments/responses.txt 
are corresponding real (R,G,B).
  1. Estimate the camera sensitivities using this data. Again, the deliverable is a plot with both the real sensors and the estimated ones that will appear when the TA runs the code.
  2. Hopefully you will find that your sensors are terrible! Can you explain this (in the README)? Consider that the real light spectra came from a limited number of sources, through a limited number of filters, hitting a limited number of surfaces. Further, the reflectance spectra of most surfaces is smooth, which implies that they have limited dimension. For example, you can reconstruct them from a small set of sines and cosines (Fourier series).
  3. We can make things better by doing constrained least squares. For example we can insist that the solution vector is positive. Implement this. If you are doing this in Matlab, you will need to use a function like quadprog. (The way quadprog() is set up is a little different than what you might expect. Here is a link to a simple example if you are having trouble. If you are using the UA vision library (KJB library), then you will want to look at the man page for constrained_least_squares Again, plot the results.
  4. Hopefully you will now have positive sensors, but they are still weird. The problem is that they are not smooth. We can promote a smooth fit as follows. First, construct a matrix which can be used to multiply a spectra vector, and returns a second vector which is the successive differences of the elements of the input spectral. The matrix implements a simple derivative estimate. Ignore fence post error (i.e. you can compute 100 differences for a 101 element spectra). Hence, if M is the matrix, and R is a sensor response function (e.g. for the red channel), then D=M*R is a vector of 100 elements, where
            D    =    R      - R 
             i         i+1      i
    

    Further, introduce a scalar multiple of the above differencing matrix which we will refer to as lambda. You will tweak lambda below.

    We want a smooth function, so we want the differences to be small. In least squares, this means that we want them to be (approximately) zero. Augment your light_spectra matrix with another 100 rows that is the differencing matrix. Augment your response (R,G,B) matrix to have the desired result (zero).

    Verify for yourself that tweaking lambda adjusts the balance of fit and smoothness. You should be able to produce very smooth curves that do not resemble sensors, and curves approaching the ones in the previous part (of course, lambda == 0 should be exactly the same sensors as before).

    Note: Lambda implements the desired effect because in least squares any row can be weighted by simply multiplying both the row and the response by a scalar. (If the scalar were 2, this is exactly equivalent to duplicating the row.)

    Tweak lambda to give reasonable curves. Note that the curve for blue (leftmost, covering the smaller wavelengths) cannot be fit very well. Don't worry about this.

Part C

Below are links to two images. Dump these into a into a drawing program, and draw enough lines over the image to make a case that the image is either approximately in perspective or not. (Have a look at the building examples in the lecture notes if this is not making sense). You should understand and state your assumptions. To get you started: You can assume that that the chandelier is perfectly symmetric.

Your deliverables for this part of the assignment should be the PDFs of your image with lines drawn on them and an explanation of what you conclude.

Image one

Image two

Part D (Optional challenge problems)

Challenge problems are not for credit. They are for students who are especially interested in the subject, and who are comfortable with their understanding of the basics. They can be quite difficult, and I recommend being careful about spending too much time on them. Often, but not always, they will be discussed in the advanced vision seminar.

In class we learned that under perspective projection, parallel lines (generally) converge to a point. Can you prove this?

We also learned that under perspective projection, the vanishing points for sets of coplaner parallel lines are colinear. Can you prove this?


What to hand in

You should provide either a Matlab program or a C/C++ program that makes plots as described above. If you are working in C/C++, you should also provide source code and a Makefile. Grad students should try to answer the question regarding the cause of the messy pseudoinverse fit. Finally, you need a answer for question C in PDF.

To hand in the above, use the turnin program available on lectura (turnin key is cs477_hw2).

For those not familiar with turnin:

To hand in files using turnin you need to sign onto machine lectura, and make sure that the files you want to hand in are in a directory that lectura sees, and then change to that directory. Note that your home directory on the graphics machines and lectura is the same, so if you have just tested your program on a graphics machine, you have probably done all the file transferring that you need to do. To hand in file XXX, you would do the following:

turning cs477_hw2 XXX
To hand in multiple files, you can have additional files after the XXX, or do this multiple times. For a different assignment, you will need to use a different key (e.g., cs477_hw3).

For more detailed instructions, use:

    man turnin
on lectura.