Sunday, November 25, 2012

Blender: exporting camera tracking markers to CSV

For university, I needed a camera tracker which could track motion of some particles under a microscope, and give me the coordinates of a particle for each frame. Blender has a very nice camera tracker which is ridiculously easy to use (and very fast), but it cannot export its results in a gnuplot-compatible format. But, it has a nice Python API, so you can just do it yourself! This is a script which exports all camera tracking markers of all videos in a blender file to CSV files in a directory called "data":
import bpy
D = bpy.data

for clip in D.movieclips:
    for track in clip.tracking.tracks:
        fn = 'data/tr_{0}_{1}.csv'.format(clip.name.split('.')[0], track.name)
        with open(fn, 'w') as f:
            frameno = 0
            while True:
                markerAtFrame = track.markers.find_frame(frameno)
                if not markerAtFrame:
                    break
                frameno += 1
                coords = markerAtFrame.co.xy
                f.write('{0} {1}\n'.format(coords[0], coords[1]))
Just paste this to a blender text editor window and press Alt+P to run it. You have to create a directory named "data" manually before that.

Careful: The coordinate output is in units of the video height / width. So if your video is not square sized, you need to multiply the output by the video clip dimensions (clip.size[0] and clip.size[1]).

20 comments:

  1. Thanks so much for this! Do you know the units of the coordinates (I'm getting values like 0.643...), and do you know if (0,0) is the center of the video or top left corner?

    ReplyDelete
    Replies
    1. I don't know about (0, 0), but I'm pretty sure it's one of the corners since I don't remember getting any negative values ever.

      The coordinates are fractions of your video size, so if you get (0.6, 0.8) then it's really (0.6*video_width, 0.8*video_height) in pixels.

      Cheers!

      Delete
    2. (0,0) is the Top left corner

      Delete
  2. Thanks for the script, it was really helpful. However there are a couple of problems (at least in the more recent version of blender):
    1. The script will miss any tracks if they don't start at frame 0. (My tracks usually start at frame 1, for example).
    2. Blender now has object tracking, and this script misses the tracks that are assigned to objects instead of the camera.

    The script below should fix these:
    https://gist.github.com/anonymous/5663418

    ReplyDelete
    Replies
    1. Hello, I meet a problem is that an error has reported in “ open_data = open(filename, 'w', newline='')”. Is this the problem of the filepath?

      Delete
  3. [Re-posting interesting anonymous comment which was eaten by the blogpost spam filter]

    Hello, there is small improvment for this script
    - use of csv module instead of print() > easier to change data fromat
    - dict() for saving data with another parts.

    https://gist.github.com/anonymous/31c915d611f0a84e5d33

    ReplyDelete
  4. Thank you very much! Under Windows, especially Win7, the path needs some tweaking

    ReplyDelete
    Replies
    1. Ok, feel free to post a tweaked version here. I don't have windows, so I can't test it.

      Delete
    2. This comment has been removed by the author.

      Delete
  5. Under Windows, the default working directory seems to be that one where blender.exe is located. Maybe, this can be changed in User preferences.

    Anyway, the following addition makes the folder with your blend file your default directory, then it checks if the subfolder_for_exports exists and creates it if it does not.


    import os
    subfolder_for_exports = 'data' # change it to whatever name
    os.chdir(os.path.dirname(os.path.dirname(__file__)))
    if not os.path.exists(subfolder_for_exports):
    REPLACE WTH SPACESos.makedirs(subfolder_for_exports)

    You know that notorious IdentationError when copy-n-pasting python scripts ;-)

    ReplyDelete
  6. Thank you. I was precisely going to write a script to export the trackers position and a quick search on google brought me here. You saved me a couple of hours ;)

    ReplyDelete
  7. Thanks for sharing! I have a quick question. Can I have the actual frame number saved as well. In my images, some of the frames does not have the object that I want to track. For those frames I want to have NaN values for x and y coordinates. Thanks a lot in advance

    ReplyDelete
    Replies
    1. Sure, just replace
      f.write('{0} {1}\n'.format(coords[0], coords[1]))
      by something like
      f.write('{0} {1} {2}\n'.format(coords[0], coords[1], frameno))

      Then you will get the frame number in a third column.

      Delete
  8. Thanks for the post! Helped a lot.

    ReplyDelete
  9. Hey I'm new to python & Blender. Could someone please help with changing the code to put all tracks into one .csv file, instead of creating a .csv file for each track?

    ReplyDelete
  10. Fantastic script. And good question from the colleague above:

    Hey I'm new to python & Blender. Could someone please help with changing the code to put all tracks into one .csv file, instead of creating a .csv file for each track?

    ReplyDelete
  11. Howdy terrific blog! Does running a blog like this take a massive amount work? I have virtually no understanding of coding however I had been hoping to start my
    own blog soon. 토토

    ReplyDelete
  12. I have been browsing online more than 3 hours today, yet I never found any interesting article like yours. It's pretty worth enough for me. In my view, if all site owners and bloggers made good content as you did, the net will be a lot more useful than ever before 토 토

    ReplyDelete

Note: Only a member of this blog may post a comment.