Image-9 Bluescreen

Building on the earlier image manipulation and logic sections, here we see how to implement the "bluescreen" movie special effect.

Bluescreen

First: A Tale of 2 Pixels


a red pixel and a green pixel

Solution code:

  //Q1: make the red/green/blue numbers be the same, the pixels will look identical

  // copy over the 3 numbers with setXXX/getXXX
  // get from pixel2, set into pixel
  pixel.setRed(pixel2.getRed());
  pixel.setGreen(pixel2.getGreen());
  pixel.setBlue(pixel2.getBlue());

Bluescreen Stop Sign Example

Say we want to change the red part of sign to look like leaves
stop sign leaves background texture

Bluescreen Algorithm "Non Trivial"

bluescreen image/back algorithm

Bluescreen Example Code - Demo


image-bluescreen-1

 

The above bluescreen example code detects the red part of the sign, and for those pixels, copies over the pixels from the back image. The bluescreen code has 3 key differences from the earlier examples:

  1. back = new SimpleImage("leaves.jpg"); - open a second image and store it in the variable "back" (thus far we've only opened one image at a time)
  2. pixel2 = back.getPixel(x, y); - say we are looking at pixel x,y in the main image. From the other image get the pixel at the same x,y and store it in the variable "pixel2". We get the x and y of the current pixel in the loop with the functions pixel.getX() and pixel.getY().
  3. pixel.setRed(pixel2.getRed()); - copy the red value from pixel2 to pixel. Also do this for the other two colors. The result is that at this x,y location, the pixel is copied from the back to image.

Bluescreen Stop/Leaves Experiments - Your Try It

Try these on the above code.

  1. Flip -- try replacing everything-but-the-red with leaves instead of the red, i.e. "red-low" detection
  2. Sky -- try replacing the blue sky instead of the red areas of the sign. What color do you look for? Tune the * factor so only the sky is changed.
  3. Shorter -- make the code a little shorter by eliminating the need for "x" and "y" variables. Put the calls to pixel.getX() and pixel.getY() right in the back.getPixel(...) call.

Solution code:

    // flip: just change < to >

    // sky: if (pixel.getBlue() > avg * 1.1) {
    // This is a great example of tuning the * factor

    // pixel2 in one line:
    // pixel2 = back.getPixel(pixel.getX(), pixel.getY());

Monkey Bluescreen Example - You Try It

Now we'll do one like the movies -- film the movie start in front of a blue screen. Replace the blue background behind the monkey with pixels from moon.jpg.

Here is our monkey movie star:
monkey shown in front of blue background

Here is our background, the famous Apollo 8 photo of the earth shown rising above the moon horizon. There is a theory that this famous image helped start the environmental movement.
famous Apollo 8 photo of earth against a black background


image-bluescreen-2

 

Solution code:

image = new SimpleImage("monkey.jpg");
back = new SimpleImage("moon.jpg");
back.setAsBig(image);

for (pixel: image) {
  avg = (pixel.getRed() + pixel.getGreen() + pixel.getBlue())/3;
  // your code here
  if (pixel.getBlue() > avg * 0.92) {  // detect blue-high
    pixel2 = back.getPixel(pixel.getX(), pixel.getY());
    pixel.setRed(pixel2.getRed());
    pixel.setGreen(pixel2.getGreen());
    pixel.setBlue(pixel2.getBlue());
  }
}

print(image);

Selecting High vs. Low

monkey in front of blue background


image-bluescreen-3

 

Solution code:

    // red-high -> monkey
    if (pixel.getRed() > avg * 1.05) {

    // flip: red-low -> background
    if (pixel.getRed() < avg * 1.05) {

    // blue-low -> monkey
    if (pixel.getBlue() < avg * 0.95) {

    // blue-high -> background
    if (pixel.getBlue() > avg * 0.95) {

Note: back.setAsBig(image);

Looping over a main image and then grabbing pixels from a back image, there is a problem if the back image is smaller than the main image. The code will try to access a non-existent pixel, and we get an "x/y out of bounds" error. The following line, before the loop, fixes this problem by resizing the back image to be bigger if necessary. As a precaution, we'll include this line for the problems that grab x/y pixels from the back image.

  back.setAsBig(image);

Another Effect: Image Blend

A "blend" is another effect to try, making a "ghost" version of the monkey in the back image. We blend the colors from the two images instead of replacing entire pixels.


image-bluescreen-4

 

Solution code:

image = new SimpleImage("monkey.jpg");
back = new SimpleImage("paris.jpg");
back.setAsBig(image);

for (pixel: image) {
  avg = (pixel.getRed() + pixel.getGreen() + pixel.getBlue())/3;
  // your code here
  if (pixel.getBlue() < avg * 0.9) {  // detect monkey (blue-low)
    div = 2;  // monkey is divided by this variable below
    pixel2 = back.getPixel(pixel.getX(), pixel.getY());
    pixel2.setRed(pixel2.getRed() + pixel.getRed()/div);
    pixel2.setGreen(pixel2.getGreen() + pixel.getGreen()/div);
    pixel2.setBlue(pixel2.getBlue() + pixel.getBlue()/div);
  }
}
print(back);