├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── README.md ├── alley_1_flow ├── frame_0001.flo ├── frame_0002.flo ├── frame_0003.flo ├── frame_0004.flo ├── frame_0005.flo ├── frame_0006.flo ├── frame_0007.flo ├── frame_0008.flo ├── frame_0009.flo └── frame_0010.flo ├── cli ├── CMakeLists.txt └── main.cpp ├── lib ├── CMakeLists.txt ├── README-FlowIO.md ├── color_flow.cpp ├── colorcode.cpp ├── colorcode.h ├── colortest.cpp ├── flowIO.cpp ├── flowIO.h ├── flowIOOpenCVWrapper.cpp ├── flowIOOpenCVWrapper.h ├── imageLib │ ├── CMakeLists.txt │ ├── Convert.cpp │ ├── Convert.h │ ├── Convolve.cpp │ ├── Convolve.h │ ├── Copyright.h │ ├── Error.h │ ├── Image.cpp │ ├── Image.h │ ├── ImageIO.cpp │ ├── ImageIO.h │ ├── ImageIOpng.cpp │ ├── License.txt │ ├── README-StereoMatcher.md │ ├── README.md │ ├── RefCntMem.cpp │ ├── RefCntMem.h │ └── imageLib.h ├── motiontocolor.cpp └── motiontocolor.h └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /alley_1_cflow/ 3 | /alley_1_flow_vis/ 4 | /nbproject/ 5 | *~ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | sudo: required 4 | dist: trusty 5 | 6 | compiler: 7 | - gcc 8 | 9 | before_script: 10 | - sudo apt-get install build-essential 11 | - sudo apt-get install cmake 12 | - sudo apt-get install libboost-all-dev 13 | - sudo apt-get install libopencv-dev 14 | - mkdir build 15 | - cd build 16 | - cmake .. 17 | 18 | script: make 19 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | add_subdirectory(lib) 4 | add_subdirectory(cli) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flow IO OpenCV 2 | 3 | [![Build Status](https://travis-ci.org/davidstutz/flow-io-opencv.svg?branch=master)](https://travis-ci.org/davidstutz/flow-io-opencv) 4 | 5 | This is a fork and [OpenCV](http://opencv.org/) wrapper of the optical flow input/output code provided as part of the [Sintel dataset](http://sintel.is.tue.mpg.de/) [1]. The code is based on `imageLib`, a small C++ library for multi-channel images based on the [StereoMatcher](http://research.microsoft.com/en-us/downloads/9bc7fd74-5953-4064-9732-76405573aaef/) [2] code by Daniel Scharstein and Richard Szeliski. We refer to: 6 | 7 | * [lib/README-FlowIO](lib/README-FlowIO.md): the original README shipped with the Sintel dataset. 8 | * [lib/imageLib/README](lib/imageLib/README.md): the original README of `imageLib` shipped with the Sintel dataset. 9 | * [lib/imageLib/README-StereoMatcher](lib/imageLib/README-StereoMatcher.md): the original README of the StereoMatcher. 10 | 11 | [1] D. J. Butler, J. Wulff, G. B. Stanley, M. J. Black. 12 | A naturalistic open source movie for optical flow evaluation. 13 | In European Conference on Computer Vision, pages 611 - 625, 2012. 14 | [2] D. Scharstein, R. Szeliski. 15 | A taxonomy and evaluation of dense two-frame stereo correspondence algorithms. 16 | Technical Report MSR-TR-2001-81, Microsoft Research, 2001. 17 | 18 | ## Compile 19 | 20 | The OpenCV wrapper is based on [CMake](http://www.cmake.org/) and (surprise!) OpenCV (for example, follow [Installing OpenCV on Linux](http://docs.opencv.org/doc/tutorials/introduction/linux_install/linux_install.html#linux-installation) to install OpenCV). The code has been tested on Ubuntu 14.04 and 14.10. 21 | 22 | $ sudo apt-get install cmake build-essential libboost-all-dev 23 | $ mkdir build 24 | $ cd build 25 | $ cmake .. 26 | $ make 27 | $ ./cli/cli --help 28 | Allowed options: 29 | --help produce help message 30 | --input-dir arg input directory 31 | --output-dir arg output directory 32 | --vis-dir arg visualize results in a separate directory 33 | 34 | The provided command line tool can be used to convert `.flo` files to `.txt` files using the `cv::FileStorage` format. Additionally, the tool provides visualization capabilities. For example: 35 | 36 | $ ./cli/cli ../alley_1_flow ../alley_1_cflow --vis-dir ../alley_1_flow_vis 37 | 38 | The result is shown below: 39 | 40 | ![Example: visualized flow of the alley_1 sequence.](screenshot.png?raw=true "Example: visualized flow of the alley_1 sequence.") 41 | 42 | ## Usage 43 | 44 | A usage example is provided in `cli/main.cpp`: 45 | 46 | // Define input file and output (visualization) path (or directly output file). 47 | boost::filesystem::path in_file(...); 48 | boost::filesystem::path out_dir(...); 49 | boost::filesystem::path vis_dir(...); 50 | 51 | cv::Mat flow = FlowIOOpenCVWrapper::read(in_file.string()); 52 | 53 | boost::filesystem::path txt_path = out_dir / in_file.filename(); 54 | IO::writeMat(txt_path.string() + ".txt", flow); 55 | 56 | if (visualize) { 57 | cv::Mat image = FlowIOOpenCVWrapper::flowToColor(flow); 58 | 59 | boost::filesystem::path image_path = vis_dir / in_file.filename(); 60 | cv::imwrite(image_path.string() + ".png", image); 61 | } 62 | 63 | ## License 64 | 65 | See `lib/README-FlowIO.md` and `lib/imageLib/README.md` for license information. The OpenCV wrapper and the corresponding command line tool are licensed as follows: 66 | 67 | Copyright (c) 2015, David Stutz 68 | All rights reserved. 69 | 70 | Redistribution and use in source and binary forms, with or without modification, 71 | are permitted provided that the following conditions are met: 72 | 73 | * Redistributions of source code must retain the above copyright notice,this list of conditions and the following disclaimer. 74 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 75 | * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 76 | 77 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 78 | -------------------------------------------------------------------------------- /alley_1_flow/frame_0001.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0001.flo -------------------------------------------------------------------------------- /alley_1_flow/frame_0002.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0002.flo -------------------------------------------------------------------------------- /alley_1_flow/frame_0003.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0003.flo -------------------------------------------------------------------------------- /alley_1_flow/frame_0004.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0004.flo -------------------------------------------------------------------------------- /alley_1_flow/frame_0005.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0005.flo -------------------------------------------------------------------------------- /alley_1_flow/frame_0006.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0006.flo -------------------------------------------------------------------------------- /alley_1_flow/frame_0007.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0007.flo -------------------------------------------------------------------------------- /alley_1_flow/frame_0008.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0008.flo -------------------------------------------------------------------------------- /alley_1_flow/frame_0009.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0009.flo -------------------------------------------------------------------------------- /alley_1_flow/frame_0010.flo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/alley_1_flow/frame_0010.flo -------------------------------------------------------------------------------- /cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 4 | 5 | find_package(OpenCV REQUIRED) 6 | find_package(Boost COMPONENTS system filesystem program_options REQUIRED) 7 | include_directories(../lib/imageLib/ ../lib/ ${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) 8 | 9 | add_executable(cli main.cpp) 10 | target_link_libraries(cli flow_io flow_io_imagelib ${OpenCV_LIBRARIES} ${Boost_LIBRARIES}) 11 | -------------------------------------------------------------------------------- /cli/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Example for flow reading and visualization. The command line tool converts all 3 | * .flo files in the given directory to .txt files (stored using cv::FileStorage) 4 | * and creates visualizations as .png images. 5 | * 6 | * Usage: 7 | * $ ./cli/cli --help 8 | * Allowed options: 9 | * --help produce help message 10 | * --input-dir arg input directory 11 | * --output-dir arg output directory 12 | * --vis-dir arg visualize results in a separate directory 13 | * 14 | * Copyright (c) 2015, David Stutz 15 | * All rights reserved. 16 | * 17 | * Redistribution and use in source and binary forms, with or without modification, 18 | * are permitted provided that the following conditions are met: 19 | * 20 | * - Redistributions of source code must retain the above copyright notice, 21 | * this list of conditions and the following disclaimer. 22 | * - Redistributions in binary form must reproduce the above copyright notice, 23 | * this list of conditions and the following disclaimer in the documentation and/or 24 | * other materials provided with the distribution. 25 | * - Neither the name of David Stutz nor the names of its contributors may be 26 | * used to endorse or promote products derived from this software without specific 27 | * prior written permission. 28 | * 29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 30 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 33 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 34 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 35 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 36 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 37 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | * POSSIBILITY OF SUCH DAMAGE. 40 | */ 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include "flowIOOpenCVWrapper.h" 47 | 48 | std::multimap readDirectory(boost::filesystem::path directory, 49 | std::vector extensions) { 50 | 51 | assert(boost::filesystem::is_directory(directory)); 52 | assert(!extensions.empty()); 53 | 54 | std::multimap files; 55 | boost::filesystem::directory_iterator end; 56 | 57 | for (boost::filesystem::directory_iterator it(directory); it != end; ++it) { 58 | 59 | // Check extensions. 60 | bool correct = false; 61 | for (std::vector::iterator ex = extensions.begin(); 62 | ex != extensions.end(); ++ex) { 63 | 64 | if (*ex == it->path().extension().string()) { 65 | correct = true; 66 | } 67 | } 68 | 69 | if (correct) { 70 | files.insert(std::multimap::value_type(it->path().string(), it->path())); 71 | } 72 | } 73 | 74 | return files; 75 | } 76 | 77 | int writeMat(boost::filesystem::path file, const cv::Mat& mat) { 78 | assert(mat.rows > 0 && mat.cols > 0); 79 | 80 | cv::FileStorage fs(file.string(), cv::FileStorage::WRITE); 81 | fs << "mat" << mat; 82 | 83 | fs.release(); 84 | return mat.rows; 85 | } 86 | 87 | int main(int argc, char** argv) { 88 | 89 | boost::program_options::options_description desc("Allowed options"); 90 | desc.add_options() 91 | ("help", "produce help message") 92 | ("input-dir", boost::program_options::value(), "input directory") 93 | ("output-dir", boost::program_options::value(), "output directory") 94 | ("vis-dir", boost::program_options::value()->default_value(""), "visualize results in a separate directory"); 95 | 96 | boost::program_options::positional_options_description positionals; 97 | positionals.add("input-dir", 1); 98 | positionals.add("output-dir", 1); 99 | 100 | boost::program_options::variables_map parameters; 101 | boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(desc).positional(positionals).run(), parameters); 102 | boost::program_options::notify(parameters); 103 | 104 | if (parameters.find("help") != parameters.end()) { 105 | std::cout << desc << std::endl; 106 | return 1; 107 | } 108 | 109 | boost::filesystem::path in_dir(parameters["input-dir"].as()); 110 | if (!boost::filesystem::is_directory(in_dir)) { 111 | std::cout << "Input directory does not exist." << std::endl; 112 | return 1; 113 | } 114 | 115 | boost::filesystem::path out_dir(parameters["output-dir"].as()); 116 | if (!boost::filesystem::is_directory(out_dir)) { 117 | boost::filesystem::create_directories(out_dir); 118 | } 119 | 120 | bool visualize = false; 121 | boost::filesystem::path vis_dir(parameters["vis-dir"].as()); 122 | 123 | if (!vis_dir.empty()) { 124 | if (!boost::filesystem::is_directory(vis_dir)) { 125 | boost::filesystem::create_directories(vis_dir); 126 | } 127 | 128 | visualize = true; 129 | } 130 | 131 | std::vector extension; 132 | extension.push_back(".flo"); 133 | 134 | std::multimap frames = readDirectory(in_dir, extension); 135 | assert(frames.size() > 0); 136 | 137 | for (std::multimap::iterator it = frames.begin(); 138 | it != frames.end(); it++) { 139 | // std::cout << "Converting flow " << it->second.string() << "." << std::endl; 140 | 141 | // Read .flo file. 142 | cv::Mat flow = FlowIOOpenCVWrapper::read(it->second.string()); 143 | 144 | boost::filesystem::path txt_path = out_dir / it->second.filename(); 145 | writeMat(txt_path.string() + ".txt", flow); 146 | 147 | if (visualize) { 148 | cv::Mat image = FlowIOOpenCVWrapper::flowToColor(flow); 149 | 150 | boost::filesystem::path image_path = vis_dir / it->second.filename(); 151 | cv::imwrite(image_path.string() + ".png", image); 152 | 153 | // std::cout << "Visualized flow " << image_path.string() << "." << std::endl; 154 | } 155 | } 156 | 157 | return 0; 158 | } 159 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | add_subdirectory(imageLib) 4 | 5 | find_package(OpenCV REQUIRED) 6 | include_directories(./imageLib/ ${OpenCV_INCLUDE_DIRS}) 7 | 8 | add_library(flow_io flowIO.cpp flowIO.h colorcode.cpp motiontocolor.cpp flowIOOpenCVWrapper.cpp) 9 | target_link_libraries(flow_io flow_io_imagelib ${OpenCV_LIBRARIES}) 10 | -------------------------------------------------------------------------------- /lib/README-FlowIO.md: -------------------------------------------------------------------------------- 1 | # Original README: Flow IO 2 | 3 | Some utilities for reading, writing, and color-coding `.flo` images. 4 | 5 | Daniel Scharstein, 7/2/07. 6 | * Updated 2/9/08 to fix bug in `color_flow.cpp`. 7 | * Updated 6/9/09 to make robust to `NaN` or constant 0 flow (thanks Jan Bouecke). 8 | 9 | See `flowIO.cpp` for sample code for reading and writing `.flo` files. 10 | Here's an excerpt from this file describing the flow file format: 11 | 12 | ## `.flo` File Format 13 | 14 | Stores 2-band float image for horizontal (u) and vertical (v) flow components. 15 | Floats are stored in little-endian order. 16 | A flow value is considered "unknown" if either |u| or |v| is greater than 1e9. 17 | 18 | | Bytes | Content | 19 | |--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| 20 | | 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) | 21 | | 4-7 | width as an integer | 22 | | 8-11 | height as an integer | 23 | | 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], ...` | 24 | 25 | 26 | Once you have a `.flo` file, you can create a color coding of it using `color_flow`. 27 | 28 | Use `colortest` to visualize the encoding. 29 | 30 | ## Compile 31 | 32 | cd imageLib 33 | make 34 | cd .. 35 | make 36 | ./colortest 10 colors.png 37 | -------------------------------------------------------------------------------- /lib/color_flow.cpp: -------------------------------------------------------------------------------- 1 | // color_flow.cpp 2 | // color-code motion field 3 | // normalizes based on specified value, or on maximum motion present otherwise 4 | 5 | // DS 2/9/08 fixed bug in MotionToColor concerning reallocation of colim (thanks Yunpeng!) 6 | 7 | static char *usage = "\n usage: %s [-quiet] in.flo out.png [maxmotion]\n"; 8 | 9 | #include 10 | #include 11 | #include "imageLib.h" 12 | #include "flowIO.h" 13 | #include "colorcode.h" 14 | 15 | int verbose = 1; 16 | 17 | void MotionToColor(CFloatImage motim, CByteImage &colim, float maxmotion) 18 | { 19 | CShape sh = motim.Shape(); 20 | int width = sh.width, height = sh.height; 21 | colim.ReAllocate(CShape(width, height, 3)); 22 | int x, y; 23 | // determine motion range: 24 | float maxx = -999, maxy = -999; 25 | float minx = 999, miny = 999; 26 | float maxrad = -1; 27 | for (y = 0; y < height; y++) { 28 | for (x = 0; x < width; x++) { 29 | float fx = motim.Pixel(x, y, 0); 30 | float fy = motim.Pixel(x, y, 1); 31 | if (unknown_flow(fx, fy)) 32 | continue; 33 | maxx = __max(maxx, fx); 34 | maxy = __max(maxy, fy); 35 | minx = __min(minx, fx); 36 | miny = __min(miny, fy); 37 | float rad = sqrt(fx * fx + fy * fy); 38 | maxrad = __max(maxrad, rad); 39 | } 40 | } 41 | printf("max motion: %.4f motion range: u = %.3f .. %.3f; v = %.3f .. %.3f\n", 42 | maxrad, minx, maxx, miny, maxy); 43 | 44 | 45 | if (maxmotion > 0) // i.e., specified on commandline 46 | maxrad = maxmotion; 47 | 48 | if (maxrad == 0) // if flow == 0 everywhere 49 | maxrad = 1; 50 | 51 | if (verbose) 52 | fprintf(stderr, "normalizing by %g\n", maxrad); 53 | 54 | for (y = 0; y < height; y++) { 55 | for (x = 0; x < width; x++) { 56 | float fx = motim.Pixel(x, y, 0); 57 | float fy = motim.Pixel(x, y, 1); 58 | uchar *pix = &colim.Pixel(x, y, 0); 59 | if (unknown_flow(fx, fy)) { 60 | pix[0] = pix[1] = pix[2] = 0; 61 | } else { 62 | computeColor(fx/maxrad, fy/maxrad, pix); 63 | } 64 | } 65 | } 66 | } 67 | 68 | int main(int argc, char *argv[]) 69 | { 70 | try { 71 | int argn = 1; 72 | if (argc > 1 && argv[1][0]=='-' && argv[1][1]=='q') { 73 | verbose = 0; 74 | argn++; 75 | } 76 | if (argn >= argc-3 && argn <= argc-2) { 77 | char *flowname = argv[argn++]; 78 | char *outname = argv[argn++]; 79 | float maxmotion = argn < argc ? atof(argv[argn++]) : -1; 80 | CFloatImage im, fband; 81 | ReadFlowFile(im, flowname); 82 | CByteImage band, outim; 83 | CShape sh = im.Shape(); 84 | sh.nBands = 3; 85 | outim.ReAllocate(sh); 86 | outim.ClearPixels(); 87 | MotionToColor(im, outim, maxmotion); 88 | WriteImageVerb(outim, outname, verbose); 89 | } else 90 | throw CError(usage, argv[0]); 91 | } 92 | catch (CError &err) { 93 | fprintf(stderr, err.message); 94 | fprintf(stderr, "\n"); 95 | return -1; 96 | } 97 | 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /lib/colorcode.cpp: -------------------------------------------------------------------------------- 1 | // colorcode.cpp 2 | // 3 | // Color encoding of flow vectors 4 | // adapted from the color circle idea described at 5 | // http://members.shaw.ca/quadibloc/other/colint.htm 6 | // 7 | // Daniel Scharstein, 4/2007 8 | // added tick marks and out-of-range coding 6/05/07 9 | 10 | #include 11 | #include 12 | typedef unsigned char uchar; 13 | 14 | int ncols = 0; 15 | #define MAXCOLS 60 16 | int colorwheel[MAXCOLS][3]; 17 | 18 | 19 | void setcols(int r, int g, int b, int k) 20 | { 21 | colorwheel[k][0] = r; 22 | colorwheel[k][1] = g; 23 | colorwheel[k][2] = b; 24 | } 25 | 26 | void makecolorwheel() 27 | { 28 | // relative lengths of color transitions: 29 | // these are chosen based on perceptual similarity 30 | // (e.g. one can distinguish more shades between red and yellow 31 | // than between yellow and green) 32 | int RY = 15; 33 | int YG = 6; 34 | int GC = 4; 35 | int CB = 11; 36 | int BM = 13; 37 | int MR = 6; 38 | ncols = RY + YG + GC + CB + BM + MR; 39 | //printf("ncols = %d\n", ncols); 40 | if (ncols > MAXCOLS) 41 | exit(1); 42 | int i; 43 | int k = 0; 44 | for (i = 0; i < RY; i++) setcols(255, 255*i/RY, 0, k++); 45 | for (i = 0; i < YG; i++) setcols(255-255*i/YG, 255, 0, k++); 46 | for (i = 0; i < GC; i++) setcols(0, 255, 255*i/GC, k++); 47 | for (i = 0; i < CB; i++) setcols(0, 255-255*i/CB, 255, k++); 48 | for (i = 0; i < BM; i++) setcols(255*i/BM, 0, 255, k++); 49 | for (i = 0; i < MR; i++) setcols(255, 0, 255-255*i/MR, k++); 50 | } 51 | 52 | void computeColor(float fx, float fy, uchar *pix) 53 | { 54 | if (ncols == 0) 55 | makecolorwheel(); 56 | 57 | float rad = sqrt(fx * fx + fy * fy); 58 | float a = atan2(-fy, -fx) / M_PI; 59 | float fk = (a + 1.0) / 2.0 * (ncols-1); 60 | int k0 = (int)fk; 61 | int k1 = (k0 + 1) % ncols; 62 | float f = fk - k0; 63 | //f = 0; // uncomment to see original color wheel 64 | for (int b = 0; b < 3; b++) { 65 | float col0 = colorwheel[k0][b] / 255.0; 66 | float col1 = colorwheel[k1][b] / 255.0; 67 | float col = (1 - f) * col0 + f * col1; 68 | if (rad <= 1) 69 | col = 1 - rad * (1 - col); // increase saturation with radius 70 | else 71 | col *= .75; // out of range 72 | pix[2 - b] = (int)(255.0 * col); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/colorcode.h: -------------------------------------------------------------------------------- 1 | void computeColor(float fx, float fy, uchar *pix); 2 | -------------------------------------------------------------------------------- /lib/colortest.cpp: -------------------------------------------------------------------------------- 1 | // colortest.cpp 2 | 3 | // create a test image showing the color encoding 4 | 5 | static char usage[] = "usage: %s range outimage [size]\n"; 6 | 7 | # include 8 | # include 9 | #include "imageLib.h" 10 | #include "colorcode.h" 11 | 12 | int main(int argc, char **argv) 13 | { 14 | int verbose = 1; 15 | if (argc < 3) { 16 | fprintf(stderr, usage, argv[0]); 17 | exit(1); 18 | } 19 | int optind = 1; 20 | float truerange = atof(argv[optind++]); 21 | char *outname = argv[optind++]; 22 | int size = optind < argc ? atoi(argv[optind++]) : 151; 23 | 24 | float range = 1.04 * truerange; // make picture a bit bigger to show out-of-range coding 25 | try { 26 | CShape sh(size, size, 3); 27 | CByteImage out(sh); 28 | 29 | int s2 = size/2; 30 | for (int y = 0; y < size; y++) { 31 | for (int x = 0; x < size; x++) { 32 | float fx = (float)x / (float)s2 * range - range; 33 | float fy = (float)y / (float)s2 * range - range; 34 | if (x == s2 || y == s2) // make black coordinate axes 35 | continue; 36 | uchar *pix = &out.Pixel(x, y, 0); 37 | //fx = rintf(fx); 38 | //fy = rintf(fy); 39 | computeColor(fx/truerange, fy/truerange, pix); 40 | } 41 | } 42 | int ir = (int)truerange; 43 | int ticksize = size < 120 ? 1 : 2; 44 | for (int k = -ir; k <= ir; k++) { 45 | int ik = (int)(k / range * s2) + s2; 46 | for (int t = -ticksize; t <= ticksize; t++) { 47 | uchar *pix; 48 | pix = &out.Pixel(ik, s2 + t, 0); pix[0] = pix[1] = pix[2] = 0; 49 | pix = &out.Pixel(s2 + t, ik, 0); pix[0] = pix[1] = pix[2] = 0; 50 | } 51 | } 52 | 53 | WriteImageVerb(out, outname, verbose); 54 | } 55 | catch (CError &err) { 56 | fprintf(stderr, err.message); 57 | fprintf(stderr, "\n"); 58 | exit(1); 59 | } 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /lib/flowIO.cpp: -------------------------------------------------------------------------------- 1 | // flow_io.cpp 2 | // 3 | // read and write our simple .flo flow file format 4 | 5 | // ".flo" file format used for optical flow evaluation 6 | // 7 | // Stores 2-band float image for horizontal (u) and vertical (v) flow components. 8 | // Floats are stored in little-endian order. 9 | // A flow value is considered "unknown" if either |u| or |v| is greater than 1e9. 10 | // 11 | // bytes contents 12 | // 13 | // 0-3 tag: "PIEH" in ASCII, which in little endian happens to be the float 202021.25 14 | // (just a sanity check that floats are represented correctly) 15 | // 4-7 width as an integer 16 | // 8-11 height as an integer 17 | // 12-end data (width*height*2*4 bytes total) 18 | // the float values for u and v, interleaved, in row order, i.e., 19 | // u[row0,col0], v[row0,col0], u[row0,col1], v[row0,col1], ... 20 | // 21 | 22 | 23 | // first four bytes, should be the same in little endian 24 | #define TAG_FLOAT 202021.25 // check for this when READING the file 25 | #define TAG_STRING "PIEH" // use this when WRITING the file 26 | 27 | 28 | #include 29 | #include 30 | #include 31 | #include "imageLib.h" 32 | #include "flowIO.h" 33 | #include 34 | 35 | // return whether flow vector is unknown 36 | bool unknown_flow(float u, float v) { 37 | return (fabs(u) > UNKNOWN_FLOW_THRESH) 38 | || (fabs(v) > UNKNOWN_FLOW_THRESH) 39 | || isnan(u) || isnan(v); 40 | } 41 | 42 | bool unknown_flow(float *f) { 43 | return unknown_flow(f[0], f[1]); 44 | } 45 | 46 | // read a flow file into 2-band image 47 | void ReadFlowFile(CFloatImage& img, const char* filename) 48 | { 49 | if (filename == NULL) 50 | throw CError("ReadFlowFile: empty filename"); 51 | 52 | const char *dot = strrchr(filename, '.'); 53 | if (strcmp(dot, ".flo") != 0) 54 | throw CError("ReadFlowFile (%s): extension .flo expected", filename); 55 | 56 | FILE *stream = fopen(filename, "rb"); 57 | if (stream == 0) 58 | throw CError("ReadFlowFile: could not open %s", filename); 59 | 60 | int width, height; 61 | float tag; 62 | 63 | if ((int)fread(&tag, sizeof(float), 1, stream) != 1 || 64 | (int)fread(&width, sizeof(int), 1, stream) != 1 || 65 | (int)fread(&height, sizeof(int), 1, stream) != 1) 66 | throw CError("ReadFlowFile: problem reading file %s", filename); 67 | 68 | if (tag != TAG_FLOAT) // simple test for correct endian-ness 69 | throw CError("ReadFlowFile(%s): wrong tag (possibly due to big-endian machine?)", filename); 70 | 71 | // another sanity check to see that integers were read correctly (99999 should do the trick...) 72 | if (width < 1 || width > 99999) 73 | throw CError("ReadFlowFile(%s): illegal width %d", filename, width); 74 | 75 | if (height < 1 || height > 99999) 76 | throw CError("ReadFlowFile(%s): illegal height %d", filename, height); 77 | 78 | int nBands = 2; 79 | CShape sh(width, height, nBands); 80 | img.ReAllocate(sh); 81 | 82 | //printf("reading %d x %d x 2 = %d floats\n", width, height, width*height*2); 83 | int n = nBands * width; 84 | for (int y = 0; y < height; y++) { 85 | float* ptr = &img.Pixel(0, y, 0); 86 | if ((int)fread(ptr, sizeof(float), n, stream) != n) 87 | throw CError("ReadFlowFile(%s): file is too short", filename); 88 | } 89 | 90 | if (fgetc(stream) != EOF) 91 | throw CError("ReadFlowFile(%s): file is too long", filename); 92 | 93 | 94 | fclose(stream); 95 | } 96 | 97 | // write a 2-band image into flow file 98 | void WriteFlowFile(CFloatImage img, const char* filename) 99 | { 100 | if (filename == NULL) 101 | throw CError("WriteFlowFile: empty filename"); 102 | 103 | const char *dot = strrchr(filename, '.'); 104 | if (dot == NULL) 105 | throw CError("WriteFlowFile: extension required in filename '%s'", filename); 106 | 107 | if (strcmp(dot, ".flo") != 0) 108 | throw CError("WriteFlowFile: filename '%s' should have extension '.flo'", filename); 109 | 110 | CShape sh = img.Shape(); 111 | int width = sh.width, height = sh.height, nBands = sh.nBands; 112 | 113 | if (nBands != 2) 114 | throw CError("WriteFlowFile(%s): image must have 2 bands", filename); 115 | 116 | FILE *stream = fopen(filename, "wb"); 117 | if (stream == 0) 118 | throw CError("WriteFlowFile: could not open %s", filename); 119 | 120 | // write the header 121 | fprintf(stream, TAG_STRING); 122 | if ((int)fwrite(&width, sizeof(int), 1, stream) != 1 || 123 | (int)fwrite(&height, sizeof(int), 1, stream) != 1) 124 | throw CError("WriteFlowFile(%s): problem writing header", filename); 125 | 126 | // write the rows 127 | int n = nBands * width; 128 | for (int y = 0; y < height; y++) { 129 | float* ptr = &img.Pixel(0, y, 0); 130 | if ((int)fwrite(ptr, sizeof(float), n, stream) != n) 131 | throw CError("WriteFlowFile(%s): problem writing data", filename); 132 | } 133 | 134 | fclose(stream); 135 | } 136 | 137 | 138 | /* 139 | int main() { 140 | 141 | try { 142 | CShape sh(5, 1, 2); 143 | CFloatImage img(sh); 144 | img.ClearPixels(); 145 | img.Pixel(0, 0, 0) = -5.0f; 146 | char *filename = "test.flo"; 147 | 148 | WriteFlowFile(img, filename); 149 | ReadFlowFile(img, filename); 150 | } 151 | catch (CError &err) { 152 | fprintf(stderr, err.message); 153 | fprintf(stderr, "\n"); 154 | exit(1); 155 | } 156 | 157 | return 0; 158 | } 159 | */ 160 | -------------------------------------------------------------------------------- /lib/flowIO.h: -------------------------------------------------------------------------------- 1 | // flowIO.h 2 | 3 | // the "official" threshold - if the absolute value of either 4 | // flow component is greater, it's considered unknown 5 | #define UNKNOWN_FLOW_THRESH 1e9 6 | 7 | // value to use to represent unknown flow 8 | #define UNKNOWN_FLOW 1e10 9 | 10 | // return whether flow vector is unknown 11 | bool unknown_flow(float u, float v); 12 | bool unknown_flow(float *f); 13 | 14 | // read a flow file into 2-band image 15 | void ReadFlowFile(CFloatImage& img, const char* filename); 16 | 17 | // write a 2-band image into flow file 18 | void WriteFlowFile(CFloatImage img, const char* filename); 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/flowIOOpenCVWrapper.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * OpenCV wrapper for optical flow input/output and visualization capabilities 3 | * provided by the Sintel dataset [1] based on imageLib, originally developed 4 | * as part of StereoMatcher [2]. 5 | * 6 | * [1] D. J. Butler, J. Wulff, G. B. Stanley, M. J. Black. 7 | * A naturalistic open source movie for optical flow evaluation. 8 | * In European Conference on Computer Vision, pages 611 - 625, 2012. 9 | * [2] D. Scharstein, R. Szeliski. 10 | * A taxonomy and evaluation of dense two-frame stereo correspondence algorithms. 11 | * Technical Report MSR-TR-2001-81, Microsoft Research, 2001. 12 | * 13 | * Copyright (c) 2015, David Stutz 14 | * All rights reserved. 15 | * 16 | * Redistribution and use in source and binary forms, with or without modification, 17 | * are permitted provided that the following conditions are met: 18 | * 19 | * - Redistributions of source code must retain the above copyright notice, 20 | * this list of conditions and the following disclaimer. 21 | * - Redistributions in binary form must reproduce the above copyright notice, 22 | * this list of conditions and the following disclaimer in the documentation and/or 23 | * other materials provided with the distribution. 24 | * - Neither the name of David Stutz nor the names of its contributors may be 25 | * used to endorse or promote products derived from this software without specific 26 | * prior written permission. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 32 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 | * POSSIBILITY OF SUCH DAMAGE. 39 | */ 40 | #include "flowIOOpenCVWrapper.h" 41 | #include "imageLib.h" // Important to include this before flowIO.h 42 | #include "flowIO.h" 43 | #include "colorcode.h" 44 | #include "motiontocolor.h" 45 | 46 | cv::Mat FlowIOOpenCVWrapper::read(std::string path) { 47 | 48 | CFloatImage flow; 49 | ReadFlowFile(flow, path.c_str()); 50 | 51 | int rows = flow.Shape().height; 52 | int cols = flow.Shape().width; 53 | 54 | assert(rows > 0); 55 | assert(cols > 0); 56 | assert(flow.Shape().nBands == 2); 57 | 58 | cv::Mat matFlow(rows, cols, CV_32FC2, cv::Scalar(0, 0)); 59 | 60 | for (int i = 0; i < rows; i++) { 61 | for (int j = 0; j < cols; j++) { 62 | matFlow.at(i, j)[0] = flow.Pixel(j, i, 0); 63 | matFlow.at(i, j)[1] = flow.Pixel(j, i, 1); 64 | } 65 | } 66 | 67 | return matFlow; 68 | } 69 | 70 | void FlowIOOpenCVWrapper::write(std::string path, const cv::Mat & flow) { 71 | assert(flow.channels() == 2); 72 | assert(flow.type() == CV_32FC2); 73 | 74 | int rows = flow.rows; 75 | int cols = flow.cols; 76 | 77 | CFloatImage cFlow(cols, rows, 2); 78 | 79 | for (int i = 0; i < rows; i++) { 80 | for (int j = 0; j < cols; j++) { 81 | cFlow.Pixel(j, i, 0) = flow.at(i, j)[0]; 82 | cFlow.Pixel(j, i, 1) = flow.at(i, j)[1]; 83 | } 84 | } 85 | 86 | WriteFlowFile(cFlow, path.c_str()); 87 | } 88 | 89 | cv::Mat FlowIOOpenCVWrapper::flowToColor(const cv::Mat & flow, float max) { 90 | assert(flow.channels() == 2); 91 | // assert(flow.type() == CV_32F); 92 | 93 | int rows = flow.rows; 94 | int cols = flow.cols; 95 | 96 | CFloatImage cFlow(cols, rows, 2); 97 | 98 | for (int i = 0; i < rows; i++) { 99 | for (int j = 0; j < cols; j++) { 100 | cFlow.Pixel(j, i, 0) = flow.at(i, j)[0]; 101 | cFlow.Pixel(j, i, 1) = flow.at(i, j)[1]; 102 | } 103 | } 104 | 105 | CByteImage cImage; 106 | MotionToColor(cFlow, cImage, max); 107 | 108 | assert(cImage.Shape().height == rows); 109 | assert(cImage.Shape().width == cols); 110 | assert(cImage.Shape().nBands == 3); 111 | 112 | cv::Mat image(rows, cols, CV_8UC3, cv::Scalar(0, 0, 0)); 113 | 114 | for (int i = 0; i < rows; i++) { 115 | for (int j = 0; j < cols; j++) { 116 | image.at(i, j)[0] = cImage.Pixel(j, i, 0); 117 | image.at(i, j)[1] = cImage.Pixel(j, i, 1); 118 | image.at(i, j)[2] = cImage.Pixel(j, i, 2); 119 | } 120 | } 121 | 122 | // cv::cvtColor(image, image, CV_HSV2BGR); 123 | 124 | return image; 125 | } 126 | -------------------------------------------------------------------------------- /lib/flowIOOpenCVWrapper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * OpenCV wrapper for optical flow input/output and visualization capabilities 3 | * provided by the Sintel dataset [1] based on imageLib, originally developed 4 | * as part of StereoMatcher [2]. 5 | * 6 | * [1] D. J. Butler, J. Wulff, G. B. Stanley, M. J. Black. 7 | * A naturalistic open source movie for optical flow evaluation. 8 | * In European Conference on Computer Vision, pages 611 - 625, 2012. 9 | * [2] D. Scharstein, R. Szeliski. 10 | * A taxonomy and evaluation of dense two-frame stereo correspondence algorithms. 11 | * Technical Report MSR-TR-2001-81, Microsoft Research, 2001. 12 | * 13 | * Copyright (c) 2015, David Stutz 14 | * All rights reserved. 15 | * 16 | * Redistribution and use in source and binary forms, with or without modification, 17 | * are permitted provided that the following conditions are met: 18 | * 19 | * - Redistributions of source code must retain the above copyright notice, 20 | * this list of conditions and the following disclaimer. 21 | * - Redistributions in binary form must reproduce the above copyright notice, 22 | * this list of conditions and the following disclaimer in the documentation and/or 23 | * other materials provided with the distribution. 24 | * - Neither the name of David Stutz nor the names of its contributors may be 25 | * used to endorse or promote products derived from this software without specific 26 | * prior written permission. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 32 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 | * POSSIBILITY OF SUCH DAMAGE. 39 | */ 40 | #ifndef FLOWIOOPENCVWRAPPER_H 41 | #define FLOWIOOPENCVWRAPPER_H 42 | 43 | #include 44 | #include 45 | 46 | /** 47 | * OpenCV wrapper to read and write .flo files as well as visualize flow. 48 | */ 49 | class FlowIOOpenCVWrapper { 50 | public: 51 | /** 52 | * Read a .flo file into a cv::Mat with 2 channels of type CV_32F. 53 | * 54 | * @param path 55 | * @return 56 | */ 57 | static cv::Mat read(std::string path); 58 | /** 59 | * Write a cv::Mat file with2 channels of type CV_32F to a .flo file. 60 | * @param path 61 | * @param flow 62 | */ 63 | static void write(std::string path, const cv::Mat & flow); 64 | /** 65 | * Color the flow and return a 3-channel BGR image. 66 | * 67 | * @param flow 68 | * @return 69 | */ 70 | static cv::Mat flowToColor(const cv::Mat & flow, float max = -1); 71 | 72 | }; 73 | 74 | #endif /* FLOWIOOPENCVWRAPPER_H */ 75 | 76 | -------------------------------------------------------------------------------- /lib/imageLib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | add_library(flow_io_imagelib RefCntMem.cpp Image.cpp ImageIO.cpp ImageIOpng.cpp Convolve.cpp Convert.cpp) 4 | -------------------------------------------------------------------------------- /lib/imageLib/Convert.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/Convert.cpp -------------------------------------------------------------------------------- /lib/imageLib/Convert.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/Convert.h -------------------------------------------------------------------------------- /lib/imageLib/Convolve.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/Convolve.cpp -------------------------------------------------------------------------------- /lib/imageLib/Convolve.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/Convolve.h -------------------------------------------------------------------------------- /lib/imageLib/Copyright.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | StereoMatcher 1.0 4 | 5 | This Microsoft Research Source Code License Agreement ("MSR-SCLA") is 6 | a legal agreement between you and Microsoft Corporation 7 | (``Microsoft'' or ``we'') for the above pre-release Software. 8 | 9 | By installing, copying, compiling or otherwise using the Software found at 10 | http://research.microsoft.com/downloads/, 11 | you agree to be bound by the terms of this MSR-SCLA. If you do not agree, 12 | do not install, copy, compile or use the Software. The Software is protected 13 | by copyright and other intellectual property laws and is licensed, not sold. 14 | 15 | You may do anything you want with the Software for non-commercial research or 16 | teaching purposes, free of charge. In return, we simply ask that you agree to 17 | the following: 18 | 19 | * To leave in place all copyright notices and licensing information that you 20 | might find in the Software. 21 | 22 | * That you will not use the Software in a live operating environment where it 23 | may be relied upon to perform in the same manner as a commercially released 24 | product, or with data that has not been sufficiently backed up. 25 | 26 | * To make freely available to others the source code of any modifications or 27 | additions you make to the Software source code, and any related documentation, 28 | solely and exclusively under the same terms as this License. 29 | 30 | * That Microsoft is granted back, without limitations, the rights to reproduce, 31 | install, use, modify, distribute and transfer your source modifications or 32 | additions in source and/or object code formats. 33 | 34 | * That any feedback about the Software provided by you to us is voluntarily 35 | given, and Microsoft shall be free to use the feedback as it sees fit without 36 | obligation or restriction of any kind, even if the feedback is designated by 37 | you as confidential. 38 | 39 | * NO WARRANTIES WHATSOEVER: That the Software comes ``AS IS'', with all 40 | faults and with no warranties, conditions or representations. None. 41 | Not even the implied warranty of merchantability, warranty of fitness for 42 | a particular purpose, or any warranty against interference with your 43 | enjoyment of the Software or against infringement. The entire risk as to 44 | satisfactory quality, performance, accuracy, and effort is with you. 45 | There is no warranty that this Software will fulfill any of your particular 46 | purposes or needs. 47 | 48 | * That we have no duty of reasonable care or lack of negligence and that we 49 | are not obligated to (and will not) provide technical support or updates for 50 | the Software. 51 | 52 | * That we will not be liable for any damages, including those known as direct, 53 | indirect, special, consequential, or incidental damages related to the Software 54 | or this MSR-SCLA, nor any damages for negligence, to the maximum extent the 55 | law permits. 56 | 57 | * That if you sue or threaten to sue anyone over patents that you think may 58 | apply to the Software or if you breach this MSR-SCLA in any way, your license 59 | to the Software ends automatically. 60 | 61 | * That this MSR-SCLA shall be construed and controlled by the laws of the 62 | State of Washington, USA, without regard to conflicts of law. 63 | 64 | 65 | Copyright (c) Microsoft Corporation. All rights reserved 66 | 67 | */ 68 | -------------------------------------------------------------------------------- /lib/imageLib/Error.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/Error.h -------------------------------------------------------------------------------- /lib/imageLib/Image.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/Image.cpp -------------------------------------------------------------------------------- /lib/imageLib/Image.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////// 2 | // 3 | // NAME 4 | // Image.h -- a simple reference-counted image structure 5 | // 6 | // DESCRIPTION 7 | // The CImage class is used to create and access weakly typed 8 | // two-dimensional images. 9 | // 10 | // The templated CImageOf classes are used to create strongly typed images. 11 | // The currently supported pixel types are: 12 | // unsigned char, int, and float. 13 | // 14 | // The images can have an arbitrary width, height, and also an arbitrary 15 | // number of bands (channels) per pixel. For example, traditional RGBA 16 | // images can be represented using a 4-channel unsigned_8 image. 17 | // 18 | // Images are normally allocated on the stack (NOT on the heap, i.e., 19 | // "new Image" should not be used). They can be freely returned from 20 | // functions and put into other data structures. Assignment and copy 21 | // construction share memory (to copy pixel values from one image to 22 | // another one, use CopyPixels()). 23 | // 24 | // SEE ALSO 25 | // Image.cpp implementation 26 | // RefCntMem.h reference-counted memory object used by CImage 27 | // 28 | // Copyright � Richard Szeliski, 2001. 29 | // See Copyright.h for more details 30 | // 31 | /////////////////////////////////////////////////////////////////////////// 32 | 33 | 34 | namespace std {} 35 | using namespace std; 36 | 37 | #include 38 | #include 39 | #include 40 | #include "RefCntMem.h" 41 | 42 | #ifdef WIN32 43 | #include 44 | #else 45 | #include 46 | #define __max(a,b) (((a) > (b)) ? (a) : (b)) 47 | #define __min(a,b) (((a) < (b)) ? (a) : (b)) 48 | #endif 49 | 50 | #include 51 | #ifndef FLT_MAX 52 | #define FLT_MAX 3.402823466e+38F /* max value */ 53 | #define FLT_MIN 1.175494351e-38F /* min positive value */ 54 | #endif 55 | 56 | typedef unsigned char uchar; 57 | 58 | 59 | // Shape of an image: width x height x nbands 60 | 61 | struct CShape 62 | { 63 | int width, height; // width and height in pixels 64 | int nBands; // number of bands/channels 65 | 66 | // Constructors and helper functions 67 | CShape(void) : width(0), height(0), nBands(0) {} 68 | CShape(int w, int h, int nb) : width(w), height(h), nBands(nb) {} 69 | bool InBounds(int x, int y); // is given pixel address valid? 70 | bool InBounds(int x, int y, int band); // is given pixel address valid? 71 | bool operator==(const CShape& ref); // are two shapes the same? 72 | bool SameIgnoringNBands(const CShape& ref); // " ignoring the number of bands? 73 | bool operator!=(const CShape& ref); // are two shapes not the same? 74 | }; 75 | 76 | inline bool CShape::InBounds(int x, int y) 77 | { 78 | // Is given pixel address valid? 79 | return (0 <= x && x < width && 80 | 0 <= y && y < height); 81 | } 82 | 83 | inline bool CShape::InBounds(int x, int y, int b) 84 | { 85 | // Is given pixel address valid? 86 | return (0 <= x && x < width && 87 | 0 <= y && y < height && 88 | 0 <= b && b < nBands); 89 | } 90 | 91 | 92 | // Padding (border) mode for neighborhood operations like convolution 93 | 94 | enum EBorderMode 95 | { 96 | eBorderZero = 0, // zero padding 97 | eBorderReplicate = 1, // replicate border values 98 | eBorderReflect = 2, // reflect border pixels 99 | eBorderCyclic = 3 // wrap pixel values 100 | }; 101 | 102 | // Image attributes 103 | 104 | struct CImageAttributes 105 | { 106 | int alphaChannel; // which channel contains alpha (for compositing) 107 | int origin[2]; // x and y coordinate origin (for some operations) 108 | EBorderMode borderMode; // border behavior for neighborhood operations... 109 | // char colorSpace[4]; // RGBA, YUVA, etc.: not currently used 110 | }; 111 | 112 | 113 | // Generic (weakly typed) image 114 | 115 | class CImage : public CImageAttributes 116 | { 117 | public: 118 | CImage(void); // default constructor 119 | CImage(CShape s, const type_info& ti, int bandSize); 120 | // uses system-supplied copy constructor, assignment operator, and destructor 121 | 122 | void ReAllocate(CShape s, const type_info& ti, int bandSize, 123 | void *memory, bool deleteWhenDone, int rowSize); 124 | void ReAllocate(CShape s, const type_info& ti, int bandSize, 125 | bool evenIfSameShape = false); 126 | void DeAllocate(void); // release the memory & set to default values 127 | 128 | CShape Shape(void) { return m_shape; } 129 | const type_info& PixType(void) { return *m_pTI; } 130 | int BandSize(void) { return m_bandSize; } 131 | 132 | void* PixelAddress(int x, int y, int band); 133 | 134 | void SetSubImage(int xO, int yO, int width, int height); // sub-image sharing memory 135 | 136 | protected: 137 | void SetPixels(void *val_ptr); // Fill the image with a value 138 | 139 | private: 140 | void SetDefaults(void); // set internal state to default values 141 | 142 | CShape m_shape; // image shape (dimensions) 143 | const type_info* m_pTI; // pointer to type_info class 144 | int m_bandSize; // size of each band in bytes 145 | int m_pixSize; // stride between pixels in bytes 146 | int m_rowSize; // stride between rows in bytes 147 | char* m_memStart; // start of addressable memory 148 | CRefCntMem m_memory; // reference counted memory 149 | public: 150 | int alphaChannel; // which channel contains alpha (for compositing) 151 | }; 152 | 153 | inline void* CImage::PixelAddress(int x, int y, int band) 154 | { 155 | // This could also go into the implementation file (CImage.cpp): 156 | return (void *) &m_memStart[y * m_rowSize + x * m_pixSize + band * m_bandSize]; 157 | } 158 | 159 | 160 | // Strongly typed image 161 | 162 | template 163 | class CImageOf : public CImage 164 | { 165 | public: 166 | CImageOf(void); 167 | CImageOf(CShape s); 168 | CImageOf(int width, int height, int nBands); 169 | // uses system-supplied copy constructor, assignment operator, and destructor 170 | 171 | void ReAllocate(CShape s, bool evenIfSameShape = false); 172 | void ReAllocate(CShape s, T *memory, bool deleteWhenDone, int rowSize); 173 | 174 | T& Pixel(int x, int y, int band); 175 | 176 | CImageOf SubImage(int x, int y, int width, int height); // sub-image sharing memory 177 | 178 | void FillPixels(T val); // fill the image with a constant value 179 | void ClearPixels(void); // fill the image with a 0 value 180 | 181 | T MinVal(void); // minimum allowable value (for clipping) 182 | T MaxVal(void); // maximum allowable value (for clipping) 183 | }; 184 | 185 | // These are defined inline so user-defined image types can be supported: 186 | 187 | template 188 | inline CImageOf::CImageOf(void) : 189 | CImage(CShape(), typeid(T), sizeof(T)) {} 190 | 191 | template 192 | inline CImageOf::CImageOf(CShape s) : 193 | CImage(s, typeid(T), sizeof(T)) {} 194 | 195 | template 196 | inline CImageOf::CImageOf(int width, int height, int nBands) : 197 | CImage(CShape(width, height, nBands), typeid(T), sizeof(T)) {} 198 | 199 | template 200 | inline void CImageOf::ReAllocate(CShape s, bool evenIfSameShape) 201 | { 202 | CImage::ReAllocate(s, typeid(T), sizeof(T), evenIfSameShape); 203 | } 204 | 205 | template 206 | inline void CImageOf::ReAllocate(CShape s, T *memory, 207 | bool deleteWhenDone, int rowSize) 208 | { 209 | CImage::ReAllocate(s, typeid(T), sizeof(T), memory, deleteWhenDone, rowSize); 210 | } 211 | 212 | template 213 | inline T& CImageOf::Pixel(int x, int y, int band) 214 | { 215 | return *(T *) PixelAddress(x, y, band); 216 | } 217 | 218 | template 219 | inline CImageOf CImageOf::SubImage(int x, int y, int width, int height) 220 | { 221 | // sub-image sharing memory 222 | CImageOf retval = *this; 223 | retval.SetSubImage(x, y, width, height); 224 | return retval; 225 | } 226 | 227 | template 228 | inline void CImageOf::FillPixels(T val) 229 | { 230 | // fill the image with a constant value 231 | SetPixels(&val); 232 | } 233 | 234 | template 235 | inline void CImageOf::ClearPixels(void) 236 | { 237 | // fill the image with a 0 value 238 | T val = 0; 239 | FillPixels(val); 240 | } 241 | 242 | // Commonly used types (supported in type conversion routines): 243 | 244 | typedef CImageOf CByteImage; 245 | typedef CImageOf CIntImage; 246 | typedef CImageOf CFloatImage; 247 | 248 | // Color pixel support 249 | 250 | template 251 | struct RGBA 252 | { 253 | PixType B, G, R, A; // A channel is highest one 254 | }; 255 | -------------------------------------------------------------------------------- /lib/imageLib/ImageIO.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/ImageIO.cpp -------------------------------------------------------------------------------- /lib/imageLib/ImageIO.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/ImageIO.h -------------------------------------------------------------------------------- /lib/imageLib/ImageIOpng.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/ImageIOpng.cpp -------------------------------------------------------------------------------- /lib/imageLib/License.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/License.txt -------------------------------------------------------------------------------- /lib/imageLib/README-StereoMatcher.md: -------------------------------------------------------------------------------- 1 | # StereoMatcher 2 | 3 | This directory contains the source code to the two-frame dense stereo 4 | matching code developed by Daniel Scharstein and Richard Szeliski. 5 | Please see the associated `Licence.txt` and Copyright.h files for terms and 6 | conditions of use. 7 | 8 | The algorithms implemented in this code are described in our Technical 9 | Report: 10 | 11 | D. Scharstein and R. Szeliski. A taxonomy and evaluation of dense 12 | two-frame stereo correspondence algorithms. Technical Report 13 | MSR-TR-2001-81, Microsoft Research, November 2001. 14 | 15 | which can be found at 16 | [http://www.research.microsoft.com/scripts/pubs/view.asp?TR_ID=MSR-TR-2001-81](http://www.research.microsoft.com/scripts/pubs/view.asp?TR_ID=MSR-TR-2001-81) 17 | and which will also appear in a special issue of IJCV on stereo matching. 18 | 19 | To compile the code, please use the Workspace or makefile. 20 | If you wish to run the graph cut algorithm, you will need to follow the 21 | instructions given in `maxflow/README-maxflow.txt`. 22 | 23 | The program is driven by command line arguments and scripts. To run a 24 | particular scriptfile, just use 25 | StereoMatch script `scriptfile.txt` 26 | Some sample scripts that you can use to evaluate the output of your stereo 27 | algorithm or to run one of the matching algorithms are given on the 28 | Middlebury Stereo Web site, 29 | [http://www.middlebury.edu/stereo/code.html](http://www.middlebury.edu/stereo/code.html) 30 | You can also find some sample data sets at the same location. 31 | 32 | There is no documentation provided beyond the comments embedded in the 33 | source code. The main parameters controlling the algorithm are in 34 | StereoParameters.h, and a subset of these is documented in more detail in 35 | the Techical Report cited above. If you don't understand what a parameter 36 | is doing, just leave it at its default value (it may control experimental 37 | code we are still working on). 38 | 39 | You can obtain the latest version of this software by following the 40 | download link from the Middlebury Stereo Web page URL given above. 41 | 42 | Daniel Scharstein and Richard Szeliski, December 6, 2001. -------------------------------------------------------------------------------- /lib/imageLib/README.md: -------------------------------------------------------------------------------- 1 | # imageLib 2 | 3 | imageLib is a small C++ library for 2D multi-band images. See `Image.h` 4 | for more detail. Reading and writing of images is supported in png 5 | and `pgm/ppm` formats, as well as a subset of Targa. See `ImageIO.h` for 6 | more detail. 7 | 8 | This code is derived from a subset of the StereoMatcher code by Rick 9 | Szeliski and Daniel Scharstein, which is available at 10 | [http://research.microsoft.com/downloads/](http://research.microsoft.com/downloads/). 11 | 12 | This code is distributed under the same Source Code License Agreement 13 | as the original version. Please see the file `Copyright.h`. -------------------------------------------------------------------------------- /lib/imageLib/RefCntMem.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/RefCntMem.cpp -------------------------------------------------------------------------------- /lib/imageLib/RefCntMem.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/lib/imageLib/RefCntMem.h -------------------------------------------------------------------------------- /lib/imageLib/imageLib.h: -------------------------------------------------------------------------------- 1 | // imageLib.h 2 | 3 | // common includes 4 | 5 | #include "Error.h" 6 | #include "Image.h" 7 | #include "ImageIO.h" 8 | #include "Convert.h" 9 | -------------------------------------------------------------------------------- /lib/motiontocolor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "imageLib.h" 3 | #include "flowIO.h" 4 | #include "colorcode.h" 5 | #include "motiontocolor.h" 6 | 7 | void MotionToColor(CFloatImage motim, CByteImage &colim, float maxmotion) 8 | { 9 | CShape sh = motim.Shape(); 10 | int width = sh.width, height = sh.height; 11 | colim.ReAllocate(CShape(width, height, 3)); 12 | int x, y; 13 | // determine motion range: 14 | float maxx = -999, maxy = -999; 15 | float minx = 999, miny = 999; 16 | float maxrad = -1; 17 | for (y = 0; y < height; y++) { 18 | for (x = 0; x < width; x++) { 19 | float fx = motim.Pixel(x, y, 0); 20 | float fy = motim.Pixel(x, y, 1); 21 | if (unknown_flow(fx, fy)) 22 | continue; 23 | maxx = __max(maxx, fx); 24 | maxy = __max(maxy, fy); 25 | minx = __min(minx, fx); 26 | miny = __min(miny, fy); 27 | float rad = std::sqrt(fx * fx + fy * fy); 28 | maxrad = __max(maxrad, rad); 29 | } 30 | } 31 | // printf("max motion: %.4f motion range: u = %.3f .. %.3f; v = %.3f .. %.3f\n", 32 | // maxrad, minx, maxx, miny, maxy); 33 | 34 | 35 | if (maxmotion > 0) // i.e., specified on commandline 36 | maxrad = maxmotion; 37 | 38 | if (maxrad == 0) // if flow == 0 everywhere 39 | maxrad = 1; 40 | 41 | // if (verbose) 42 | // fprintf(stderr, "normalizing by %g\n", maxrad); 43 | 44 | for (y = 0; y < height; y++) { 45 | for (x = 0; x < width; x++) { 46 | float fx = motim.Pixel(x, y, 0); 47 | float fy = motim.Pixel(x, y, 1); 48 | uchar *pix = &colim.Pixel(x, y, 0); 49 | if (unknown_flow(fx, fy)) { 50 | pix[0] = pix[1] = pix[2] = 0; 51 | } else { 52 | computeColor(fx/maxrad, fy/maxrad, pix); 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /lib/motiontocolor.h: -------------------------------------------------------------------------------- 1 | void MotionToColor(CFloatImage motim, CByteImage &colim, float maxmotion); -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/flow-io-opencv/e9877258417f046f945c243ec6a6f0131ef2130d/screenshot.png --------------------------------------------------------------------------------