CS100M Spring 2008
Project 4
Due Thursday 3/27 at 6pm

You must work either on your own or with one partner. You may discuss background issues and general solution strategies with others, but the project you submit must be the work of just you (and your partner). If you work with a partner, you and your partner must first register as a group in CMS and then submit your work as a group. 

Objectives

Completing this project will help you learn about 2D arrays, 3D arrays, and image manipulation in Matlab.

1. Image Manipulation Tools

In this problem, you are to write several Matlab functions to manipulate color images.  These functions are mostly just for fun since they manipulate images in ways that are visually interesting, but not very useful for standard photography.

  1. swap(A, layerA, layerB): returns the image array that results when layerA and layerB are swapped in image array A.  For example, below you can see a picture of the Cornell Law School followed by a version in which the red and the green layers are swapped.

     
  2. scale(A, redFactor, greenFactor, blueFactor): returns the image array that results when each layer of the image is scaled by (multiplied by) the specified scale factor.  For example, below you can see a picture created by using scale(A, 0.5, 1, 0.8).

     
  3. invert(A, layer): returns the image array that results when the specified layer (1, 2, or 3) is inverted in image array A. In other words, we replace each value v in the specified layer with the value (255 - v).  Below you can see a picture created by using invert(A, 3).

     
  4. modify(A, layer, func): return the image array that results when the specified layer (1, 2, or 3) is operated on by function func.  Func represents a function that takes a 2D image array and produces an altered 2D image array.  Here's a picture created by using modify(A, 1, @mirror).  As discussed in lecture Lecture 15, the @ symbol is used to tell Matlab that we are passing function mirror as an argument instead of trying to call the function mirror. The full text for function mirror is reproduced below the picture.

    function B = mirror( A )
    % Mirror (left-to-right) matrix A to produce matrix B.

    [m,n] = size(A);
    B = A(:,n:-1:1);

2. Hiding an Image

Computers have made it easy to transmit hidden data. Almost any large data file can be altered in small ways so that data is encoded in the file. Since pictures are large data files, they can be used to transmit extra information, particularly since the human eye is unable to detect small changes to images. You are to write two functions, one to hide a black-and-white image in a color image and the other to recover the original black-and-white image given both the original color image and the altered version. Example code using the two functions is shown below.

A = imread('pic.jpg');
B = imread('bwpic.jpg');
modifiedA = hide(B, A);
imwrite(modifiedA, 'modpic.bmp');
% We assume that both modpic and pic are transmitted
% The .bmp format does not do any compression, so no information is lost

% At the other end, we read in both pictures and recover the black and white image
A = imread('pic.jpg');
modifiedA = imread('modpic.bmp');
recoveredB = recover(A, modifiedA);

To keep our picture-hiding scheme simple, we require that the black-and-white picture has fewer rows and fewer columns than the color picture. Each pixel in the black-and-white picture is represented by a number of type uint8 (unsigned 8-bit number). For instance, the uint8 number 165 can be written as 128 + 32 + 4 + 1 which corresponds to the bit pattern 10100101. We hide this bit pattern by altering the corresponding pixel in each layer of the color picture. We do this by breaking the bit pattern like this: 10 10 01 01. We treat the first two bits as a binary number (in this case the number is 2) and add or subtract it from the corresponding pixel in the red layer. We have to allow for both adding or subtracting because we can't add if the red-layer value is near 255 and we can't subtract if the red-layer value is near 0. We continue across our number, storing the next 2 bits by adding or subtracting either 0, 1, 2, or 3 from the green-layer pixel. We do the same thing with the next two bits added or subtracted from the blue-layer pixel. We're left with 2 extra bits that we simply discard (this will cause us to loose some detail in our black-and-white picture, but we'll let this happen in order to keep our scheme simple).

To recover a picture, we do the same process in reverse. We can determine the bit-pattern for our black-and-white picture by finding the difference between the two color images.

Be careful here because the numbers are of type uint8. Such numbers are unsigned, so we can't represent negative numbers and there are no fractional parts when dividing uint8 numbers. You may want to experiment with uint8 numbers in the Matlab command window. When hiding the image, you should be able to pull out the appropriate bit-pairs by using division, multiplication, and subtraction.

The pictures below represent an original color-picture and an altered version of the same picture. If your recover function is correctly implemented then you should be able to recover a black-and-white image.