
VSFM, for those who’ve tried it, is a right huge pain in the arse to install. Ryan Bauman has done us all a huge favour by dockerizing it. His explanation of this is here – and once you’ve figured out some of the kinks, this is much easier way of working with it.
Ah yes, the kinks.
First of all, before we go any further, why would you want to do this? Isn’t 123D Catch enough? It is certainly easier, I grant you that. And it does a pretty good job. But structure-from-motion applications each approach the job differently – Ryan does a comparison here on the same objects. Some of those applications are very expensive indeed. VSFM is free to use, and can be called from the command line, and with care and practice one can get very good results. (What really caught everyone’s eye on twitter the other day was Ryan’s workflow for generating 3d objects from found drone aerial footage. HOW COOL IS THAT.). So I set out to replicate it.
First things first: you need to go to Docker and install it (here is a post wherein I futz with Docker to run Rstudio).
Now, Ryan’s container (that we will use in a moment) also comes with the handy youtube-dl for grabbing youtube videos, and another package for manipulating and cutting stills out of that video. What follows are my notes to myself (in which I sometimes copy-and-pasted from others’ posts, to remind me what I was trying to do) as I work through the first part of Ryan’s workflow – from downloading the video to generating the point cloud. The meshlab texturing stuff will be a follow-up post.
1. Initialize and run boot2docker from the command line, creating a new Boot2Docker VM.
$ boot2docker init
This creates a new virtual machine. You only need to run this command once.
Start the boot2docker VM.
$ boot2docker start
Set the environment variables in your shell do the following:
$ eval "$(boot2docker shellinit)"
Then this:
$ docker run -i -t ryanfb/visualsfm /bin/bash
first time, will take a long time to download everything you need. This is Ryan’s container – the next time you go to do this, it’ll spin up very quickly indeed (one of the advantages of Docker; it’s a virtual machine with just the bits you need!) Then:
$ youtube-dl 'https://www.youtube.com/watch?v=3v-wvbNiZGY'
downloads a file from youtube called:
The Red Church Dating to the late 5thearly 6th century-3v-wvbNiZGY.mp4
let’s rename that:
$ mv 'The Red Church Dating to the late 5thearly 6th century-3v-wvbNiZGY.mp4' redchurch.mp4
now let’s create a new directory for it:
$ mkdir redchurch
and move the mp4 file into it:
$ mv redchurch.mp4 redchurch
Ok, so now we split it into frames:
$ avconv -i redchurch.mp4 -r 1/1 -qscale:v 1 redchurch_%08d.jpg
(note that in the original post by Ryan, he was using ffmpeg; the docker container uses this alternative)
And then we go up a level
$ cd ..
and run some vsfm on it:
$ VisualSFM sfm+pairs+pmvs ~/redchurch redchurch.nvm @8
This part took nearly three hours on my machine.
ASIDE: now, I had to increase the available memory for VSFM to make it work; otherwise I was getting a ‘segmentation error’ at this step. To do this, first I found the .boot2docker folder by hitting control as I clicked on the finder, and then ‘go to’ /users/[user]/.boot2docker. I opened a new terminal there, and made a new file called ‘profile’ (no extension) with the following info
#disk image size in MB DiskSize = 20000 # VM memory size in MB Memory = 7168
I made the file by typing vi profile at the terminal, then typed in the info; then escape to stop editing and :save profile to save the file and close it.
Now to get stuff out (and this post was most helpful)
we need to open another terminal window, start docker there, and ask Docker to give us the id of the container that is running, so we can cp (copy) files out of it:
$ docker ps
There will we a randomly generated ‘short name’ for your container; the short id will be the same as at the prompt in your terminal where the vsfm is running; eg in my case: root@031e72dfb1de:~#
Then we need to get the full container id:
$ docker inspect -f '{{.Id}}' SHORT_CONTAINER_ID-or-CONTAINER_NAME
example (drawn from this post):
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d8e703d7e303 solidleon/ssh:latest /usr/sbin/sshd -D cranky_pare $ docker inspect -f '{{.Id}}' cranky_pare
You will get a ridiculously long string. Copy & paste it somewhere handy. On my machine, it’s:
031e72dfb1de9b4e61704596a7378dd35b0bd282beb9dd2fa55805472e511246
Then, in your other terminal (the one NOT running vsfm, but has docker running in it), we do:
$ docker cp <containerid>:path-to-file useful-location-on-your-machine
In my case, the command looks like this:
shawngraham$ docker cp 031e72dfb1de9b4e61704596a7378dd35b0bd282beb9dd2fa55805472e511246:root/redchurch.1.ply ~/shawngraham/dockerific/
update: turns out you can use the short id, in this case, 031e72dfb1de:root etc and it’ll work just fine.
(dockerific being the folder I made for this occasion)
~oOo~
Tomorrow, I’ll write up the kinks in the meshlab part of this workflow. Thanks again to Ryan for a brilliant piece of work!
~oOo~
update july 29
ok, let’s make life a bit easier for ourselves, in terms of getting stuff into and out of the docker container. Let’s create a folder that we can use as a kind of in-out tray. I’ll create a folder on my file system, at /user/shawngraham/dockerific
Then, when I am ready to run the container, we’ll mount that folder to the tmp folder in the container, like so:
$ docker run -i -t -v /Users/shawngraham/dockerific/:/tmp/ ryanfb/visualsfm /bin/bash
Now, anything we put in the tmp folder will turn up in dockerific, and vice versa. NB, things might get overwritten, so once something turns up in dockerific that I want to keep, I move it into another folder safe from the container. Anyway, when I want to get things out of the docker container, I can just CoPy <file> <to this location>
cp output.ply ~/tmp/
…and then grab it from the finder to move it somewhere safe.