Christopher Wellons
mosquitopsu@gmail.com
Public GPG Key
Post Index - see a list of all of the entries.
I am a computer engineer working at the Johns Hopkins University Applied Physics Laboratory. I love computers and free software.
Most of the topics you will find here are about hobby computing and programming with free software (and a few exceptions).
E-mail me: mosquitopsu@gmail.com
Projects:
- Brainfuck Compiler
- PNG Archiver
- BINI Tools
-
Parallel Mandelbrot Generator
Archives:
September 2007
October 2007
November 2007
December 2007
January 2008
February 2008
March 2008
April 2008
June 2008
July 2008
August 2008
September 2008
I wanted to try making one of those movie montage things I wrote about earlier into a nice poster that could be hung on a wall. Now, I prefer a Spartan environment whenever possible, so I really did not want to have my own poster. No decorations for me, please. I just wanted to make one. My solution? Make one for my sister, who has lots of junk and would enjoy having one. Her favorite movie is Pirates of the Caribbean, so I used this movie, which she conveniently already had on DVD.
As before, I used mplayer to rip all of the frames I
needed. To get a poster-quality version I would need better
resolution. To do this, I changed the frame output image size to
160x90 (100 times bigger than before).
[...] framestep=30,scale=160:90 [...]
Next, I used my own montage script to put these frames together. My script took about 2 minutes to put together one of these larger montages. Finally, I used the GIMP to add a black border and simple title at the top. Since I don't have any more than 512MB of memory on my computers, I actually had to scale the image down to 1/4 of its original size to do this. Before scaling, the GIMP was spending hours just adding the border because it was thrashing the hard drive. It needed about 2G of memory and it was using the hard drive to get it.
I took my giant image to FedEx Kinko's where they printed it to a 2'x2' poster for 30 bucks. Here are the results, taken using my sister's crappy Kodak camera (never buy Kodak digital cameras, as they all suck!). To help see what is going on, I provided a glare version and a non-glare version. Each shows different details.
Here is the normal version from before for comparison.
I had written a previous post called Movie DNA where I described a simple way of distilling an entire movie down to a single frame. It involved the use of two tools, with no intermediate code or software in the middle to glue things together.
The first tool, mplayer was used to dump all of the frames we needed. This took about the running length of the movie to do, which wasn't so bad. There may be a way to speed this up by giving mplayer some extra hints. I have not yet figured this part out.
The real time cost was in
ImageMagick's montage tool, which made the final
montage out of the images. This took between 6 and 10 hours to do
this, depending on the length of the movie. The process seemed to be
non-linear for some reason, with long movies taking unproportionally
longer to process (One could always dig around the montage source to
find out why). I knew there had to be a way that this could be
improved!
Well, I wrote a Perl script last night, dubbed gdmontage
to speed up the montage process. It was even faster than I thought it
would be, taking only 12 seconds on the same machine as
before. It uses the GD Graphics
Library via
Perl's GD module,
which you would need to install to use this. It also uses
the Term::ProgressBar,
if it's available, to provide a progress bar
and ETA.
Like the original montage program, the script recognizes
file globs, so you can provide the files through a glob in order to
avoid the limits on command line arguments.
$ ./gdmontage.pl "frames/*"
It is a bit unfair to call my code a "faster montage" because it only
covers a tiny subset of the original montage. It makes
some big assumptions in order to be faster; specifically, it assumes
that every image is the same size. The original montage must look at
every image before it even starts in order to determine the dimensions
and placement of the final image.
It is also geared towards the Cinema Redux thing, doing only 60 images
per row. This can be changed internally (no command line arguments for
this) by adjusting the parameters at the top of the script. The script
could probably be easily expanded to include most of the features of
ImageMagick's montage, but I am sure this Perl script would be much
faster when it comes to creating large montage's. (Why
is montage so slow?)
Anyway, you can get the script here: gdmontage.pl (GPLv3)

