Showing posts with label imagemagick. Show all posts
Showing posts with label imagemagick. Show all posts

Sunday, 6 June 2010

Granular Therapy

Here's a relaxing movie I just made of spinning modelled sand grains:



I'm not going to divulge the details of the model of how to create the sand grains (a current research project of mine). I can tell you I used these rather excellent functions for MATLAB:

Volume interpolation Crust algorithm, described more here

A toolbox for Multi-Parametric Optimisation

I used 'recordmydesktop' to capture the grains in my MATLAB figure window. It created an OGV format video (which I renamed to 'beautiful_grains.ogv'). I then used the following code to decode the video into jpegs

 mkdir out_pics  
mplayer -ao null -ss 00:00:03 -endpos 50 beautiful_grains.ogv -vo jpeg:outdir=out_pics



I needed to crop the pictures to just the grains, then turn the cropped pictures back into a video. I used this:

 cd out_pics  
for image in *.jpg
do
# crop the image
convert $image -crop 600x600+350+135 grains%05d.tiff
done
# make movie from the cropped tiffs
ffmpeg -r 25 -i grains%05d.tiff -y -an spinning_grains_small.avi


et voila! Now sit back with a cuppa and relax to those spinning grains.

Saturday, 5 June 2010

Updated Power Spectrum from an Image

A while back I posted on using ImageMagick to do a full frequency-decomposition on an image, and create a power spectrum. It had several inaccuracies. Here's an update with how to do it better

First, you need to install a version of IM which is HDRI enabled (see here)

# test for valid version of Image Magick
 im_version=`convert -list configure | \  
sed '/^LIB_VERSION_NUMBER /!d; s//,/; s/,/,0/g; s/,0*\([0-9][0-9]\)/\1/g'`
[ "$im_version" -lt "06050407" ] && errMsg "--- REQUIRES IM VERSION 6.5.4-7 OR HIGHER ---"


# test for hdri enabled
 hdri_on=`convert -list configure | grep "enable-hdri"`  
[ "$hdri_on" = "" ] && errMsg "--- REQUIRES HDRI ENABLED IN IM COMPILE ---"


#read $file, load and converting to greyscale
 convert $file -colorspace gray in_grey.tiff  


# crop image to smallest dimension
 min=`convert in_grey.tiff -format "%[fx: min(w,h)]" info:`  


# crop image, and convert to png (why?)
 convert in_grey.tiff -background white -gravity center -extent ${min}x${min} in_grey_crop.png  


# get data, find mean as proportion, convert mean to percent, and de-mean image
 data=`convert in_grey_crop.png -verbose info:`  
mean=`echo "$data" | sed -n '/^.*[Mm]ean:.*[(]\([0-9.]*\).*$/{ s//\1/; p; q; }'`
m=`echo "scale=1; $mean *100 / 1" | bc`
convert in_grey_crop.png -evaluate subtract ${m}% in_grey_crop_dm.png


# pad to power of 2
 p2=`convert in_grey_crop_dm.png -format "%[fx:2^(ceil(log(max(w,h))/log(2)))]" info:`  
convert in_grey_crop_dm.png -background white -gravity center -extent ${p2}x${p2} in_grey_crop_dm_pad.png


# fft
 convert in_grey_crop_dm_pad.png -fft in_ft.png  


# get spectrum
 convert in_ft-0.png -contrast-stretch 0 -evaluate log 10000 in_spec.png  


... but it's still not quite right. Any tips?

Turn your OGV movie section into a cropped animated GIF

An example from a recent project

 # make directory for output jpg  
mkdir out_pics
# section to the ogv video file into jpegs
mplayer -ao null -ss 00:00:03 -endpos 50 beautiful_movie.ogv -vo jpeg:outdir=out_pics
cd out_pics
# loop over each image and crop into desired rectangle
for image in *.jpg
do
convert $image -crop 600x600+350+135 "$image crop.tiff"
done
# turn into an animated gif
convert -page 600x600+0+0 -coalesce -loop 0 *.tiff beautiful_animation.gif

Unlock the power of ImageMagick to HDRI

My primary motivation to do this has been to use ImageMagick for Fast Fourier Transforms, which have a myriad of applicability in image processing and filtering

First, you have to install perlmagick. Using apt,
 sudo apt-get install perlmagick  


Then the perl libraries
 sudo apt-get install libperl-dev  


Install the rather magnificent fftw libraries
 sudo apt-get install libfftw3-dev fftw-dev  


wget the source code, untar, move it, cd home
 wget ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz   
tar xvfz ImageMagick.tar.gz
mv ImageMagick-6.6.0-8 $HOME
cd $HOME/ImageMagick-6.6.0-8


Install (see here for instructions)
 make distclean   
./configure --enable-hdri LDFLAGS='-L/usr/local/lib -R/usr/local/lib'


see also here for a bug fix, and also see here for instructions

make & sudo make install
make check


To see whether the fft commands are working properly, you could issue the following:
 if [ -s lena.png] #check to see if the file exists  
then
# do fft and ifft roundtrip
convert lena.png -fft -ift lena_mp_roundtrip.png
else
#first download
wget http://optipng.sourceforge.net/pngtech/img/lena.png
#then convert
convert lena.png -fft -ift lena_mp_roundtrip.png
fi


see here for further information on fft transforms with, and watch your world spin faster

