Chapter 2 introduced the SimpleCV shell and some of the most common commands. This appendix covers a few additional tricks for working with the shell, including:
Macros to automate tasks
Timing to test the performance on scripts
Not all vision system developers need to know this, but power users may find that these tricks help streamline the development process.
Chapter 2 described the SimpleCV shell as a tool for testing small snippets of code. However, when working with more than a few lines of code, it is often convenient to create reusable blocks of code. This is done with macros. Macro means big. In the case of a shell, this means a big block of code. Obviously, big is a relative term, in this case contrasted with the “micro” size of a few lines of code. Macros are most appropriate when testing or using the same block of code repeatedly. For example, macros are great for automatically setting up the camera object, loading a few images, or other repetitive initialization tasks.
Macros probably sound a bit like functions. However, macros do not take any parameters. The closest thing to a parameter with a macro is to create variables outside of the macro, set those variables to a desired value, and then reference those variables from inside the macro.
The SimpleCV shell already has macro support built in. Shell macros are created from the history of previously used commands. These commands are bundled together into a single macro. A macro can be thought of as a shortcut versus using the up-arrow to look up and execute a bunch of previously entered commands. Therefore, the first step in constructing the macro is to run the commands to be included in the macro. For example, in the SimpleCV shell, perform the following basic camera setup:
>>> from SimpleCV import Camera >>> cam = Camera() >>> img = cam.getImage()
Notice that each line of code entered in the shell has a line number
associated with it. For example, the first line of code is labeled with
SimpleCV:1
. The previously entered
example should look like Figure A-1.
Although the line numbers for the commands are displayed in the
SimpleCV prompt, the commands are interlaced with the output of those
commands. However, on most systems, the history
function lists all previous commands and
their line number.
>>> history 1: from SimpleCV import Camera 2: cam = Camera() 3: img = cam.getImage() 4: _ip.magic("history ")
Your actual line numbers may vary from the above description if you
issued other commands during your shell session. However, the overall
format should look similar. In particular, you should see the previously
entered commands to initialize the camera and snap a picture. The next
step is to create a macro to easily initialize the camera and grab a
picture. In our example, the commands involved correspond to the line
numbers 1 through 3. To create the macro, use the macro
command with the name to give the new
marcro and the appropriate line numbers to include in the macro. For
example, to create a macro named quickinit, and have
it execute the commands from lines 1 through 3:
>>> macro quickinit 1-3 Macro `quickinit` created. To execute, type its name (without quotes). Macro contents: from SimpleCV import Camera cam = Camera() img = cam.getImage()
The macro is now created. To execute it, simply type the macro’s name:
>>> quickinit >>> img.show()
To see a list of previously created macros, type the macro
command with no parameters:
>>> macro ['quickinit']
Because only one macro was previously created, only one is
displayed. If more are created, they would also be listed there. If you
want to save a macro to use in other sessions, you can use the store
command. In addition, to see a list of all
the commands that were included in a previously created macro, use the
print
command followed by the name of
the macro. To show the commands from the previously created quickinit
macro:
>>> print quickinit from SimpleCV import Camera cam = Camera() img = cam.getImage()
The above example is probably a bit inefficient. It is not necessary
to import the Camera library every time. In fact, the SimpleCV shell
automatically loads all of SimpleCV’s libraries, so no import statement is
even needed. Fortunately, it is possible to edit a previously created
macro using the edit
command.
>>> edit quickinit
On many Mac and Linux systems, the default editor for the edit
command is VI. VI is not the world’s
easiest editor for casual users. For more information on using VI, visit
http://www.vim.org and click on the link for their
documentation. It can be easy to get stuck on even basic commands like
saving or quitting. As a quick hint to those who may be stuck, press
i
when in VI in order to enter insert
mode to edit the file. To exit insert mode, press escape to be switched
back to command mode. From command mode, save the changes and quit VI by
entering :wq
(as in
write-quit).
The SimpleCV shell can also be used to work with external Python scripts. This can be helpful when testing and debugging files. For example, assume that the photo booth demo from Chapter 2 is saved in a file named photobooth.py. To run this from inside the shell, simply type:
>>> run photobooth.py
This will startup and run the photo booth application. To stop the execution, either click the close button on the window, or hit Control-C from inside the shell.
Notice that the messages in the application appear in a very small font in the middle of the screen. Wouldn’t it be better to increase the font size and put the message in the corner? It is easy to open and edit files directly in the shell. In fact, this was already demonstrated earlier. Simply type:
>>> edit photobooth.py
This opens the editor. Now go down to line 13 and change the
previous drawText()
command to:
img.drawText("Starting app. Left click to save photo", 0, 0, fontsize=50, color=Color().getRandom())
Next, go to line 30 to find the other drawText()
command and change it to:
img.drawText("Took a photo. Click the mouse to take another.", 0, 0, fontsize=50, color=Color().getRandom())
Now save and exit. The shell will save the file and instantly relaunch the program. This is rather convenient when repeatedly jumping back and forth between editing a file and then running to test the file.
Some of the feature detection and template matching algorithms can be complex and computationally intensive algorithms. When time matters, it is important to understand how long it takes a program to execute. For example, consider a security camera designed to detect people walking into a room. If the program takes five seconds just to process one image, then a person could sneak by between frames. Or another case where speed would matter would be a camera on an assembly line that needs to capture and process images fast enough to keep up with the flow of products. Fortunately, it is fairly easy to test a program, identify the bottlenecks, and tune the program to better align with the software design requirements.
The timeit
function is used to
time a given function. To see a basic example of how this works, consider
a basic blob detection example. This appears to run pretty quickly, but
how fast? Use the timeit()
function to
find out:
>>> img = Image('logo') >>> %timeit blobs = img.findBlobs(100)
The timeit
function actually runs
the specified line of code 100 times and find the best times. The output
from the function will be something like: 100
loops, best of 3: 2.12 ms per loop. This means that it takes
2.12 milliseconds to run that snippet of code. (Actual output will vary
from computer to computer.) Not too bad.
But still, the logo image is kind of small. It it relatively easy to find blobs on a small image because there is less data to process. What about for a larger image? For example, an HD camera
could be capturing images that are 1920×1280
. How much longer will that take? The
SimpleCV shell does not ship with a 1920×1280
version of an image, but it is
possible to fake one by scaling the built-in image to those
dimensions.
>>> img = Image('logo') >>> imgHD = img.resize(1920, 1280) >>> %timeit blobs = imgHD.findBlobs(100)
In this case, the computing time was 41.7 ms. Once again, the actual output time will vary, but it will probably require about 20 times more processing time than the original image. 40 milliseconds is still pretty quick, but this is a single line of code on a pretty simple image.
Need to speed up a program? One trick is to shrink the image size.
For example, a 640×480
image is a lot
easier to process than a full HD image.