-
So one theme in computers is this idea of
bulk operation. So we have this ...
-
right now with the for-
loop. So you can write a little bit of
-
code, and the computer takes care of
running that code thousands or millions of
-
times across some big data set. So another
theme is, this idea of logic or
-
selectivity. So, for this, we're gonna be
able to write a test, which is true or
-
false, and then use that to control if a
particular piece of code runs or not. And
-
so, that, in JavaScript is done with a
thing called the if-statement, and that'll
-
be the subject of this section. Combining
the if-statement, with the for-loop gives us
-
a very powerful combination. Both the sort
of reach to cover a lot of data, and the
-
selectivity to sorta pick exactly what we
want to do with, different parts of data.
-
So that'll work. That'll allow us to work
on many interesting problems. So here's the
-
syntax of an if-statement shown in the
context of a for-loop. So, it's right here.
-
So, it starts with the word if. And then,
that's followed by a part called the test,
-
which appears inside of parentheses. And
we're actually gonna spend most of our
-
energy sort of playing around with the
test. In this case, the test says, if
-
pixel.getRed is greater than 160, So
for now, our tests will, will pretty much
-
have this form. Basically, comparing one
number, versus another number. In this
-
case, I'm using greater than or the other
one. The one going the other way is the
-
less than. So following the, so what this
does is, obviously, just tests, for this
-
pixel, is the red value over 160 or not?
So that, that's just true or false. The
-
way the if-statement works is that the
test is followed by a set of curly braces,
-
just like for the for-loop. And inside
the curly braces, I'm gonna call that the
-
"then" code. And the "then" code could just be
any lines of code we want. So the way
-
the if-statement works, is that when it
runs, it evaluates the test. And the
-
tests can be, essentially for each
pixel, this test will be either true or
-
false. If it's true, the if-statement then
goes ahead and runs the "then"-code,
-
whatever that says to do. If the test is
false, then the "then"-code is just skipped.
-
So the if statement works as kind of a
switch. To just either enable or disable,
-
the code, inside the, inside the "then"-block here. So that, this pattern of having
-
the outer loop look at all the pixels, and
then inside of it putting an if-statement
-
to sort of control what we're going to do
in certain cases, that's going to work,
-
to solve, many interesting situations. So,
the, first problem I'll look at here. Is
-
suppose, is the, the stop sign. So suppose
I wanna take this stop sign and I wanna
-
change all of the red in the sign to be
blue, so it just looks like it looks like
-
a stop sign from Mars. So my first attempt
at this is. Gonna write the test. I'll
-
just, my test will be if pixel.getRed is
greater than 160. So that's just checking
-
if the red value is kind of large. And, so
that's here. And I can do whatever I want
-
in the "then"-code here. In this case
I'll just set red and green to zero and
-
blue to 255, so that will give us that
kind of blue appearance. Let's just try
-
that. So if I run it. So you can see
it's... It kind of works. The red parts of
-
the sign have been certainly obliterated
to look all blue. And then we've got some
-
areas over here and areas over here as
well. I should say this technique is, it's
-
an okay technique but we're going to
refine it to come up with something a
-
little bit better. One thing I want to
show is that this 160 here, there's
-
nothing really magic about that value. For
code like this, you would expect to sort
-
of play around with different values and
sort of adjust it so it looks the way you
-
want. So let's say I wanna... I wanna cover,
I wanna have less blue here. Then what I
-
would want is to make this test more
restrictive. Now, the way you can think
-
about it, is that, it's going through
thousands of pixels, and for each one,
-
it's checking the red value. And, in this
case, to say that the red value is over
-
160, it's sort of a hurdle. It's like, it
has to get over the 160. So if I were to
-
put a bigger number here, like, let's say,
200. And I run that. Well that's not much
-
difference. Alright, lets try even bigger.
How about 240. I run that. There we go.
-
You see what's happened is I've made the if, the if-test more restrictive. Sort of,
-
fewer pixels get by. And if I make it up
to 250. Really raise that thing. Then all,
-
the great majority of the pixels don't get
past the if-statement. There's just a few
-
remaining pixels scattered around here
that are, red enough to get past that
-
test. So it can go the other way too. So
instead of 160, I could go down to like,
-
let's say 100. I'm gonna lower the, the
hurdle. In that case, then. Yeah, we know.
-
Way to, many more pixels than I want end
up making the test. So that's kind of a
-
typical step for a lot the, the problems
we're gonna look at where we'll have some
-
num-, we'll, we'll have some structure we
want and then we'll be left with some
-
number that we kinda tweak up or down a
little bit to, to get it the way we want.
-
The other thing I can show here,
I'll set this back to 160 is the code, the
-
"then"-code could just do whatever. Now it's
under the control of the if-test. Here it
-
just sets it to blue but I could just as
easily say well, let's set red, green, and
-
blue all to zero. And if I run that, we
get a sort of a black stop sign instead. So
-
we'll, we'll use that sort of creativity
later to put different sorts of code in
-
the "then"-section. Alright, so scroll back
here, so this kinda works, I'm, I'm
-
getting the red sign. But I'm also
getting, it turns out I'm getting all the
-
white parts of the sign as well. This, our
test effectively gets both red and white.
-
And you can see that most clearly if you
just scroll back to see what the sign
-
looked like originally, right? It's got
these red areas, but it's also got,
-
obviously, these big white letters. And
we're just getting all of that. And. If I
-
look at this test again, you can sorta see
why that is. Well, I'm checking if just,
-
if red is greater than 160. And so when
does that happen? Well, one time that
-
happens is for a red pixel, you know, a
pixel that we think of as reddish. Where
-
the red value's gonna be high, and the
green and the blue will be kind of low. So
-
it'll be t-, let's say red is 200. It'll
be true then. But what about the white
-
pixels? So, a white pixel might have
values like, maybe, red, green, and blue
-
are all 220. All three numbers are high.
And because my test just looks at red, and
-
says, is it greater than 160? It's gonna
trip for the, the white pixels as well.
-
Both the white and the red pixels for both
of those this test will appear true. It
-
fails to distinguish those cases and
that's exactly what's happening here. The
-
red areas and the white areas both have
red values of high, that are high. And so
-
this test just... It's not, it's not quite
distinguishing in those cases. So, we want
-
to do a little bit better. So I'm going to
build up a better strategy that we could
-
use to solve this problem. So to get
started I want to make sort of a graphical
-
view. Of a pixel. Suppose I've got three
pixels. And each pixel obviously is going
-
to have red, green and blue values. And so
suppose what I did, is I made this little
-
bar chart. So here's the pixel on the
left, and here's the pixel in the middle,
-
and here's the pixel on the right. And all
I've done is, I've just graphed, the red,
-
green and blue values. And so, for any one
of these, I could ask, well, for that
-
pixel. Which color predominates? What sort
of cast does it have? So here for this
-
pixel, I'd say it's red. You can see the
red just sticks up the most. For this
-
middle pixel I would say blue. It has kind
of a blue cast. And here this pixel, even
-
though the pixel itself is much darker, I
would say that it has a greenish cast. In
-
all three of those cases what's going on
is. I think intuitively, we're kinda
-
looking at the three bars and asking well
which one pokes above the other two. And
-
that, that is a reasonable way of thinking
about well what color cast does that have?
-
So, I'll remind you, sort of have to bring
in here, in last section we had this idea
-
of the average of a-, of a pixel, so the
average was going to be, averaging the
-
red, green, and blue values to come up
with sort of an average between those
-
three. So I can combine that. With my
little bar chart here. Where for this
-
first pixel, I could take the red, green,
and blue values and average them and I
-
could think of that as sort of a line. And
the line is going to be kind of in the
-
middle of the heights of the bars. Because
it is right? It's going to be shorter than
-
the tallest one and taller than the
shortest one it's going to be kind of in
-
the middle somewhere. So with the average.
It, it allows us to pursue the earlier
-
strategy, but now it's a little more
concrete. We'd say, like, well, right.
-
This first one is reddish, and we see that
the red bar is poking above the average,
-
and the other two aren't. In this middle
one, we see that the blue bar is poking
-
above the average. And here, here we see
the green bar is poking above the average.
-
So, that just gives a kind of. A little
intuition about how it is I could decide
-
what cast a color has. The nice thing
about the average is it's just a number.
-
It's just a single number. And so it's
gonna be pretty easy to incorporate into
-
an if test. So for example, I, I could
write the tests. If pixel.getRed is
-
greater than average. Right, getRed is a
number. Average is a number. And then, if
-
you look at this left pixel, it's going to
be true. Yeah, the red is greater than the
-
average. And for these other two pixels,
it's going to be false. In both cases, the
-
red is below the average. And so, this
suggests sort of, the strategy I'm going
-
to pursue. For detecting what cast a pixel
has by first computing its average, and if
-
I wanna look for red or green or whatever
comparing that to the average to decide if
-
that cast is present. And this is
gonna work pretty well. So let me revisit
-
my stop sign problem. And now what I'm
going to do is for the test, as I was
-
describing earlier, I'm going to write the
test as pixel.getRed, greater than
-
average. And then, actually, I'm gonna
multiply times, sort of, an adjustment
-
factor. I'm just using the average, just
by itself, is, really is absolutely what
-
we want. We want some sort of a number
that we can tweak. So here's, here's the,
-
here's the real code down. So I'm, I'm
looping over the whole image. As in the
-
last section, I'm gonna just compute the
average between the red, green, and blue,
-
so I can use that for my comparisons. And
then here, I'm gonna write the if-test,
-
as, as, I've said. Is the red greater than
the average, and then, this is sort of the
-
adjustment factor that we'll play with.
Alright, so let's try that. All right. So
-
what we see is, I'm, we're getting the
sign pretty nicely, but, you know, there's
-
way too much extra blue over here. This is
just, we have to fix the adjustment
-
factor. So I'm just going to try, making
the hurdle a little higher. So if I say
-
1.3 here, make it a little higher, and
that cuts it down. We still have a little
-
bit over here. I could go up to, 1.8. Make
the hurdle much higher. Okay well you see
-
I get the sign but I, I lose this 4-way
thing here. Apparently those are slightly
-
different shades of red, so I'll go down
to, let's try, 1.4. There. I think, I think
-
1.4 looks pretty good. Right, where
there's a little bit of blue here, a
-
little bit of extra coloring over there
that I'm gonna tolerate, but it seems like
-
in terms of the sign, we've dialed in on
the red areas pretty nicely. So. So that
-
shows this technique, working pretty well.
I should just show that this factor, you
-
could also try numbers less than one, so I
could try like 0.9 and then it's like
-
super impressive. So I'll put this back to
1.4. There we go. That's nice. That's dialed in on the sign.
-
Alright, so let me try a second example of
this technique. I want you to imagine that
-
you're visiting Stanford sometime and you
park here and you get a parking ticket.
-
Now philosophically we know it's best to
sort of take in the world as it has
-
actually happened. Don't think too much
about what you wish had happened. However
-
in this case, we're gonna try and fix it,
fix history in code. So what I wanna do is
-
take this picture and fix the red curb to
not be red anymore, to be gray. So here's
-
the code for that. We'll try different
variants of this. So I've got a curve.jpg
-
is this image. I'm going to loop
through all the pixels and compute the
-
average. And so now we're left with. The
test. So I'll say if pixel.getRed is
-
greater than average. Whatever here, we'll
start with a factor of 1.5. And as my
-
first attempt at this problem, what I'm
gonna to do is set the pixels to just sort
-
of a middle gray, so 120, 120, 120. We'll
just sort of paint gray on there. Alright,
-
so let's try that. Alright so what we see
is, we're getting too, too little gray
-
here. So when you're adjusting one of
these if, if-tests, you always wanna
-
think, well, do you wanna make it more or
less restrictive? In this case, I wanna
-
make it less restrictive, right? I wanna
get the grey going along here. So I'm
-
gonna make the hurdle lower. So I'll try
1.4. Hm, that's getting there, let's try
-
1.3. Yeah keep going, how about 1.1. Oh,
too far. Okay, 1.2. Alright, so
-
this does a pretty good job. I've, I've
identified the red curb over here, and,
-
like, put this sort of flat 120-120-120
gray on there. If you look carefully, I'm
-
also catching a little bit of parts of the
plant that I guess had a little bit of red
-
cast. And actually, over here on the right
hand side, there's these plants that I
-
guess had sort of a red cast. And I'm, I'm
clobbing them up with this, right? With
-
this gray. So this is, you know, it's
pretty good. But what it says in the
-
problem statement here, is, actually, for
part (b). What I'd like to do is instead of
-
just changing this to 120-120-120 I wanna
use the technique from the previous
-
section, where I say "Well, look, let's
take the red parts of this image, and
-
change just those parts to be grayscale."
Previously I did an example where I would
-
change an entire image to grayscale. Now
I'm using the if-test to just pick out
-
certain regions of the image and just
change them to grayscale. And it just turns
-
out, this is gonna, this'll look better.
Beac.. All of this. Let's just see. So
-
remember the algorithm to change a pixel
to grayscale, is to first compute the
-
average for that pixel, which actually I'm
already doing here. And then with that
-
average number in hand then set the red,
green and blue values of the pixel to all
-
be that average. It happens for this code
that's a very small change, instead of
-
saying setRed(120). I'll just say setRed(avg), and likewise setGreen(avg) and setBlue(avg).
-
Let's try that. There we go. So you can
see here, I've mapped right, sorta put
-
gray. On here. And it looks a lot better.
Because, really, this red curb does have a
-
pattern of light and dark on it. And by
changing each pixel to be gray, but we're
-
still respecting the light and dark. So
that's why, that's why it looks better
-
here. Also notice the plants, over on the
right hand side here, that looked so bad
-
before. Well they were red plants before.
Now we've changed them to kind of gray
-
plants. But I think, you sort of can't
tell, like where it looks fine. So I think
-
that's a, you know, I think that's a nice
solution. All right here. So this just
-
restates, what I was just saying there.
So, I'd say the conclusion for the section
-
is, mainly, the, just the idea of, of an
if-statement, that combines a test with
-
some then code under the control of that
test. And then, I've done a couple
-
examples using this particular technique
to detect. Pixels of a certain color in an
-
image. So, you know, my standing example
of pixel.getRed greater than average times
-
some factor and using that's kinda dial in
on pixels of a certain color. And then
-
finally we've seen that the then code. Can
sort of do anything. It can change it to
-
blue or change it to red or whatever and
certainly we'll take advantage of that
-
flexibility for solving lots of problems.