Thursday, 16 April 2009

Frequency Transforms on Images

As part of my work, I have to do a lot of spectral analysis with images. Traditionally I have used MATLAB to do this - it is exceptionally easy and powerful, and works just fine. As a simple example, if I want a power-spectrum of an image, treated as a 2D matrix of 8-bit numbers, the sequence of commands is this:

 %------------------- MATLAB  

% read image in, convert to greyscale and double-precision
image=double(rgb2gray(imread('myimage.jpg')));
% crop to smallest dimension
[m,n]=size(im);
im=im(1:min(m,n),1:min(m,n));
% find image mean
imMean=mean(im(:));
% and subtract mean from the image
demean=im-imMean;
% find the 2D fourier transform
ft=fft2(demean);
% power spectrum is the element-by-element square of the fourier transform
spectrum=abs(ft).^2;


Seven lines of commands. Couldn't be simpler. That's the beauty of MATLAB. The snag is that it costs several hundreds to thousands of dollars for the program, which makes it difficult to share your code with other people. So recently I've thought about coding up some things I want to share with other people in Python.

Python is a cross-platform, open-source programming language and environment. It is not too dissimilar to MATLAB in many respects, especially when you install the right libraries. In order to do the same in Python as above, as easy as possible, I needed to install Python Imaging Library (PIL),  NumPy and SciPy. Then the sequence of operations is as follows:


 # ----------------PYTHON  

#-----------------------
# declare libraries to use
import Image
import scipy.fftpack
from pylab import*
import cmath
from numpy import*
# load image, convert to greyscale
im=Image.open('myimage.jpg').convert("L")
# crop to smallest dimension
box=(0,0,im.ny,im.nx)
region=im.crop(box)
# find mean
imMean=mean(asarray(region))
# 2D fourier transform of demeaned image
ft=fft2(region-imMean)
# power spectrum
spectrum=pow(abs(ft),2)


Same answer. Not bad - not harder, just different. And completely free. Oh, and this'll work on UNIX, Linux, Mac, and PC when Python is installed (with a couple of extra libraries). Great! 

Hmm, I thought, I wonder if it is possible to do the same in a piece of non-numerical software. I tried ImageMagick because its free and ubiquitous on Linux and Mac, and also available for PC, and it has a massive user-community. It is incredibly powerful as a command-line graphics package - even more powerful than PhotoShop and Illustrator, and like all UNIX-based applications, infinitely flexible. It turns out it is a little more tricky to calculate the power spectrum in ImageMagick, but here's how.

First, you need the right tools - ImageMagick is usually already present on most Linux distributions - if not, if a debian/Ubuntu user use sudo apt-get install imagemagick, or download from the webiste hyperlinked above. Then you'll need an open-source C-program for calculation of FFTs: this is provided by FTW - download fftw-3.2.1.tar.gz, untar, cd to that directory, then install the binary by issuing the usual commands:

 ./configure  

sudo make && make install


This C-program is no good on its own, so the last ingredient is a wrapper for ImageMagick. Fortunately - nay, crucially, this has been provided by Sean Burke and Fred Weinhaus - introducing IMFFT! The program can be downloaded and installed from here. And here is an in-depth tutorial of how to use it (I'm only just getting to grips with it myself). For some reason the compiled program is called 'demo'. I move it to my /bin directory so my computer can see it wherever I am working, and in the process change the name to something more suitable - fft:

 cp demo ./fft && sudo mv ./fft /bin  



Right, it's a little bit more involved, but here is the bash shell script for the power spectrum in ImageMagick:

 #----------------------------- IMAGEMAGICK  

#-------------------------------------------------
#!/bin/bash
# read image and convert to greyscale
convert myimage.tif -colorspace gray input_grey.tiff
# find min dimension for cropping
min=`convert input_grey.tiff -format "%[fx: min(w,h)]" info:`
# crop image
convert input_grey.tiff -background white -gravity center -extent ${min}x${min} input_grey_crop.tiff
# de-mean image
# get data
data=`convert input_grey_crop.tiff -verbose info:`
# find mean as proportion
mean=`echo "$data" | sed -n '/^.*[Mm]ean:.*[(]\([0-9.]*\).*$/{ s//\1/; p; q; }'`
# convert mean to percent
m=`echo "scale=1; $mean *100 / 1" | bc`
# de-mean image
convert input_grey_crop.tiff -evaluate subtract ${m}% ggc_dm.tiff
# pad to power of 2
p2=`convert ggc_dm.tiff -format "%[fx:2^(ceil(log(max(w,h))/log(2)))]" info:`
convert ggc_dm.tiff -background white -gravity center -extent ${p2}x${p2} ggc_dm_pad.tiff
# forward fast fourier transform
fft f ggc_dm_pad.tiff
# creates ggc_dm_F_Q16.tiff, on which get spectrum
convert ggc_dm_F_Q16.tiff -contrast-stretch 0% -gamma .5 -fill "rgb(1,1,1)" -opaque black ggc_dm_F_Q16_spec.tiff


Voila! The spectrum is the image 'ggc_dm_F_Q16_spec.tiff'. I haven't yet worked out how to keep all the data inside the program, to eliminate the need (and cumulative errors associated with) writing the outputs at every stage to file, and eading them back in again. This means I can't use the spectrum for any scientific application. But in theory it should be possible. Any suggestions welcome!