[localhost:~]$ cat * > /dev/ragfield

Tuesday, March 31, 2009

Image stabilization in iMovie '09

I got the chance yesterday to try out the new image stabilization feature in iMovie '09. It works. Sort of.

Last weekend I strapped my Flip video camera onto the handlebars of my bike while descending a big hill. The resulting footage was pretty jerky. I started iMovie for the first time and it decided to build thumbnails for what seemed like forever. Finally I was able to add my clip to a project and enable image stabilization for it. It took around two hours on my 2.2 GHz dual core MacBook Pro to process five minutes of video. Ouch.

It appears to work by cropping the image frame to give it a few extra pixels in each direction with which to work. It then attempts to match up corresponding sections of subsequent video frames. Finally, it re-expands the cropped image to fill the frame again.

With my particular video there were a few sections which it was able to successfully stabilize, but most of it couldn't be helped. In parts the video was actually worse after stabilization (due to the scaling?). Anyway, here's a brief comparison. The top image is the original (scaled down from HD) video. The bottom frame is the stabilized version from iMovie '09.

I assure you the two videos are synchronized. Notice how the iMovie (bottom) video has a noticeably smaller field of view, slightly washed out colors, and slightly more side-to-side movement, but slightly less jerkiness.

The video was easy to put together in Mathematica. First I saved each movie as an Image Sequence in QuickTime Player Pro. Then I combined the two frames using Mathematica 7's image processing functions. Then I assembled the resulting frames back into a movie using QuickTime Player Pro. Here's the Mathematica code.

processFrame[i_Integer] := Module[
    {n, n1, n2, n3, i1, i2, i3},
    n = StringJoin[IntegerString[i, 10, 4], ".png"];
    n1 = StringJoin["Descent/Descent", n];
    n2 = StringJoin["DescentStabilized/DescentStabilized", n];
    n3 = StringJoin["DescentCompare/DescentCompare", n];
    i1 = Import[n1];
    i2 = Import[n2];
    i3 = ImageAssemble[{
        {ImageResize[i1, {480, 270}]},
        {ImageResize[i2, {480, 270}]}
    Export[n3, i3]
With[{start = 1, stop = 9606}, Monitor[
    Do[processFrame[i], {i, start, stop, 1}],
    ProgressIndicator[Dynamic[(i - start)/(stop - start)]]

I'll bet I could do the stabilization in Mathematica...

1 comment:

Jonathan said...

Gee, judging from the Mathematic plugs, you'd think Wolfram paid you or something...