CS51 - Spring 2010 - Lecture 12
Computer vision demo
-
http://grail.cs.washington.edu/rome/
show
TargetIterative demo
- assume you have the following constants:
- private static final int MIN_OUTER = 20; // largest radius of the bullseye
- private static final int RING_GAP = 10; // the difference in radius between rings
- a few things to note
- the rings are centered around where you clicked
- a ring of radius r will have width and height 2*r
- implement this
look at
TargetIterative code
what if we now want to be able to drag the last made target around?
- to drag, we need a variable that references each of the FramedOvals as well as the final FilledOval
- since the target can be arbitrarily sized, this is challenging
recursive approach
- another way to view this is that the target is made up of a single outer ring, with a smaller target inside it
- a RingedTarget consists of an outer FramedOval with a smaller RingedTarget inside
- constructor
- parameters
- Location (where to draw it)
- radius
- canvas
- implementation
- create a new FramedOval
- reduce the radius by RING_GAP
- create a new RingedTarget
- what will happen if we just implement this as is?
- will shrink indefinitely until we get an error
- when do we want to stop?
- eventually we will be trying to create a new RingedTarget that is < MIN_OUTER
- instead of creating a RingedTarget, create a FilledOval for the center
- now we can create one class that extends WindowController and in onMouseClick, rather than have a while loop, we just create a new RingedTarget, which is a separate class
- how do we get the RingedTarget to move?
- two things:
- move the outer ring
- move the rest of the RingedTarget
- again, when will this stop?
- we need to check if the radius of our current RingedTarget is too small
- if it is, then move the FilledOval that is the center
- how would we write contains?
- just ask if the outer ring contains the point
this whole process is called recursion, in this case, structural recursion
- similar to mathematical induction
- we have the recursive case, where we define the structure with respect to itself
- our recursive case was to create another RingedTarget
- we have the base case, which is when everything should stop
- our base case was to create a FilledOval
- why do we need a base case?
- we need to know when to stop
- why did creating a FilledOval stop things?
- it's not a recursive structure, so once we create it, it stops
show RingedTargetSimple from
BullsEyeController code
- notice the check in the constructor to see whether we are in the base case or the recursive case
- similarly, in the move method, we move the outer ring and then check to see if we're in the base case
- how would we write the removeFromCanvas method?
- almost identical to move, except instead of calling move on the objects, call removeFromCanvas
- anything funny/weird about this code?
- all the RingedTargets have a FramedOval bullsEye, but on the very last one that's created actually uses it
- it's kind of annoying in the move method to have to check whether we're in the base case or the recursive case
- fundamentally, is there anything different between what we want to do to the recursive case (RingedTarget) vs. our base case (FilledOval)?
- what are the things that we want to do?
- move
- contains
- when we see shared behavior, what does this make us think?
- interface: look at the TargetInterface in
BullsEyeController code
TargetInterface
- RingedTarget implements TargetInterface already
- FramedOval does not... need to create a new class, we'll call it BullsEye
- look at BullsEye class
- mostly just a wrapper class around FramedOval
- notice that this class is NOT a recursive class. It is NOT defined with respect to itself.
- how does this help us?
look at RingedTarget class in
BullsEyeController code
- our innerRest variable is now of type TargetInterface
- in the constructor we can either assign a new RingedTarget to it OR a new BullsEye
- greatly simplifies the move and removeFromCanvas methods
- what would we need to change to add the moveTo method?
- change the TargetInterface
- add the moveTo method in both BullsEye and RingedTarget method
- need to keep track of the radius to do moveTo properly
- besides that, moveTo should look a lot like the move method
designing recursive programs
- describe the recursion in words...this should suggest the recursive and base classes, as well as the instance variables in each
- define an interface with all the methods that both the base and recursive cases must implement
- define the class(es) representing the base case(s)
- define the constructor(s) for the recursive class(es). The recursive calls in the constructor should create objects that are simpler than the one currently being constructed. In particular, eventually you should hit the base case.
- write each method in the recursive class(es) using the assumption that the method will work correctly on the simpler objects referred to by the instance variables
show
Broccoli demo
- describe the recursion in words:
- a "Broccoli" is a stem (line) with three other Broccolis to the left, center and right of the stem
- what things do we want Broccoli to be able to do (i.e. what should go in the interface)
- move
- contains
- what will the base case be and what does the class look like?
- base case is the flower at the end of the very end
- constructor
- green stem (Line)
- yellow bud (FilledOval)
- move
- move both the stem and the bud
- contains
- contains either the stem or the bud
- what does the constructor for Broccoli look like?
- construct the stem
- reduce the size of the next stem to be created!
- if the stem is still large enough
- construct three new Broccoli to the left, center and right of the end of the current Broccoli
- otherwise
- construct three new Flowers to the left, center and right of the end of the current Broccoli
- write the other methods?
- what will move look like?
- move the stem
- move the left, right and center (you write them assuming they work!)
- what about contains?
- if contains on either the stem, the left, the center or the right
look at
Broccoli code
- AngLine is another way for us to draw a line
- specify a starting location, a length and a direction (in reference to PI... 360 degress is 2 PI)
- what is PI/9?
- 180 degrees/9 = 20 degrees
- very simple code!
show
SimpleRecScribbler demo
look at lab 6