Image Logic - If Statements

< Code In The Browser

If Statement

Our use of loops thus far have allowed us to write a little bit of code which is run for many data points. That's one big theme in computer code. The if-statement will add a second theme: the ability to write a true/false test, and only run a bit of code if the test is true. This will profoundly expand what we can do with code.

The if-statement has a true/false test which controls if some code is run or not. The if-statement syntax is:

if (x < 200) {     // "test", true if the value stored in x is less than 200
  print("hi");     // "body" code indented inside the if-statement
}

When run, the if-statement first evaluates the "test" inside the parenthesis to see if the test is true or false. If the test is true, the "body" code inside the curly braces { } of the if-statement is run. If the test is false, the body code is skipped. The various parts or the if-statement: the word "if", the parenthesis, the curly braces .. are all required (technically the braces are optional, but we will always include them). Indent the body code inside the braces, visually reflecting which lines are inside the if-statement (just as we indent the lines inside a for-loop).

For this section, we'll use this picture of a stop sign:

Writing an if-statement within an image loop, the if test can select certain pixels within the image to change, rather than changing every pixel as we did previously. Guess what this code does before running it:


Experiments to try on the above code: (pixel.getX() > 100), (pixel.getY() < 10), (pixel.getY() > 100), (100 < pixel.getY()) (this form is the same as the previous one, but we'll typically write in the form with the x first)

Any code can be inside the if { ... } body of course: the above body sets red/green to 0. Variants: set red/green to 0 and set blue to 255, set all to 0, set all to 255

If Color

Suppose we want to do something just to the red pixels on the sign, like make red parts of the stop sign into a pure blue color, as you might see on a vacation to a very strange country where they do stop signs their own way. What would an if statement look like that detects the red parts of the sign?

One approach is an if statement like this: if (pixel.getRed() > 160) { ...
i.e. if the red number is high, the pixel is probably part of the sign. The specific value, 160 or whatever, can be tuned by trying a few different values to get one that works best. Here's code that tries that strategy. Experiment with different values for the "160". If-Strategy: As you change the test, think if you want to make test more restrictive ("tighter") or less restrictive? When writing if-statements, deciding if you want the test to be more or less restrictive is a good first step.


The problem with the above approach is that the red value is high in two kinds of cases -- the red part of the sign we want, but also parts of the scene that are near white. Recall that pure white is (255, 255, 255), so in whitish areas, all three values are high, so our (red > 160) test gets those too -- the white letters inside the sign are a clear example of this problem.

If Color Average

A refinement to detect the "red" areas is to first compute the average value for each pixel (as we did previously). Then compare the red value to the average for each pixel. Rather than checking the literal value of the red (e.g. 160), this checks if the red is relatively large compared to the other two channels .. does the pixel lean towards redish. If the test is (pixel.getRed() > avg) we get all the areas that have every a tiny red cast, which is not restrictive enough. The fix is to multiply the avg by some factor to make it more restrictive, like this: (pixel.getRed() > avg * 1.5). As before, the specific value, 1.5, can be tuned by trying different values. Try the values: 1, 1.5, 2, 2.5. The larger the value, the higher the bar is set to detect red pixels. By adjusting the * 1.5 factor, this technique can nicely zero in on specific color areas.



If Color Exercises

1. Night Mode

Night mode: detect the blue sky and turn it dark. The tricky part is detecting the blue sky vs. the rest of the image. First try setting the sky pixels to pure black. That looks a little harsh. Try setting the values to around around 30, but with blue larger than the other two for a sort of dusky look.


2. Blue Letter Day (optional)

Rather than detect the red parts of the sign, detect the white parts. Set them to be pure blue, so we have blue letters on a red sign. How to detect the white areas?

Hint: a white area is one where all three colors are pretty high (say over 200). What will the average be for a white pixel?


This work was created by Nick Parlante and is released under the Creative Commons Share-Alike license 3.0