Image Processing

In this lab we use the MyroC library's representation of images and practice passing 2D arrays to functions that alter their parameters.

Example Dot

The program white-picture-with-black-dot.c creates a white picture, places a [2 pixel by 2 pixel] black dot in the middle, and displays the result using rDisplayPicture from the MyroC library.

  1. Copy white-picture-with-black-dot.c to your account, compile and run it, and review how the program works.
    1. Note that this program does not utilize a Scribbler 2 robot, so no rConnect or rDisconnect statements are needed!
    2. The program uses the MyroC library, which includes definitions of Pixel and Picture. What happens if you define Pixel and Picture (as given in the reading) in this program as well?
    3. Variables whitePix and blackPix are declared and initialized at the start of the program. Review how a struct is defined and initialized, and explain what the expression = {0, 0, 0} does. What values are assigned to which fields within the whitePix struct?
    4. Review how the program places a black dot in the middle of the picture. Enhance the program to place a red dot near the top middle of the picture, a green dot near the left middle of the picture, and a blue dot near the middle bottom of the picture.
    5. Review the definition of rDisplayPicture in the MyroC header file.
      • Where is the text, "display of myArt", displayed?
      • What happens if the parameter 10 is changed to 20? to -3? to 0?

Initial Experiments with Pictures

  1. Write a function,
  2. void
    colorToGray (Picture * pic)
    which takes in a Picture* and then converts each pixel to its grayscale value, where the RGB channels at each pixel are all set to the same brightness value, calculated as
    (0.30 * red) + (0.59 * green) + (0.11 * blue)
    The calling function should then display the Picture. Test this out on a few pictures you take with your robot. Note:
    • A grayscale pixel will have identical values for the red, green, and blue components. Thus, in this problem you will need to compute the composite intensity using the formula above and assign that value to each component of the pixel.
    • The colorToGray should change the picture argument. Thus, the calling context will need to provide the address of the picture (e.g., &pix), and code within colorToGray will need to dereference the pointer to get the original picture (e.g., (*pic)).
  3. Write a function,
    setPictureMax (Picture * pic)
    which finds what the highest RGB value for each pixel is and sets that pixel to just that value—e.g., a pixel of RGB (50,135,85) will have a new RGB of (0,135,0). That is, setPictureMax should not change the RGB value of the channel with the highest value, but the other two colors should be set to 0.

    Your function should change the parameter, so the original picture in the calling procedure (e.g., in main) is changed. The main program then can display the picture. Test this out on a few pictures you take with your robot.

  4. Write a program flip-picture that takes a picture from the robot (using rTakePicture) and displays the picture for 5 seconds. The program should then flip the picture upside down and display the result for 5 seconds.

    Flipping a picture upside down requires swapping pixels in one row (e.g., near the top) with pixels in a corresponding row (e.g., near the bottom). In the swap, the column index of the swapped pixels will be the same, but the corresponding pixels in two rows will be interchanged.

    Note: If a and b are two values of type T, then interchanging the values in these variables cannot be done easily with simple assignments:

    a = b; /* BROKEN */
    b = a; /*  SWAP  */

    In this code, the original value of a is overwritten in the first assignment, so there is no way to give b the original value of a. Instead, in normal processing, interchanging the values of two variables requires an additional storage location:

    T temp = a;  /* declare temporary variable storing data of the relevant type */
    a = b;
    b = temp;

Transforming Pixel Arrays

  1. Write a program create-negative.c that changes each RGB value V of each pixel to 255 - V, and display the result.
  2. Write a program mirror-picture.c that takes a picture from the robot (using rTakePicture), displays the picture for 5 seconds, flips the picture left-to-right, and finally displays the result for 5 seconds

Find Bright Light

Consider the brightness of a pixel as being the sum of its R, G, and B values.

  1. Write a program find-brightest.c that takes a picture from the Scribbler 2's camera, and finds the coordinates of the brightest pixel. (If there are two pixels with the same brightness, the program could report any of the bright pixels—your choice.)
  2. Modify the program from the previous step, so that once the brightest pixel is found, the program draws a small red box around that location. (If thebox would go outside the picture, just draw the part of the boxwithin the picture itself.) Be sure your program displays the resulting picture with the identifying red box.
  3. Modify the previous two programs to consider the collective brightness of each 3-by-3 collection of pixels. That is, brightness will be computed as the sum of all pixels in a 3-by-3 square. Once found, the program should draw a small box around this bright region.