4

I'm trying to read a .flo file as a numpy 2Channels image.

The format is described like this:

".flo" file format used for optical flow evaluation

Stores 2-band float image for horizontal (u) and vertical (v) flow components.
Floats are stored in little-endian order.
A flow value is considered "unknown" if either |u| or |v| is greater than 1e9.

bytes  contents

0-3     tag: "PIEH" in ASCII, which in little endian happens to be the float 202021.25
        (just a sanity check that floats are represented correctly)
4-7     width as an integer
8-11    height as an integer
12-end  data (width*height*2*4 bytes total)
        the float values for u and v, interleaved, in row order, i.e.,
        u[row0,col0], v[row0,col0], u[row0,col1], v[row0,col1], ...

(Excerpt from this readme)

Here's my code but I'm kind of stuck, I don't know how to read the file as a 2 Channels numpy 2D array.

import numpy as np
import os

# test.flo, 512*512 optical flow file

f = open('test.flo', 'rb')
f.seek(11, os.SEEK_SET)  # skip header bytes


data_array = np.fromfile(f, np.float16)
data_2D = np.resize(data_array, (512, 512))

Maybe someone knows how to do that ?

Oliver W.
  • 13,169
  • 3
  • 37
  • 50
Paul Parneix
  • 129
  • 1
  • 9
  • well, the format is described in the README you linked, and sample C++ code for reading `.flo` files is [here](http://vision.middlebury.edu/flow/code/flow-code/flowIO.cpp) - see the `ReadFlowFile()` function (line 46) for details. Translation shouldn't be too terribly difficult for someone with a little bit of knowledge of C/C++ (which unfortunately is not me...) – MattDMo Jan 18 '15 at 19:18
  • Also, if you download [`flow-code-matlab.zip`](http://vision.middlebury.edu/flow/code/flow-code-matlab.zip), you can find `readFlowFile.m` which has the same code in Matlab, if you're more fluent in that. – MattDMo Jan 18 '15 at 19:25
  • hi, thanks for comments, I'm not that fluent in C++ or mathlab, but I'll try. Actually I'm trying to find a numpy solution to avoid C++ style for loop, that will be quite slow in python. – Paul Parneix Jan 18 '15 at 19:36
  • Two things that jump out: 1) You are specifying np.float16. From the readme and the C source code, there are two bands of 4 byte (32-bit) floats. Try np.float32. 2) You are fseeking offset 11.. shouldn't that be offset 12 for the start of the data? – bsa Jan 19 '15 at 00:14

2 Answers2

11

Try this. I've tested it on one .flo file so far.

import numpy as np
import sys

if __name__ == '__main__':
    if len(sys.argv) <= 1:
        print('Specify a .flo file on the command line.')
    else:
        with open(sys.argv[1], 'rb') as f:
            magic, = np.fromfile(f, np.float32, count=1)
            if 202021.25 != magic:
                print('Magic number incorrect. Invalid .flo file')
            else:
                w, h = np.fromfile(f, np.int32, count=2)
                print(f'Reading {w} x {h} flo file')
                data = np.fromfile(f, np.float32, count=2*w*h)
                # Reshape data into 3D array (columns, rows, bands)
                data2D = np.resize(data, (w, h, 2))
                print(data2D)
bsa
  • 2,671
  • 21
  • 31
  • Thanks ! It's working perfectly. I ended with a working solution, but it was quite dirty ; specify w & h, read the whole file and delete the header... your way is really clever. thanks again :) – Paul Parneix Jan 19 '15 at 02:28
  • 2
    Flip `w` and `h` in `(w, h, 2)`->`(h, w 2)` if you want to view it with something like Matplotlib. – BeRecursive Mar 30 '15 at 15:34
  • could you please give the C++ code for this. I would like to compare two fol files ( optical flow Sintel dataset) and get the evaluation of algorithms.I want to get "EPE all EPE matched EPE unmatched d0-10 d10-60 d60-140 s0-10 s10-40 s40+" result of Optical flow from "http://sintel.is.tue.mpg.de/results" dataset. I used OpenCV 3, VC++ 2013, Win 7 64bit. and I need example code of getting this results. – Farshid PirahanSiah Oct 21 '15 at 15:14
  • How about posting a new question, and linking back to this one. Post the code you have so far. – bsa Oct 23 '15 at 11:57
  • I'm a tad confused if something is wrong here, as you are reading in the same number for width and height `w = np.fromfile(f, np.int32, count=1) ; h = np.fromfile(f, np.int32, count=1)` – redrubia Feb 24 '17 at 17:06
  • `np.fromfile` advances the file pointer. So the first call reads 4 bytes, then the second call reads the next 4 bytes. – bsa Feb 26 '17 at 01:48
6

bsa's answer does not work for python 3.5 onwards. The small modification shown below, e.g. np.fromfile(f, np.int32, count=1)[0], will.

import numpy as np
import os
import sys

# WARNING: this will work on little-endian architectures (eg Intel x86) only!
if '__main__' == __name__:
    if len(sys.argv) > 1:
        with open(sys.argv[1], 'rb') as f:
            magic = np.fromfile(f, np.float32, count=1)
            if 202021.25 != magic:
                print('Magic number incorrect. Invalid .flo file')
            else:
                w = np.fromfile(f, np.int32, count=1)[0]
                h = np.fromfile(f, np.int32, count=1)[0]
                print('Reading %d x %d flo file' % (w, h))
                data = np.fromfile(f, np.float32, count=2*w*h)
                # Reshape data into 3D array (columns, rows, bands)
                data2D = np.resize(data, (h, w, 2))
    else:
        print('Specify a .flo file on the command line.')
Mr.Epic Fail
  • 358
  • 3
  • 15
  • I don't think your code will work in Python 3.5 because you are still using Python 2 style `print 'blah'` instead of `print('blah')`.. – bsa Sep 20 '19 at 17:00
  • I've updated my code so it works with Python 3.6 or higher. – bsa Sep 21 '19 at 00:04