Archive

Tag Archives: scripting

A640 rotated_84_2

Having been flying around the country over the past couple of weeks, I’ve shot a lot of timelapse out of the front windscreen. Just because I can.

It’s largely thanks to CHDK and I have managed to record myself getting lost on routes between Sheffield, Lancaster, Leeds, Newcastle, Nottingham and York. I have a few plans for this media, but one journey is already online here:

This was quite a successful Flying Monkey TV experiment and I had it edited and online within three hours of getting home.

These journeys were mostly shot on a Canon PowerShot A560, timelapse-enable with CHDK, and mounted on the inside of the front windscreen with a suction mount (see below). I mounted the camera hanging from the top of the screen, upside down. This meant that it was in line with the passenger side roof pillar and hence did not obscure my view.

I don’t use the auto-rotate feature in most cameras because it sometimes gets confused and can give you a few incorrectly rotated frames here and there. Consequently, shooting this way, I end up with an upside-down video that then needs rotating.

559CANON_full_2048_03pct

I used to drop them into Final Cut Pro, render them and export them to a new movie file, which works fine, but I think it’s time to write a Bash script to do it.

No sooner said than done! Well, not quite, but it was much easier than I imagined. As usual Google managed to find some very helpful resources for me to cannibalise. Writing the code is much faster than documenting it into a usable blog post.

I started by reminding myself how to create a basic for-next procedure (detail included here for other noobs). Here is a bit of basic code with lists the files in the present working directory ending in “.JPG” (don’t forget this is case-sensitive) and echos them to the screen. The semicolons separate the statements and the “done” terminates it.

for i in $(ls *.JPG); do echo $i; done

For the next step, instead of just listing the file names to the screen, I added the ImageMagick step to rotate the image and write it over the original.

for i in $(ls *.JPG); do convert $i -rotate 180 $i; done

As you might have already gathered, I like some progress feedback so added an echo with the file count and file name.

for i in $(ls *.JPG); do convert $i -rotate 180 $i; x=$(($x+1)) ;echo “$i $x”; done

However, a current file number is only of use if you know how many more to go. A bit of googling revealed this forum thread and the code:

ls -l | wc -l

This lists all the files in the current directory and then pipelines that list to give an integer count of the items in that list. It’s not necessary if this is just a temporary folder and it’s cleared between uses, but if you want to filter the file types you can add a wild card search like this:

ls -l *.JPG | wc -l

I found information about the two commands on linux.about.com and a forum thread which combines the two on unix.com.
http://linux.about.com/od/commands/l/blcmdl1_ls.htm
http://linux.about.com/library/cmd/blcmdl1_wc.htm
http://www.unix.com/unix-dummies-questions-answers/36490-ls-command-listing-number-files.html

So my final piece of code (for this iteration at least) is here:

x=0; c=$(ls -l *.JPG | wc -l); for i in $(ls *.JPG); do convert $i -rotate 180 $i; x=$(($x+1)) ;echo “$x /$c $i”; done

This sets x to be 0, c to be the number of files with filenames ending in “.JPG” in the current directory, rotates each one of them by 180 degrees, overwrites the original file and echos the file number, the file count and the filename. It’s pretty basic and I’ll roll it into a script soon.

There may well be better ways of doing this, but it worked well as an exercise to reinforce my learning.

Advertisements

The script here is only a slightly cleaned up version of the previous one, but also with a major addition. A timer.

It may be just that I’m new to Linux, but getting the syntax correct was very unintuitive. It took a lot of trial-and-error to get the spaces in the right place, and it reminds me a lot of programming in the 1980’s where you just get a “syntax error” message and nothing else.

This timer function uses the classic technique of storing the system time at the start of the script and then again once the script has finished, subtracting the former from the latter and the difference is the time taken.

This function only returns an the number of seconds as an integer, and a result of “1350575350” might as well be in grains of sand. So, I have then reformatted the output to a more human-readable minutes and seconds by dividing the number of seconds elapsed by 60 to get the minutes and deriving the modulus (what’s left over) for the number of seconds. I could also do a similar thing with the value 3600 if I wanted to format it in hours, minutes and seconds.

Strangely, when I tried date +%2s (which returns the current system time in seconds) at the command line in OS X it failed, but not on the same machine whilst booted into the Linux partition. Turns out, it was a typo but Linux is happy to ignore this glaring mistake (should be date +%s) whilst OS X is not. Strange when it’s so particular about other syntax.