Original image courtesy NASA.
While studying for my digital image processing final exam yesterday, I came back across unsharp masking. When I first saw this, I thought it was really neat. This time around, I took the hands-on approach and tried it myself in Octave. It has been used by the publishing and printing industry for years.
Unsharp masking is a method of sharpening an image. The idea is this,
Here is an example using a 1-dimensional signal. I blurred the signal
with a 1x5 averaging filter -- [1 1 1 1 1] * 1/5. Then I
subtracted the blurred signal from the original to create a
mask. Finally, I added the unsharp mask to the original signal. For
images, we do this in 2-dimensions, as an image is simply a
2-dimensional signal.
When it comes to image processing, we can create the mask in one easy step! This is done by performing a 2-dimensional convolution with a Laplacian kernel. It does steps 1 and 2 at the same time. This is the Laplacian I used in the example at the beginning,
So, to do it in Octave, this is all you need,
octave> i = imread("moon.png");
octave> m = conv2(i, [0 -1 0; -1 4 -1; 0 -1 0], "same");
octave> imwrite("moon-sharp.png", i + 2 * uint8(m))
i is the image and m is the mask. The mask
created in step 2 looks like this,
You could take the above Octave code and drop it into a little she-bang script to create a simple image sharpening program. I leave this as an exercise for the reader.
Download: hashtab.tar.gz (3.9KB)
I needed a hash table written in C for a project I was working on and I didn't like any the free hash table code that was out there. Plus, I have NIH syndrome and I really wanted to write my own for fun. My goal was to make it extremely generic, so that it would work with any data of any size. A small front end could be placed on top to make it work cleanly for strings (no need to pass the length of the data).
It uses open hashing, with linked lists to store the data. The only penalty from collisions is a slightly slower lookup. This also is what alows the variable entry sizes. I could definitely fix up a few things to make it more efficient. The default hash function uses modulus, which is quite expensive.
It works just fine with all my tests so far, so it suits my needs for
the project. The code includes a demo of the hash table
(main.c). If you want to read about some better hashing
functions and use one with this hash table, take a look
at A Hash
Function for Hash Table Lookup.
Brendan Dawes has this interesting idea he calls Cinema Redux. A entire film is distilled down to a single image. You take one frame from each second of the movie, shrink that frame down to 8x6 pixels, then line them up in a montage with 60 frames per row. Each row then represents one minute of film. There are 8 examples on his website.
I was interested in trying this for myself, but I couldn't find any of his code, which he had written in Java, to do it myself. Then it hit me: I really don't need to write anything to do this! Here is how you can make your own using only two tools: mplayer and ImageMagick.
Originally I thought that I may need to write a small Perl script to
glue these two things together, but found, after digging
though man pages, that this was completely
unnecessary. There are two steps involved and each tool does one step:
grab all of the frames, and second, make a montage out of those
frames. Grabbing the frames is one call to mplayer,
mplayer -vo jpeg:outdir=frames -ao dummy -vf framestep=30,scale=8:6 \
video_file
What we are doing here is dumping every 30th frame (assuming 30
frames-per-second) into a directory named frames. These
images will be named by consecutive 8-digit numbers. These frames are
also resized down to 8x6 pixels. If you are converting a video with a
different aspect ratio, such as a wide-screen movie without
letter-boxing, you will need to adjust this. A wide-screen film would
be 16x9.
Next, we glue these frames together with ImageMagick,
montage -geometry +0+0 -background black -tile 60x "frames/*jpg" \
montage.jpg
This will create the montage in the
file montage.jpg . There is something important to note
here. See how the file glob is quoted so that the shell will not
expand it? Thats because listing 7000 frames pushes the limits of the
system in passing command line arguments. ImageMagick knows about file
globs and will do this internally.
And that's it! I put these together into
a handy shell
script that will also remove the frames after the montage has been
successfully created. The process takes between 6 and 12 hours,
depending on the length of the movie. It takes the movie running time
to produce all the frames file, then it spends the rest of the time
creating the montage, which is disappointingly slow. (Maybe I could
write a Perl script that does it faster?) The script will create a
montage out of just about any video you throw at it, thanks
to mplayer. Example usage for DVDs,
$ ./cinrdx.sh dvd://
I did it on three movies so far: Gladiator, Tron, and The Matrix. I did it to Tron and The Matrix because I wanted to see if these movies have a dominant color scheme.
To inspect the coloring of these films, I took a hue histogram. Tron is very obvious: lots of blues and cyans dominate,
I was expecting to see a lot of green show up in The Matrix, but was a little bit disappointed,
To get these histograms, I loaded the images into GNU Octave, converted it to HSV so that the red channel is really the hue channel. Then I had the GIMP make the histograms by providing the histogram of the "red" (read hue) channel. I dropped an HSV color bar below with some image editing.
octave> m = imread("movie.jpg");
octave> [x map] = rgb2ind(m);
octave> map = rgb2hsv(map);
octave> imwrite("movie-hsv.jpg", x, map);
See if you can find some really interesting things to do with this.
Notice: This software is not affiliated with the South Park Zone nor South Park. In fact, this bypasses all of the South Park Zone's advertising, so they may not like it. I have do not have anyone's approval, nor do I know about any of the legal implications of this tool. Use at your own risk.
Get the
program: spd.pl
(3.8KB) GPLv3
Requires Perl
and GNU
wget
This was an afternoon project the other day. I found out about a
website called the South Park
Zone. This website has information on where to fetch South Park
episodes from different hosts, such as MySpace and YouTube. These
videos are stored in the Flash video format. You see, I don't have the
proprietary Flash software installed and the free versions aren't
quite ready for use yet. I use
other means of watching videos on sites like YouTube. This means
that I normally have to either
use a
tool to find the .flv file or search through the
site's HTML code manually.
In this case, I couldn't find an existing tool that could grab the videos pointed to by the South Park Zone. I was able to find it manually, but trying to watch several videos takes a bit of digging. Anyway, if I really want to become a hacker sometime (I feel I am not yet worthy of this name), what do I do? Well, I write a program to do it for me!
I stretched my Perl legs a bit and wrote a script that will grab the
video location from the South Park Zone and download the video. The
only thing you need other than Perl is
GNU wget. This
is the program that does all the hard work. My Perl script just scans
the HTML and XML for the data.
Here is an example session,
$ spd 807
Getting mirror number ...
Getting episode URL ...
Downloading episode: The Jeffersons (125)
--20:21:21-- http://content.movies.myspace.com/0008289/24/25/828935242.flv
=> `South Park - 0807 The Jeffersons.flv'
Resolving content.movies.myspace.com... 204.16.34.216
Connecting to content.movies.myspace.com|204.16.34.216|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 43,350,604 (41M) [application/octet-stream]
100%[====================================>] 43,350,604 890.43K/s ETA 00:00
20:22:14 (823.14 KB/s) - `South Park - 0807 The Jeffersons.flv' saved [43350604/43350604]
The program accepts episode numbers, episode ranges, and search
terms. For example, assuming you have installed the program and
removed the .pl extension, this will download season 2,
episode 3 and season 10, episode 10,
$ spd 203 1010
You can also provide a range of episodes with a dash,
$ spd 405-410
With that command, season 4, episodes 5 through 10 will be fetched. The range will not work across seasons! This is because I didn't see a convenient way to find out how many episodes were in each season. Right now the tool should be fine until season 100 (3 digit seasons) or South Park Zone goes away. It knows nothing about South Park: it only fetches the data on request.
And finally, one of the coolest parts, it will do searches for you too. Right now, it just grabs the first search result, but this seems to work pretty well. For example, this grabs the famous Make Love, Not Warcraft episode,
$ spd warcraft
I have used it a bit myself, but there may still be bugs. It also
assumes that all of these videos are .flv files, but the
South Park Zone is prepared for these things to be in any format. If
its popular enough, perhaps I will turn it into a "project" and version
it. It could also use a better front end for parsing option
flags. Perhaps a quiet -q flag,
$ spd -q 506-510 708 710
Don't stop here! This isn't everything. Check out the archives (on the left) for more posts. Or just have a look at the index.