data / flow_code /C /flowIO.cpp
doanh25032004's picture
Add files using upload-large-folder tool
9913017 verified
Raw
History Blame Contribute Delete
4.68 kB
// flow_io.cpp
//
// read and write our simple .flo flow file format
// ".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], ...
//
// first four bytes, should be the same in little endian
#define TAG_FLOAT 202021.25 // check for this when READING the file
#define TAG_STRING "PIEH" // use this when WRITING the file
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "imageLib.h"
#include "flowIO.h"
// return whether flow vector is unknown
bool unknown_flow(float u, float v) {
return (fabs(u) > UNKNOWN_FLOW_THRESH)
|| (fabs(v) > UNKNOWN_FLOW_THRESH)
|| isnan(u) || isnan(v);
}
bool unknown_flow(float *f) {
return unknown_flow(f[0], f[1]);
}
// read a flow file into 2-band image
void ReadFlowFile(CFloatImage& img, const char* filename)
{
if (filename == NULL)
throw CError("ReadFlowFile: empty filename");
char *dot = strrchr(filename, '.');
if (strcmp(dot, ".flo") != 0)
throw CError("ReadFlowFile (%s): extension .flo expected", filename);
FILE *stream = fopen(filename, "rb");
if (stream == 0)
throw CError("ReadFlowFile: could not open %s", filename);
int width, height;
float tag;
if ((int)fread(&tag, sizeof(float), 1, stream) != 1 ||
(int)fread(&width, sizeof(int), 1, stream) != 1 ||
(int)fread(&height, sizeof(int), 1, stream) != 1)
throw CError("ReadFlowFile: problem reading file %s", filename);
if (tag != TAG_FLOAT) // simple test for correct endian-ness
throw CError("ReadFlowFile(%s): wrong tag (possibly due to big-endian machine?)", filename);
// another sanity check to see that integers were read correctly (99999 should do the trick...)
if (width < 1 || width > 99999)
throw CError("ReadFlowFile(%s): illegal width %d", filename, width);
if (height < 1 || height > 99999)
throw CError("ReadFlowFile(%s): illegal height %d", filename, height);
int nBands = 2;
CShape sh(width, height, nBands);
img.ReAllocate(sh);
//printf("reading %d x %d x 2 = %d floats\n", width, height, width*height*2);
int n = nBands * width;
for (int y = 0; y < height; y++) {
float* ptr = &img.Pixel(0, y, 0);
if ((int)fread(ptr, sizeof(float), n, stream) != n)
throw CError("ReadFlowFile(%s): file is too short", filename);
}
if (fgetc(stream) != EOF)
throw CError("ReadFlowFile(%s): file is too long", filename);
fclose(stream);
}
// write a 2-band image into flow file
void WriteFlowFile(CFloatImage img, const char* filename)
{
if (filename == NULL)
throw CError("WriteFlowFile: empty filename");
char *dot = strrchr(filename, '.');
if (dot == NULL)
throw CError("WriteFlowFile: extension required in filename '%s'", filename);
if (strcmp(dot, ".flo") != 0)
throw CError("WriteFlowFile: filename '%s' should have extension '.flo'", filename);
CShape sh = img.Shape();
int width = sh.width, height = sh.height, nBands = sh.nBands;
if (nBands != 2)
throw CError("WriteFlowFile(%s): image must have 2 bands", filename);
FILE *stream = fopen(filename, "wb");
if (stream == 0)
throw CError("WriteFlowFile: could not open %s", filename);
// write the header
fprintf(stream, TAG_STRING);
if ((int)fwrite(&width, sizeof(int), 1, stream) != 1 ||
(int)fwrite(&height, sizeof(int), 1, stream) != 1)
throw CError("WriteFlowFile(%s): problem writing header", filename);
// write the rows
int n = nBands * width;
for (int y = 0; y < height; y++) {
float* ptr = &img.Pixel(0, y, 0);
if ((int)fwrite(ptr, sizeof(float), n, stream) != n)
throw CError("WriteFlowFile(%s): problem writing data", filename);
}
fclose(stream);
}
/*
int main() {
try {
CShape sh(5, 1, 2);
CFloatImage img(sh);
img.ClearPixels();
img.Pixel(0, 0, 0) = -5.0f;
char *filename = "test.flo";
WriteFlowFile(img, filename);
ReadFlowFile(img, filename);
}
catch (CError &err) {
fprintf(stderr, err.message);
fprintf(stderr, "\n");
exit(1);
}
return 0;
}
*/