Wednesday, October 6, 2010

Converting VLFeat SIFT output to Lowe-compatible SIFT output for Bundler

I've recently been trying to get Bundler working on my Mac. Bundler is a part of a set of software (also including PMVS, CMVS, and others) that provides an open-source alternative to Microsoft PhotoSynth. Unfortunately, it has a dependency on a closed-source implementation of the SIFT keypoint-detection algorithm written by David Lowe.

There are a few open-source implementations of the SIFT algorithm, and one is part of the VLFeat toolkit. Unfortunately, VLFeat's SIFT tool generates differently formatted output from the Lowe version, even though it's the same sort of information. I spent far too long hunting for a conversion script, and found no standalone (or even Bundler-ready) one, so I did it with awk.

If you are using Bundler, you can just update the ToSift.sh script, replacing the line:

echo "mogrify -format pgm $IMAGE_DIR/$d; $SIFT < $pgm_file > $key_file; rm $pgm_file; gzip -f $key_file"

with


echo "wc -l $key_file.vlfeat | awk '{ print \$1 \" 128\" }' > $key_file"
echo "awk 'BEGIN { split(\"4 24 44 64 84 104 124 132\", offsets); } { i1 = 0; tmp = \$1; \$1 = \$2; \$2 = tmp; for (i=1; i<9; i++) { i2 = offsets[i]; out = \"\"; for (j=i1+1; j<=i2; j++) { if (j != i1+1) { out = out \" \" echo "rm $key_file.vlfeat"


Once that's done, the RunBundler.sh script can be run as usual.

If you'd rather just convert existing VLFeat-generated key files, you can use:

zcat vlfeat.key.gz | wc -l | awk '{ print $1 " 128" }' > lowe.key

zcat vlfeat.key.gz | awk 'BEGIN { split("4 24 44 64 84 104 124 132", offsets); } { i1 = 0; tmp = $1; $1 = $2; $2 = tmp; for (i=1; i<9; i++) { i2 = offsets[i]; out = ""; for (j=i1+1; j<=i2; j++) { if (j != i1+1) { out = out " " }; out = out $j }; i1 = i2; print out } }' >> lowe.key
gzip lowe.key


Hope this helps someone avoid the effort!