However, all complaining aside, I have got some actual useful working code up and running much more easily than I had expected.

# !/bin/bash

clear
echo “Hello Monkey Planet”
starttime=$(date +%s)

cd /home/richard/Desktop/RBTest/newtest
rm *.JPG
rm *.jpg

cd /home/richard/Desktop/RBTest/testtemp
rm *.JPG
rm *.jpg

cd /home/richard/Desktop/RBTest/newtest
#gphoto2 –get-all-files

x=1; for i in $(find $(pwd) -name \*.JPG | xargs ls -t -r); do counter=$(printf %04d $x); ln “$i” /home/richard/Desktop/RBTest/testtemp/img_”$counter”.jpg; x=$(($x+1)); done

cd /home/richard/Desktop/RBTest/testtemp
ffmpeg -r 25 -i img_%04d.jpg -s 640×480 -qscale 1 -vcodec mjpeg movie.mov
rm *.jpg

stoptime=$(date +%s)
fulltime=$(expr $stoptime – $starttime)
fulltimesecs=$(expr $fulltime % 60)
fulltimemins=$(expr $fulltime / 60)

echo “$fulltimemins minutes $fulltimesecs seconds”

I suppose it would be good to structure this programming at some point, such as the timer function, so that I could call it from any script. There probably is a function in Linux already.

More soon…

THE CODE PUBLISHED HERE COMES WITH ABSOLUTELY NO WARRANTY WHATSOEVER, SO PLEASE USE AT YOUR OWN RISK.

I am basing my code on existing bits of open source stuff scavenged from various places and cobbled together. At some point in the future I hope to make some sort of point-and-click front end for it, but in the meantime it’s just command-line code, and at the moment, pretty crude.

Here is a slightly updated version of my previous script, which now clears the work folders and downloads from the camera using gPhoto2.

# !/bin/bash
clear
echo “Hello Monkey world”
#gphoto2 —

cd /home/richard/Desktop/RBTest/newtest
rm *.JPG
rm *.jpg
cd /home/richard/Desktop/RBTest/testtemp
rm *.JPG
rm *.jpg

cd /home/richard/Desktop/RBTest/newtest
gphoto2 –get-all-files

x=1; for i in $(ls -t -r *JPG); do counter=$(printf %04d $x); ln “$i” /home/richard/Desktop/RBTest/testtemp/img_”$counter”.jpg; x=$(($x+1)); done

cd /home/richard/Desktop/RBTest/testtemp
ffmpeg -r 25 -i img_%04d.jpg -s 640×480 -qscale 1 -vcodec mjpeg movie.avi

This is pretty clunky but at least it’s getting somewhere. At some point I’ll find out how to reference files case-insensitive.

On some of the older cameras, such as my A620, the camera saves images in discrete folders of only 200 images each, which means a lot of effort in post-production if it has to be done by hand.

I think the next logical steps are to compile multiple folders of images and also to name the destination movie file discretely. The name could be created from some format information, a date/time stamp, and the model of the camera which can be derived from gPhoto2.

Googling something about recursive folders I found this:

http://stackoverflow.com/questions/245698/list-files-recursively-in-linux-with-path-relative-to-the-current-directory

However, this does not return them in creation time order and, as far as I could google, there doesn’t seem to be an argument to produce that.

After googling something about Linux pipeline commands I found a reference to xargs, and Bob’s your uncle. I can hardly believe I found it so quickly, but I remember Martyn at Access Space telling me about pipelining so I used a bit of intuition and worked out how to take the results from the find command and sort them afterwards.

http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/

Here is my Bride of Frankenstein, which takes a folder full of folders (full of images), lists them in creation order, renames them and compiles them into a movie file. Simples!

# !/bin/bash
clear
echo “Hello Monkey Planet”

cd /home/richard/Desktop/RBTest/testtemp
rm *.JPG
rm *.jpg

cd /home/richard/Desktop/RBTest/newtest

x=1; for i in $(find $(pwd) -name \*.JPG | xargs ls -t -r); do counter=$(printf %04d $x); ln “$i” /home/richard/Desktop/RBTest/testtemp/img_”$counter”.jpg; x=$(($x+1)); done

cd /home/richard/Desktop/RBTest/testtemp
ffmpeg -r 25 -i img_%04d.jpg -s 640×480 -qscale 1 -vcodec mjpeg movie.avi