Useful Image Manipulation Commands in Linux

Over the course of collecting and analyzing data in the my Deer Detector project, I came across a number of useful Linux commands that performed a lot of heavy lifting. This post describes a few of those commands and provides some examples of what they do.

Mirror Images

When performing tasks such as training a Machine Learning classifier, I often needed a lot of training examples. One of the problems I ran into was that I didn’t have a lot of images of various objects such as deer, raccoons, or cats. To get around this limitation, I generated mirror images of objects so that I could double the number of training examples. Image Magick makes this really easy. For example, I would flip the following image:


To get this image:


The command to do this:

convert original.png -flop mirror.png


Rather than having to flip through a bunch of images one at a time, I often wanted to create a single image with a lot of smaller images in it. Image Magick also helped me out here with their montage command. For example:


To generate this image, all I needed to do was tell it the expected geometry for each of the pictures (60×60), and then tell it what type of border to put around of them (a 1 pixel border around all sides):

montage image00*.jpg -geometry 60x60+1+1 montage-image.png

Image Resizing

I knew how to resize an image using something like the GIMP, but Image Magick makes it easy to resize a bunch of images programmatically. To resize all of the JPEG images in the current directory to 320×240:

for file in *.jpg ; do \
    convert $file -resize 320x240 $file ;

Animated GIFs

Animated GIFs are useful for playing a set number of frames in a loop with a delay. I did this on several occasions to display a simple time-lapse snippet without having to generate a video file. For example, here’s a raccoon eating blackberries from our bushes:


To create the GIF:

convert -delay 50 -loop 0 image*.jpg animation.gif

Compressing Animated GIFs

Often times my animated GIFs were huge! It helps sometimes to compress the GIF down a little. While I would loose some color information, doing so would often reduce the size from several megabytes down to a few hundred kilobytes. The best way to do that is to scale down the image, have Image Magick optimize the layers, and scale down the number of colors (for example, down to 256). The command to do this just adds a few options to the convert command:

convert -delay 50 -loop 0 -layers optimize \
    -depth 8 -resize 320x240 image*.jpg animation.gif

Video from Directory of Images

During my data collection phase, I wanted to create a time-lapse video from a number of images that I pulled from the Raspberry Pi NOIR camera application. Using mencoder, it is really easy to convert a directory of images into an AVI file. Assuming that all of the files are JPEG files, and that they have a correct ordering to them (for example: image00001.jpg, image00002.jpg, etc), this command will create a file called video.avi:

mencoder mf://*.jpg -mf fps=25:type=jpg \
    -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell \
    -oac copy -o video.avi

Adding Text to an Image

When I was collecting images for data analysis, I would often want to add a label identifying the file name to the image, so that when I created a video of it, I could easily tell what file any given frame came from. For example:


To add the file name in the top-left corner of any JPEG file in the current directory:

for file in *.jpg ; do \
    convert -pointsize 20 -fill yellow \
        -draw "text 5,25 '$file'" \
        $file $file ;

Drawing Rectangles in Images

At one point, I wanted to draw a rectangle around a particular object in an image. For example:


The rectangle in the image above has a top-left corner at position (4, 50), and the bottom-right corner at position (100, 100). The important option is -fill with an RGBA value that tells Image Magick to use a fully transparent color to fill the rectangle:

convert original.png \
    -stroke yellow \
    -fill "rgba(0,0,0,0)" \
    -draw "rectangle 4,50 100,100" \


Most of the commands above came in very handy when performing data collection and image pre-processing tasks. As always, your mileage may vary! Tune in next time when I’ll talk about some of the basics behind machine learning algorithms.