├── .gitignore ├── DemoExtras ├── ica_script.sh └── ica_script2.sh ├── License.txt ├── Makefile ├── README.txt ├── bicubic_interpolation.cpp ├── bicubic_interpolation.h ├── equalization.c ├── experiments ├── color_evaluation.sh ├── comparison_javier_optimized.sh ├── computation_and_latex.sh ├── dataset │ ├── img31.png │ ├── img32.png │ └── script.sh ├── evaluation_modification.sh ├── evaluation_modification_all_images.sh ├── evaluation_modification_latex.sh ├── other-data │ ├── Beanbags │ │ ├── frame10.png │ │ └── frame11.png │ ├── Dimetrodon │ │ ├── frame10.png │ │ └── frame11.png │ ├── DogDance │ │ ├── frame10.png │ │ └── frame11.png │ ├── Grove2 │ │ ├── frame10.png │ │ └── frame11.png │ ├── Grove3 │ │ ├── frame10.png │ │ └── frame11.png │ ├── Hydrangea │ │ ├── frame10.png │ │ └── frame11.png │ ├── MiniCooper │ │ ├── frame10.png │ │ └── frame11.png │ ├── RubberWhale │ │ ├── frame10.png │ │ └── frame11.png │ ├── Urban2 │ │ ├── frame10.png │ │ └── frame11.png │ ├── Urban3 │ │ ├── frame10.png │ │ └── frame11.png │ ├── Venus │ │ ├── frame10.png │ │ └── frame11.png │ └── Walking │ │ ├── frame10.png │ │ └── frame11.png ├── recalage_ic.sh ├── rmse_method.sh └── synthetic_color │ ├── plot_figure.m │ ├── script.sh │ └── script2.sh ├── file.cpp ├── file.h ├── iio.c ├── iio.h ├── input ├── affinity2.png ├── clena_nb.png ├── homography.mat ├── homography1.png ├── homography2.png ├── homography22.png ├── identity2.png ├── lena.png ├── lena_nb.png ├── rotation_translation2.png ├── script.sh ├── traffic.png ├── translation2.png ├── zoom2.png ├── zoom_rotation2.png └── zoom_rotation_translation2.png ├── inverse_compositional_algorithm.cpp ├── inverse_compositional_algorithm.h ├── mInverseCompositional_1.00 ├── License.txt ├── Makefile ├── README.txt ├── bicubic_interpolation.cpp ├── bicubic_interpolation.h ├── data │ ├── homography.mat │ ├── homography1.png │ └── homography2.png ├── equalization.c ├── file.cpp ├── file.h ├── iio.c ├── iio.h ├── inverse_compositional_algorithm.cpp ├── inverse_compositional_algorithm.h ├── main.cpp ├── mask.cpp ├── mask.h ├── matrix.cpp ├── matrix.h ├── mt19937ar.c ├── mt19937ar.h ├── noise.cpp ├── output.cpp ├── transform.mat ├── transformation.cpp ├── transformation.h ├── zoom.cpp └── zoom.h ├── main.cpp ├── mask.cpp ├── mask.h ├── matrix.cpp ├── matrix.h ├── mt19937ar.c ├── mt19937ar.h ├── noise.cpp ├── output.cpp ├── smapa.h ├── transformation.cpp ├── transformation.h ├── zoom.cpp └── zoom.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | 3 | add_noise 4 | generate_output 5 | inverse_compositional_algorithm 6 | experiments/*.txt 7 | experiments/evaluation_modification_old/ 8 | -------------------------------------------------------------------------------- /DemoExtras/ica_script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -lt "13" ]; then 4 | echo "usage:\n\t$0 nscales zoom eps transform robust lambda dbp edgepadding color gradient first_scale std eq" 5 | exit 1 6 | fi 7 | 8 | nscales=$1 9 | zoom=$2 10 | eps=$3 11 | transform=$4 12 | robust=$5 13 | lambda=$6 14 | dbp=$7 15 | edgepadding=$8 16 | color=$9 17 | gradient=${10} 18 | first_scale=${11} 19 | std=${12} 20 | eq=${13} 21 | 22 | if [ "$color" = "True" ]; then 23 | GRAYMETHOD=1 24 | else 25 | GRAYMETHOD=0 26 | fi 27 | 28 | if [ "$dbp" = "True" ]; then 29 | NANIFOUTSIDE=1 30 | else 31 | NANIFOUTSIDE=0 32 | edgepadding=0 33 | fi 34 | 35 | ref=input_0.png 36 | ref_noisy=input_noisy_0.png 37 | warped=input_1.png 38 | warped_noisy=input_noisy_1.png 39 | file=transformation.txt 40 | filewithout=transformation_without.txt 41 | if [ -f input_2.txt ]; then 42 | file2=input_2.txt 43 | else 44 | file2="" 45 | fi 46 | 47 | if [ "$eq" = "none" ]; then 48 | cp $warped $warped_noisy 49 | else 50 | echo "Contrasts of the images are equalized" 51 | equalization $ref $warped $warped_noisy $eq 52 | fi 53 | 54 | echo "Standard deviation of the noise added: $std" 55 | add_noise $ref $ref_noisy $std 56 | add_noise $warped_noisy $warped_noisy $std 57 | 58 | echo "" 59 | inverse_compositional_algorithm $ref_noisy $warped_noisy -f $filewithout -z $zoom -n $nscales -r $robust -e $eps -t $transform -s 0 -c 0 -d 0 -p 0 -g 0 > /dev/null 60 | inverse_compositional_algorithm $ref_noisy $warped_noisy -f $file -z $zoom -n $nscales -r $robust -e $eps -t $transform -s $first_scale -c $GRAYMETHOD -d $edgepadding -p $NANIFOUTSIDE -g $gradient -v 61 | 62 | echo "" 63 | echo "Without modification:" 64 | generate_output $ref_noisy $warped_noisy $filewithout $file2 65 | mv output_estimated.png output_estimated2.png 66 | if [ -f epe.png ]; then 67 | mv epe.png epe2.png 68 | echo "vis=1" > algo_info.txt 69 | fi 70 | mv diff_image.png diff_image2.png 71 | 72 | echo "" 73 | echo "With modifications:" 74 | generate_output $ref_noisy $warped_noisy $file $file2 75 | -------------------------------------------------------------------------------- /DemoExtras/ica_script2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -lt "12" ]; then 4 | echo "usage:\n\t$0 nscales zoom eps transform robust lambda dbp edgepadding color gradient first_scale std" 5 | exit 1 6 | fi 7 | 8 | nscales=$1 9 | zoom=$2 10 | eps=$3 11 | transform=$4 12 | robust=$5 13 | lambda=$6 14 | dbp=$7 15 | edgepadding=$8 16 | color=$9 17 | gradient=${10} 18 | first_scale=${11} 19 | std=${12} 20 | 21 | if [ "$color" = "True" ]; then 22 | GRAYMETHOD=1 23 | else 24 | GRAYMETHOD=0 25 | fi 26 | 27 | if [ "$dbp" = "True" ]; then 28 | NANIFOUTSIDE=1 29 | else 30 | NANIFOUTSIDE=0 31 | edgepadding=0 32 | fi 33 | 34 | ref=input_0.png 35 | ref_noisy=input_noisy_0.png 36 | warped=input_1.png 37 | warped_noisy=input_noisy_1.png 38 | file=transformation.txt 39 | filewithout=transformation_without.txt 40 | if [ -f input_2.txt ]; then 41 | file2=input_2.txt 42 | else 43 | file2="" 44 | fi 45 | 46 | echo "Standard deviation of the noise added: $std" 47 | add_noise $ref $ref_noisy $std 48 | add_noise $warped $warped_noisy $std 49 | 50 | echo "" 51 | GRAYMETHOD=0 EDGEPADDING=0 NANIFOUTSIDE=0 ROBUST_GRADIENT=0 inverse_compositional_algorithm $ref_noisy $warped_noisy -f $filewithout -z $zoom -n $nscales -r $robust -e $eps -t $transform -s 0 > /dev/null 52 | GRAYMETHOD=$GRAYMETHOD EDGEPADDING=$edgepadding NANIFOUTSIDE=$NANIFOUTSIDE ROBUST_GRADIENT=$gradient inverse_compositional_algorithm $ref_noisy $warped_noisy -f $file -z $zoom -n $nscales -r $robust -e $eps -t $transform -s $first_scale -v 53 | 54 | echo "" 55 | echo "Without modification:" 56 | NANIFOUTSIDE=1 EDGEPADDING=0 generate_output $ref_noisy $warped_noisy $filewithout $file2 57 | mv output_estimated.png output_estimated2.png 58 | if [ -f epe.png ]; then 59 | mv epe.png epe2.png 60 | fi 61 | mv diff_image.png diff_image2.png 62 | 63 | echo "" 64 | echo "With modifications:" 65 | NANIFOUTSIDE=1 EDGEPADDING=0 generate_output $ref_noisy $warped_noisy $file $file2 66 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Thibaud Briand 2 | Copyright (c) 2015, Javier Sánchez Pérez 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -Wextra -O3 2 | LDFLAGS=-lm -lpng -ljpeg -ltiff -lstdc++ 3 | 4 | SRC1 := bicubic_interpolation.cpp inverse_compositional_algorithm.cpp mask.cpp transformation.cpp file.cpp matrix.cpp zoom.cpp 5 | SRC2 := iio.c mt19937ar.c 6 | 7 | INCLUDE = -I. 8 | 9 | #Replace suffix .cpp and .c by .o 10 | OBJ := $(addsuffix .o,$(basename $(SRC1))) $(addsuffix .o,$(basename $(SRC2))) 11 | 12 | #Binary file 13 | BIN = inverse_compositional_algorithm add_noise generate_output equalization 14 | 15 | #All is the target (you would run make all from the command line). 'all' is dependent 16 | all: $(BIN) 17 | 18 | #Generate executables 19 | inverse_compositional_algorithm: main.o $(OBJ) 20 | $(CXX) -std=c++11 $^ -o $@ $(LDFLAGS) 21 | 22 | add_noise: mt19937ar.o file.o iio.o noise.o 23 | $(CXX) -std=c++11 $^ -o $@ $(LDFLAGS) 24 | 25 | generate_output: output.o $(OBJ) 26 | $(CXX) -std=c++11 $^ -o $@ $(LDFLAGS) 27 | 28 | equalization: equalization.o iio.o 29 | $(CC) -std=c99 $^ -o $@ $(LDFLAGS) 30 | 31 | #each object file is dependent on its source file, and whenever make needs to create 32 | #an object file, to follow this rule: 33 | %.o: %.c 34 | $(CC) -std=c99 -c $< -o $@ $(INCLUDE) $(CFLAGS) -Wno-unused -pedantic -DNDEBUG -D_GNU_SOURCE 35 | 36 | %.o: %.cpp 37 | $(CXX) -std=c++11 -c $< -o $@ $(INCLUDE) $(CFLAGS) 38 | 39 | clean: 40 | rm -f $(OBJ) $(BIN) main.o output.o noise.o equalization.o 41 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | The Inverse Compositional Algorithm for Parametric Motion Estimation 2 | -------------------------------------------------------------------- 3 | 4 | ******* 5 | SUMMARY 6 | ******* 7 | 8 | This program implements the modified inverse compositional algorithm for 9 | parametric motion estimation. It computes a planar transformation between two 10 | images, including translations, similarities, affinities and homographies. It 11 | computes large displacements through a pyramidal scheme and uses robust 12 | functionals to deal with noise and occlusions. 13 | 14 | Reference articles: 15 | 16 | [1] S. Baker and I. Matthews, Lucas-kanade 20 years on: A unifying framework, 17 | International journal of computer vision, 56 (2004), pp. 221-255. 18 | 19 | [2] S. Baker, R. Gross, I. Matthews, and T. Ishikawa, Lucas-kanade 20 years 20 | on: A unifying framework: Part 2, Tech. Report CMU-RI-TR-03-01, Robotics 21 | Institute, Pittsburgh, PA, February 2003. 22 | 23 | This program is part of an IPOL publication: 24 | http://www.ipol.im/ 25 | 26 | 27 | ****** 28 | AUTHOR 29 | ****** 30 | 31 | Thibaud Briand 32 | Laboratoire d'information Gaspard Monge (LIGM) 33 | Ecole Nationale des Ponts et Chaussées (ENPC) 34 | 35 | Javier Sánchez Pérez 36 | Centro de Tecnologías de la Imagen (CTIM) 37 | Universidad de Las Palmas de Gran Canaria 38 | 39 | 40 | ******* 41 | VERSION 42 | ******* 43 | 44 | Version 1, released on ??? 45 | 46 | 47 | ******* 48 | LICENSE 49 | ******* 50 | 51 | This program is free software: you can use, modify and/or redistribute it 52 | under the terms of the simplified BSD License. You should have received a 53 | copy of this license along this program. If not, see 54 | . 55 | 56 | Copyright (C) 2018, Thibaud Briand 57 | Copyright (C) 2015, Javier Sánchez Pérez 58 | All rights reserved. 59 | 60 | 61 | *********** 62 | COMPILATION 63 | *********** 64 | 65 | Required environment: Any unix-like system with a standard compilation 66 | environment (make and C and C++ compilers) 67 | 68 | Required libraries: libpng, lipjpeg, libtiff 69 | 70 | Compilation instructions: run "make" to produce an executable 71 | "inverse_compositional_algorithm" 72 | 73 | 74 | ***** 75 | USAGE 76 | ***** 77 | 78 | The program reads two input images, take some parameters and produce a 79 | parametric model. The meaning of the parameters is thoroughly discussed on the 80 | accompanying IPOL article. Usage instructions: 81 | 82 | : inverse_compositional_algorithm image1 image2 [OPTIONS] 83 | 84 | OPTIONS: 85 | -------- 86 | -f name Name of the output filename that will contain the 87 | computed transformation 88 | Default value transform.mat 89 | -o N Output transformation format: 90 | 0-Parametrization 91 | 1-3x3 Projective matrix 92 | Default value 0 93 | -n N Number of scales for the coarse-to-fine scheme 94 | Default value 0 95 | -z F Zoom factor used in the coarse-to-fine scheme 96 | Values must be in the range (0,1) 97 | Default value 0.50 98 | -e F Threshold for the convergence criterion 99 | Default value 0.0010 100 | -t N Transformation type to be computed: 101 | 2-translation; 3-Euclidean transform; 4-similarity 102 | 6-affinity; 8-homography 103 | Default value 8 104 | -r N Use robust error functions: 105 | 0-Non robust (L2 norm); 1-truncated quadratic 106 | 2-Geman & McLure; 3-Lorentzian 4-Charbonnier 107 | Default value 3 108 | -l F Value of the parameter for the robust error function 109 | A value <=0 if it is automatically computed 110 | Default value 0 111 | -s N First scale used in the pyramid 112 | Default value 0 113 | -c N Use grayscale conversion (1) or not (0) 114 | Default value 1 115 | -d N Distance to the boundary 116 | Default value 5 117 | -p N Parameter to discards boudary pixels (1) or not (0) 118 | Default value 1 119 | -g N Use gradient type: 120 | 0-Central differences; 1-Hypomode 121 | 2-Farid 3x3; 3-Farid 5x5; 4-Sigma 3; 5-Sigma 6 122 | Default value 3 123 | -v Switch on verbose mode. 124 | 125 | Execution examples: 126 | 127 | 1.Default parameters: 128 | 129 | >inverse_compositional_algorithm data/homography1.png data/homography2.png 130 | 131 | 2.Computing an affinity with the truncated quadratic and verbose mode: 132 | 133 | >inverse_compositional_algorithm data/homography1.png data/homography2.png 134 | -t 6 -r 1 -v 135 | 136 | If a parameter is given an invalid value it will take a default value. 137 | 138 | 139 | ************* 140 | LIST OF FILES 141 | ************* 142 | bicubic_interpolation.cpp: Computes the bicubic interpolation of an image 143 | file.cpp: Functions for input/output 144 | iio.c: Functions to read and write images 145 | inverse_compositional_algorithm.cpp: Implementation of the method 146 | main.cpp: Main algorithm to read the command line parameters 147 | mask.cpp: Function to compute the gradient of an image and apply a Gaussian 148 | matrix.cpp: Multiplication of matrices and vectors and calculating the inverse 149 | transformation.cpp: Compute the Jacobian and the composition of transformations 150 | zoom.cpp: Compute the zoom-out of an image and the zoom-in of the parameters 151 | 152 | Complementary programs (used for the online demo only): 153 | output.cpp: Program to compute some images and error metrics from the results 154 | noise.cpp: Program to add Gaussian noise to the input images 155 | mt19937ar.c: Program to generate random numbers, used in noise.cpp 156 | -------------------------------------------------------------------------------- /bicubic_interpolation.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #include "bicubic_interpolation.h" 12 | #include "transformation.h" 13 | #include 14 | #include 15 | #include 16 | 17 | /** 18 | * 19 | * Neumann boundary condition test 20 | * 21 | **/ 22 | static int 23 | neumann_bc( 24 | int x, //index 25 | int nx //size 26 | ) 27 | { 28 | if (x<0) 29 | x = 0; 30 | else if (x >= nx) 31 | x = nx - 1; 32 | return x; 33 | } 34 | 35 | /** 36 | * 37 | * Bicubic interpolation in one dimension 38 | * 39 | **/ 40 | static double 41 | cubic_interpolation( 42 | double v[4], //interpolation points 43 | double x //point to be interpolated 44 | ) 45 | { 46 | return v[1] + 0.5 * x * (v[2] - v[0] 47 | + x * (2.0 * v[0] - 5.0 * v[1] + 4.0 * v[2] - v[3] 48 | + x * (3.0 * (v[1] - v[2]) + v[3] - v[0]))); 49 | } 50 | 51 | /** 52 | * 53 | * Bicubic interpolation in two dimension 54 | * 55 | **/ 56 | static double 57 | bicubic_interpolation( 58 | double p[4][4], //array containing the interpolation points 59 | double x, //x position to be interpolated 60 | double y //y position to be interpolated 61 | ) 62 | { 63 | double v[4]; 64 | v[0] = cubic_interpolation (p[0], y); 65 | v[1] = cubic_interpolation (p[1], y); 66 | v[2] = cubic_interpolation (p[2], y); 67 | v[3] = cubic_interpolation (p[3], y); 68 | return cubic_interpolation (v, x); 69 | } 70 | 71 | /** 72 | * 73 | * Compute the bicubic interpolation of a point in an image. 74 | * Detects if the point goes outside the image domain 75 | * 76 | **/ 77 | double 78 | bicubic_interpolation( 79 | double *input, //image to be interpolated 80 | double uu, //x component of the vector field 81 | double vv, //y component of the vector field 82 | int nx, //width of the image 83 | int ny, //height of the image 84 | int nz, //number of channels of the image 85 | int k //actual channel 86 | ) 87 | { 88 | int sx = (uu < 0) ? -1 : 1; 89 | int sy = (vv < 0) ? -1 : 1; 90 | 91 | int x, y, mx, my, dx, dy, ddx, ddy; 92 | 93 | x = neumann_bc ((int) uu, nx); 94 | y = neumann_bc ((int) vv, ny); 95 | mx = neumann_bc ((int) uu - sx, nx); 96 | my = neumann_bc ((int) vv - sx, ny); 97 | dx = neumann_bc ((int) uu + sx, nx); 98 | dy = neumann_bc ((int) vv + sy, ny); 99 | ddx = neumann_bc ((int) uu + 2 * sx, nx); 100 | ddy = neumann_bc ((int) vv + 2 * sy, ny); 101 | 102 | //obtain the interpolation points of the image 103 | double p11 = input[(mx + nx * my) * nz + k]; 104 | double p12 = input[(x + nx * my) * nz + k]; 105 | double p13 = input[(dx + nx * my) * nz + k]; 106 | double p14 = input[(ddx + nx * my) * nz + k]; 107 | 108 | double p21 = input[(mx + nx * y) * nz + k]; 109 | double p22 = input[(x + nx * y) * nz + k]; 110 | double p23 = input[(dx + nx * y) * nz + k]; 111 | double p24 = input[(ddx + nx * y) * nz + k]; 112 | 113 | double p31 = input[(mx + nx * dy) * nz + k]; 114 | double p32 = input[(x + nx * dy) * nz + k]; 115 | double p33 = input[(dx + nx * dy) * nz + k]; 116 | double p34 = input[(ddx + nx * dy) * nz + k]; 117 | 118 | double p41 = input[(mx + nx * ddy) * nz + k]; 119 | double p42 = input[(x + nx * ddy) * nz + k]; 120 | double p43 = input[(dx + nx * ddy) * nz + k]; 121 | double p44 = input[(ddx + nx * ddy) * nz + k]; 122 | 123 | //create array 124 | double pol[4][4] = { 125 | {p11, p21, p31, p41}, {p12, p22, p32, p42}, 126 | {p13, p23, p33, p43}, {p14, p24, p34, p44} 127 | }; 128 | 129 | //return interpolation 130 | return bicubic_interpolation (pol, (double) uu - x, (double) vv - y); 131 | } 132 | 133 | /** 134 | * 135 | * Compute the bicubic interpolation of an image from a parametric transform 136 | * 137 | **/ 138 | void bicubic_interpolation( 139 | double *input, //image to be warped 140 | double *output, //warped output image with bicubic interpolation 141 | double *params, //parameters of the transformation 142 | int nparams, //number of parameters of the transform 143 | int nx, //width of the image 144 | int ny, //height of the image 145 | int nz, //number of channels of the image 146 | int delta, //distance to the boundary 147 | int nanifoutside //parameter for discarding boudary pixels 148 | ) 149 | { 150 | double out_value = ( nanifoutside ) ? NAN : 0; 151 | 152 | for (int i=0; i nx-1-delta 162 | || y < delta || y > ny-1-delta ) 163 | out = true; 164 | 165 | if ( out ) { 166 | for(int k=0; k. 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #ifndef BICUBIC_INTERPOLATION_H 12 | #define BICUBIC_INTERPOLATION_H 13 | 14 | double 15 | bicubic_interpolation( 16 | double *input, //image to be interpolated 17 | double uu, //x component of the vector field 18 | double vv, //y component of the vector field 19 | int nx, //width of the image 20 | int ny, //height of the image 21 | int nz, //number of channels of the image 22 | int k //actual channel 23 | ); 24 | 25 | /** 26 | * 27 | * Compute the bicubic interpolation of an image from a parametric trasform 28 | * 29 | **/ 30 | void bicubic_interpolation( 31 | double *input, //image to be warped 32 | double *output, //warped output image with bicubic interpolation 33 | double *params, //x component of the vector field 34 | int nparams, //number of parameters of the transform 35 | int nx, //width of the image 36 | int ny, //height of the image 37 | int nz, //number of channels of the image 38 | int delta, //distance to the boundary 39 | int nanifoutside //parameter for discarding boudary pixels 40 | ); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /equalization.c: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // All rights reserved. 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "iio.h" 14 | 15 | // function for comparing two values 16 | static int f_compare (const void * a, const void * b) 17 | { 18 | if(*(const float*)a < *(const float*)b) 19 | return -1; 20 | return *(const float*)a > *(const float*)b; 21 | } 22 | 23 | // histogram equalization of two images (it is not Midway !) 24 | static void equalization_histo(float *ref, float *modified, float *out, int w, 25 | int h, int pd) 26 | { 27 | /* mix values and indexes to keep track of pixels' location */ 28 | float *sort_values_ref = malloc(2*w*h*sizeof*sort_values_ref); 29 | float *sort_values_modified = malloc(2*w*h*sizeof*sort_values_modified); 30 | 31 | for (int l=0; l 1 ? v[1] : "-"; 194 | char *filename_modified = c > 2 ? v[2] : "-"; 195 | char *filename_out = c > 3 ? v[3] : "-"; 196 | char *equalization_type = c > 4 ? v[4] : "-"; 197 | 198 | // read images 199 | int w, h, pd; 200 | float *ref = iio_read_image_float_split(filename_ref, &w, &h, &pd); 201 | int w2, h2 , pd2; 202 | float *modified = iio_read_image_float_split(filename_modified, &w2, &h2, &pd2); 203 | 204 | // sanity check 205 | if ( pd != pd2 ) { 206 | fprintf(stderr,"Images should have the same number of channel\n"); 207 | return EXIT_FAILURE; 208 | } 209 | 210 | // memory allocation 211 | float *out = malloc(w2*h2*pd2*sizeof*out); 212 | 213 | // Contrast equalization 214 | if ( 0 == strcmp(equalization_type, "histo") ) { 215 | if( w!=w2 || h!=h2 || pd!=pd2 ) { 216 | fprintf(stderr,"Size of images should be the same\n"); 217 | return EXIT_FAILURE; 218 | } 219 | equalization_histo(ref, modified, out, w, h, pd); 220 | } 221 | else if ( 0 == strcmp(equalization_type, "affine") ) 222 | equalization_affine(ref, modified, out, w, h, w2, h2, pd); 223 | else if ( 0 == strcmp(equalization_type, "meanp") ) 224 | equalization_meanp(ref, modified, out, w, h, w2, h2, pd); 225 | else if ( 0 == strcmp(equalization_type, "meanx") ) 226 | equalization_meanx(ref, modified, out, w, h, w2, h2, pd); 227 | else { 228 | fprintf(stderr,"Unknown equalization type\n"); 229 | return EXIT_FAILURE; 230 | } 231 | 232 | // write output 233 | iio_write_image_float_split(filename_out, out, w2, h2, pd2); 234 | 235 | // free memory 236 | free(ref); 237 | free(modified); 238 | free(out); 239 | 240 | return EXIT_SUCCESS; 241 | } 242 | -------------------------------------------------------------------------------- /experiments/color_evaluation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # fixed parameters 4 | # NUMBER=1001 5 | # L=20 6 | # ref=ref.png 7 | # TIMEFORMAT="%U" 8 | # FIRST_SCALE=0 9 | # ROBUST_GRADIENT=0 10 | # EDGEPADDING=5 11 | # NANIFOUTSIDE=1 12 | # SAVE=1 13 | # SCALES=5 14 | # PRECISION=0.001 15 | # NTHREADS=1 16 | # 17 | # prog=../../../recalage_ic.sh 18 | # 19 | # # for the interpolation 20 | # interp=bicubic 21 | # boundary=hsym 22 | # base_out=burst 23 | # transform=8 #homography 24 | # 25 | # # comparison fields 26 | # centered=0 27 | # opt=1 # to determine if comparison has h1-h2 (1) or h2^-1 o h1 - id (0) 28 | # 29 | # # image parameters 30 | # INPAT=../${base_out}_%i.tiff 31 | # INPAT_NOISY=noisy_%i.tiff 32 | # TRUE_REGPAT=../${base_out}_%i.hom 33 | # REF=`printf $INPAT_NOISY 1` 34 | 35 | # create output directory 36 | dir=color_evaluation 37 | # mkdir $dir 38 | cd $dir 39 | 40 | # loop over the images 41 | # for image in "Beanbags" "DogDance" "Grove3" "MiniCooper" "Urban2" "Venus" "Dimetrodon" "Grove2" "Hydrangea" "RubberWhale" "Urban3" "Walking"; do 42 | # mkdir $image 43 | # cd $image 44 | # cp ../../other-data/$image/frame10.png $ref 45 | # 46 | # # size of the image 47 | # w=`imprintf %w $ref` 48 | # h=`imprintf %h $ref` 49 | # 50 | # # create burst 51 | # echo "Creating burst for the image $image" 52 | # create_burst $ref $base_out $NUMBER $interp $boundary $L $transform 53 | # 54 | # # invert the homography 55 | # for i in `seq 2 $NUMBER`; do 56 | # REGi=${base_out}_$i.hom 57 | # invert_homography_ica "`cat $REGi`" $REGi 58 | # done 59 | # 60 | # # loop over the noise level 61 | # for noise in 0 3 5 10 20 30 50; do 62 | # echo "Noise level $noise" 63 | # dir=noise$noise 64 | # mkdir $dir 65 | # cd $dir 66 | # for i in `seq 1 $NUMBER`; do 67 | # INi=`printf $INPAT $i` 68 | # OUTi=`printf $INPAT_NOISY $i` 69 | # add_noise $noise $INi $OUTi 70 | # done 71 | # 72 | # # L2 or lorentzian function 73 | # for ROBUST in 0 3; do 74 | # # use graymethod or not 75 | # for GRAYMETHOD in 0 1; do 76 | # # estimation of the transformation for all images 77 | # $prog $NUMBER $INPAT_NOISY $TRUE_REGPAT $REF $GRAYMETHOD $SAVE $FIRST_SCALE $EDGEPADDING $ROBUST_GRADIENT $ROBUST $NANIFOUTSIDE $SCALES $PRECISION $transform $NTHREADS $w $h $opt 78 | # basefile=graymethod${GRAYMETHOD}_save${SAVE}_scale${FIRST_SCALE}_edge${EDGEPADDING}_nan${NANIFOUTSIDE}_gradient${ROBUST_GRADIENT}_robust${ROBUST} 79 | # time_ica=time_ica_${basefile}.txt 80 | # rmse_ica=rmse_ica_${basefile}.txt 81 | # mean_and_std $time_ica 0 >> ../../time_robust${ROBUST}_graymethod${GRAYMETHOD}_noise${noise}.txt 82 | # mean_and_std $rmse_ica 0 >> ../../rmse_robust${ROBUST}_graymethod${GRAYMETHOD}_noise${noise}.txt 83 | # done 84 | # done 85 | # 86 | # #clean noisy images 87 | # out="" 88 | # for i in `seq 1 $NUMBER`; do 89 | # OUTi=`printf $INPAT_NOISY $i` 90 | # out="$out $OUTi" 91 | # done 92 | # rm $out 93 | # 94 | # cd .. 95 | # done 96 | # 97 | # rm ${base_out}_* 98 | # 99 | # cd .. 100 | # done 101 | 102 | 103 | echo "\\begin{table}" 104 | echo "\\begin{center}" 105 | echo "\\begin{tabular}{l|l|l|l|l|l}" 106 | echo "\\multicolumn{2}{l}{} &\\multicolumn{2}{|c|}{L2} & \\multicolumn{2}{c}{Lorentzian} \\\\" 107 | echo "\\hline" 108 | echo "\\multicolumn{2}{l|}{} & & Grayscale & & Grayscale\\\\" 109 | for noise in 0 3 5 10 20 30 50; do 110 | echo "\\hline" 111 | 112 | #RMSE 113 | line2echo="\\multirow{2}{0.1\\linewidth}{$\sigma = $noise$} & EPE" 114 | for ROBUST in 0 3; do 115 | for GRAYMETHOD in 0 1; do 116 | basefile=robust${ROBUST}_graymethod${GRAYMETHOD}_noise${noise} 117 | # field comparison 118 | rmse_ica=rmse_${basefile}.txt 119 | line2echo="$line2echo & `mean_and_std $rmse_ica 0`" 120 | done 121 | done 122 | line2echo="$line2echo \\\\" 123 | echo "$line2echo" 124 | 125 | #TIME 126 | line2echo=" & Time" 127 | for ROBUST in 0 3; do 128 | for GRAYMETHOD in 0 1; do 129 | basefile=robust${ROBUST}_graymethod${GRAYMETHOD}_noise${noise} 130 | # field comparison 131 | time_ica=time_${basefile}.txt 132 | vartime=`mean_and_std $time_ica 0` 133 | line2echo="$line2echo & `echo \"$vartime\" | cut -f1 -d\.`" 134 | done 135 | done 136 | if [ ! "$noise" -eq "50" ]; then 137 | line2echo="$line2echo \\\\" 138 | fi 139 | echo "$line2echo" 140 | done 141 | echo "\\end{tabular}" 142 | echo "\\caption{Influence of the color handling}" 143 | echo "\\label{fig::ic_color_handling}" 144 | echo "\\end{center}" 145 | echo "\\end{table}" 146 | 147 | cd .. 148 | -------------------------------------------------------------------------------- /experiments/comparison_javier_optimized.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -lt "4" ]; then 4 | echo "usage:\n\t$0 in noise n L" 5 | echo "image en chemin absolu" 6 | exit 1 7 | fi 8 | 9 | in=$1 10 | noise=$2 11 | NUMBER=$3 12 | L=$4 13 | 14 | if [ -z "$BUILD_IMAGES" ]; then 15 | BUILD_IMAGES=0; 16 | fi 17 | if [ -z "$NOISE" ]; then 18 | NOISE=0; 19 | fi 20 | if [ -z "$NTHREADS" ]; then 21 | NTHREADS=1 22 | fi 23 | if [ -z "$GRAYMETHOD" ]; then 24 | GRAYMETHOD=0 25 | fi 26 | if [ -z "$SAVELONGER" ]; then 27 | SAVELONGER=1 28 | fi 29 | if [ -z "$NANIFOUTSIDE" ]; then 30 | NANIFOUTSIDE=1 31 | fi 32 | if [ -z "$EDGEPADDING" ]; then 33 | EDGEPADDING=5 34 | fi 35 | if [ -z "$ROBUST_GRADIENT" ]; then 36 | ROBUST_GRADIENT=3 37 | fi 38 | if [ -z "$NSCALES" ]; then 39 | NSCALES=5 40 | fi 41 | if [ -z "$ROBUST" ]; then 42 | ROBUST=3 43 | fi 44 | if [ -z "$PRECISION" ]; then 45 | PRECISION=0.001 46 | fi 47 | if [ -z "$FIRST_SCALE" ]; then 48 | FIRST_SCALE=0 49 | fi 50 | 51 | echo "Experiments with GRAYMETHOD=$GRAYMETHOD SAVELONGER=$SAVELONGER EDGEPADDING=$EDGEPADDING NANIFOUTSIDE=$NANIFOUTSIDE ROBUST_GRADIENT=$ROBUST_GRADIENT NSCALES=$NSCALES PRECISION=$PRECISION FIRST_SCALE=$FIRST_SCALE ROBUST=$ROBUST" 52 | echo "images $in" 53 | 54 | TIMEFORMAT=%U 55 | 56 | dir=comparison_javier_optimized 57 | mkdir $dir 58 | cd $dir 59 | 60 | interp=bicubic 61 | boundary=hsym 62 | base_out=burst 63 | transform=8 #homography 64 | if [ "$BUILD_IMAGES" -eq "1" ]; then 65 | create_burst $in $base_out $NUMBER $interp $boundary $L $transform 66 | fi 67 | 68 | # comparison fields 69 | centered=0 70 | w=`imprintf %w $in` 71 | h=`imprintf %h $in` 72 | opt=1 # to determine if comparison has h1-h2 (1) or h2^-1 o h1 - id (0) 73 | 74 | if [ "$NOISE" -eq "1" ]; then 75 | for i in `seq 1 $NUMBER`; do 76 | add_noise $noise ${base_out}_$i.tiff ${base_out}_noisy_$i.tiff 77 | done 78 | fi 79 | 80 | REF=${base_out}_noisy_1.tiff 81 | { time for i in `seq 2 $NUMBER`; do 82 | INi=${base_out}_noisy_$i.tiff 83 | REGi=${base_out}_estimated_$i.hom 84 | REG2i=${base_out}_estimated_javier_$i.hom 85 | cmd="GRAYMETHOD=$GRAYMETHOD SAVELONGER=$SAVELONGER EDGEPADDING=$EDGEPADDING NANIFOUTSIDE=$NANIFOUTSIDE ROBUST_GRADIENT=$ROBUST_GRADIENT inverse_compositional_algorithm $REF $INi -f $REGi -n $NSCALES -r $ROBUST -e $PRECISION -t $transform -s $FIRST_SCALE" 86 | cmd="$cmd; ica_javier $REF $INi -f $REG2i -n $NSCALES -r $ROBUST -e $PRECISION -t $transform;" 87 | echo $cmd 88 | done | parallel -j $NTHREADS &> /dev/null; } 89 | 90 | # image parameters 91 | rmse_ica=rmse.txt 92 | rmse_ica_javier=rmse_javier.txt 93 | rm $rmse_ica $rmse_ica_javier -f 94 | for i in `seq 2 $NUMBER`; do 95 | #optimized 96 | REGICAi=${base_out}_estimated_$i.hom 97 | REGi=${base_out}_$i.hom 98 | FIELDi=${base_out}_estimated_$i.tiff 99 | compare_homography $w $h "`cat $REGICAi`" "`cat $REGi`" $FIELDi $opt 100 | compute mean $centered $FIELDi >> $rmse_ica 101 | #rm $FIELDi #$REGICAi 102 | #javier 103 | REGICAi=${base_out}_estimated_javier_$i.hom 104 | FIELDi=${base_out}_estimated_javier_$i.tiff 105 | compare_homography $w $h "`cat $REGICAi`" "`cat $REGi`" $FIELDi $opt 106 | compute mean $centered $FIELDi >> $rmse_ica_javier 107 | done 108 | echo "optimized" 109 | mean_and_std $rmse_ica 0 110 | echo "javier" 111 | mean_and_std $rmse_ica_javier 0 112 | 113 | cd .. 114 | -------------------------------------------------------------------------------- /experiments/computation_and_latex.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -lt "3" ]; then 4 | echo "usage:\n\t$0 in number displacement_max_corner [dir]" 5 | echo "example toto.tiff 10 5" 6 | exit 1 7 | fi 8 | 9 | in=$1 10 | NUMBER=$2 11 | L=$3 12 | 13 | NTHREADS=1 14 | if [ -z "$BUILD_IMAGES" ]; then 15 | BUILD_IMAGES=1 16 | fi 17 | 18 | prog=../../recalage_ic.sh 19 | 20 | # create directory 21 | if [ -z "$4" ]; then 22 | dir=evaluation_modification 23 | else 24 | dir=$4 25 | fi 26 | 27 | ref=ref.tiff 28 | 29 | rm -rf $dir 30 | mkdir $dir 31 | cp $in $dir/$ref 32 | cd $dir 33 | 34 | # create burst 35 | echo "Creating burst of $NUMBER images with displacement of $L" 36 | interp=bicubic 37 | boundary=hsym 38 | base_out=burst 39 | transform=8 #homography 40 | if [ "$BUILD_IMAGES" -eq "1" ]; then 41 | create_burst $ref $base_out $NUMBER $interp $boundary $L $transform 42 | fi 43 | 44 | 45 | # TEST with inverse homography 46 | for i in `seq 2 $NUMBER`; do 47 | REGi=${base_out}_$i.hom 48 | invert_homography_ica "`cat $REGi`" $REGi 49 | done 50 | # END TEST 51 | 52 | # sift parameters 53 | regpat=sift_%i.tiff #just used to set the name of the homography files ... 54 | regpat_sift=sift_%i.hom # to this value (shitty script) 55 | method=splineper #useless 56 | boundary=hsym #useless 57 | sr=sr 58 | field_sift=field_sift_%i.tiff 59 | rmse_sift=rmse_sift.txt 60 | max_sift=max_sift.txt 61 | time_sift=time_sift.txt 62 | ref_number=1 # the reference image is assumed to be the first image 63 | 64 | TIMEFORMAT="%U" 65 | 66 | # ICA parameters 67 | SAVE=1 68 | SCALES=5 69 | PRECISION=0.001 70 | 71 | # comparison fields 72 | centered=0 73 | w=`imprintf %w $ref` 74 | h=`imprintf %h $ref` 75 | opt=1 # to determine if comparison has h1-h2 (1) or h2^-1 o h1 - id (0) 76 | 77 | # image parameters 78 | INPAT=../${base_out}_%i.tiff 79 | INPAT_NOISY=noisy_%i.tiff 80 | TRUE_REGPAT=../${base_out}_%i.hom 81 | REF=`printf $INPAT_NOISY 1` 82 | 83 | # loop over the noise level 84 | for noise in 0 3 5 10 20 30 50; do 85 | echo "Noise level $noise" 86 | dir=noise$noise 87 | mkdir $dir 88 | cd $dir 89 | for i in `seq 1 $NUMBER`; do 90 | INi=`printf $INPAT $i` 91 | OUTi=`printf $INPAT_NOISY $i` 92 | add_noise $noise $INi $OUTi 93 | done 94 | 95 | # SIFT + RANSAC estimation 96 | echo "SIFT + RANSAC estimation" 97 | { time NTHREADS=$NTHREADS burst_registration_iteration.sh $INPAT_NOISY $regpat $ref_number $NUMBER $ref_number $method $boundary $sr 0 &> /dev/null; } 2> $time_sift 98 | 99 | # field comparison 100 | for i in `seq 2 $NUMBER`; do 101 | REGSIFTi=`printf $regpat_sift $i` 102 | REGi=`printf $TRUE_REGPAT $i` 103 | FIELDi=`printf $field_sift $i` 104 | # TEST with inverse homography 105 | invert_homography_ica "`cat $REGSIFTi`" $REGSIFTi 106 | # END TEST 107 | compare_homography $w $h "`cat $REGSIFTi`" "`cat $REGi`" $FIELDi $opt 108 | compute mean $centered $FIELDi >> $rmse_sift 109 | rm $FIELDi $REGSIFTi 110 | done 111 | 112 | # ICA 113 | echo "ICA estimation" 114 | 115 | for ROBUST in 0 3; do 116 | # DBP table 117 | FIRST_SCALE=0 118 | ROBUST_GRADIENT=0 119 | GRAYMETHOD=0 120 | NANIFOUTSIDE=0 121 | EDGEPADDING=0 122 | $prog $NUMBER $INPAT_NOISY $TRUE_REGPAT $REF $GRAYMETHOD $SAVE $FIRST_SCALE $EDGEPADDING $ROBUST_GRADIENT $ROBUST $NANIFOUTSIDE $SCALES $PRECISION $transform $NTHREADS $w $h $opt 123 | 124 | NANIFOUTSIDE=1 125 | for EDGEPADDING in 0 5; do 126 | $prog $NUMBER $INPAT_NOISY $TRUE_REGPAT $REF $GRAYMETHOD $SAVE $FIRST_SCALE $EDGEPADDING $ROBUST_GRADIENT $ROBUST $NANIFOUTSIDE $SCALES $PRECISION $transform $NTHREADS $w $h $opt 127 | done 128 | 129 | #COLOR 130 | FIRST_SCALE=0 131 | ROBUST_GRADIENT=0 132 | EDGEPADDING=5 133 | NANIFOUTSIDE=1 134 | for GRAYMETHOD in 0 1; do 135 | $prog $NUMBER $INPAT_NOISY $TRUE_REGPAT $REF $GRAYMETHOD $SAVE $FIRST_SCALE $EDGEPADDING $ROBUST_GRADIENT $ROBUST $NANIFOUTSIDE $SCALES $PRECISION $transform $NTHREADS $w $h $opt 136 | done 137 | 138 | #GRADIENT 139 | FIRST_SCALE=0 140 | GRAYMETHOD=1 141 | NANIFOUTSIDE=1 142 | EDGEPADDING=5 143 | for ROBUST_GRADIENT in 0 1 2 3 4 5; do 144 | $prog $NUMBER $INPAT_NOISY $TRUE_REGPAT $REF $GRAYMETHOD $SAVE $FIRST_SCALE $EDGEPADDING $ROBUST_GRADIENT $ROBUST $NANIFOUTSIDE $SCALES $PRECISION $transform $NTHREADS $w $h $opt 145 | done 146 | 147 | #FIRST SCALE 148 | ROBUST_GRADIENT=3 149 | GRAYMETHOD=1 150 | NANIFOUTSIDE=1 151 | EDGEPADDING=5 152 | for FIRST_SCALE in 0 1 2 3; do 153 | $prog $NUMBER $INPAT_NOISY $TRUE_REGPAT $REF $GRAYMETHOD $SAVE $FIRST_SCALE $EDGEPADDING $ROBUST_GRADIENT $ROBUST $NANIFOUTSIDE $SCALES $PRECISION $transform $NTHREADS $w $h $opt 154 | done 155 | 156 | #all method 157 | GRAYMETHOD=0 158 | EDGEPADDING=0 159 | NANIFOUTSIDE=0 160 | ROBUST_GRADIENT=0 161 | FIRST_SCALE=0 162 | $prog $NUMBER $INPAT_NOISY $TRUE_REGPAT $REF $GRAYMETHOD $SAVE $FIRST_SCALE $EDGEPADDING $ROBUST_GRADIENT $ROBUST $NANIFOUTSIDE $SCALES $PRECISION $transform $NTHREADS $w $h $opt 163 | 164 | GRAYMETHOD=1 165 | EDGEPADDING=5 166 | NANIFOUTSIDE=1 167 | ROBUST_GRADIENT=3 168 | FIRST_SCALE=0 169 | $prog $NUMBER $INPAT_NOISY $TRUE_REGPAT $REF $GRAYMETHOD $SAVE $FIRST_SCALE $EDGEPADDING $ROBUST_GRADIENT $ROBUST $NANIFOUTSIDE $SCALES $PRECISION $transform $NTHREADS $w $h $opt 170 | 171 | GRAYMETHOD=1 172 | EDGEPADDING=5 173 | NANIFOUTSIDE=1 174 | ROBUST_GRADIENT=3 175 | FIRST_SCALE=1 176 | $prog $NUMBER $INPAT_NOISY $TRUE_REGPAT $REF $GRAYMETHOD $SAVE $FIRST_SCALE $EDGEPADDING $ROBUST_GRADIENT $ROBUST $NANIFOUTSIDE $SCALES $PRECISION $transform $NTHREADS $w $h $opt 177 | done 178 | 179 | #clean 180 | for i in `seq 1 $NUMBER`; do 181 | OUTi=`printf $INPAT_NOISY $i` 182 | rm $OUTi 183 | done 184 | cd .. 185 | done 186 | 187 | cd .. -------------------------------------------------------------------------------- /experiments/dataset/img31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/dataset/img31.png -------------------------------------------------------------------------------- /experiments/dataset/img32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/dataset/img32.png -------------------------------------------------------------------------------- /experiments/dataset/script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #crop 800 1712 -800 -1712 img32.jpg img32.png 3 | #crop 800 1712 -800 -1712 img31.jpg img31.png 4 | 5 | if [ -z "$NSCALES" ]; then 6 | NSCALES=0 7 | fi 8 | 9 | ref=img31.png 10 | im=img32.png 11 | 12 | bc=hsym 13 | typeinterp=bicubic 14 | 15 | # parameters for the matching 16 | M_MATCH=290 17 | M_RANGE=290 18 | 19 | # parameters for ransac 20 | RANSAC_N=10000 21 | RANSAC_E=0.5 22 | RANSAC_M=4 23 | 24 | # ic parameter 25 | ROBUST=3 26 | 27 | # sift 28 | out=sift.tiff 29 | diff=sift_diff.tiff 30 | w=`identify -format %w $ref` 31 | h=`identify -format %h $ref` 32 | PAIRS0i=file.pairs 33 | SIFT1=ref.sift 34 | rm -f $SIFT1 35 | SIFT2=transformed.sift 36 | rm -f $SIFT2 37 | HOMO=sift.hom 38 | MASK=mask.txt 39 | INLIERS=inliers.txt 40 | unisift2.sh ives $ref > $SIFT1 41 | unisift2.sh ives $im > $SIFT2 42 | siftu pairr $M_MATCH $SIFT1 $SIFT2 $M_RANGE $M_RANGE $PAIRS0i 43 | ransac2 hom $RANSAC_N $RANSAC_E $RANSAC_M /dev/null $HOMO $MASK $INLIERS /dev/null "$w $h" 1 < $PAIRS0i 44 | 45 | convert_homography "`cat $HOMO`" $HOMO 46 | EDGEPADDING=0 generate_output $ref $im $HOMO 47 | mv output_estimated.tiff $out 48 | mv diff_image_rmse.tiff $diff 49 | 50 | #ic standard 51 | out=ic_standard.tiff 52 | diff=ic_standard_diff.tiff 53 | HOMO=ic_standard.hom 54 | EDGEPADDING=0 NANIFOUTSIDE=0 ROBUST_GRADIENT=0 GRAYMETHOD=0 inverse_compositional_algorithm $ref $im -f $HOMO -r $ROBUST -n $NSCALES -v 55 | EDGEPADDING=0 generate_output $ref $im $HOMO 56 | mv output_estimated.tiff $out 57 | mv diff_image_rmse.tiff $diff 58 | 59 | #ic optimized 60 | first=0 61 | out=ic_optimized.tiff 62 | diff=ic_optimized_diff.tiff 63 | HOMO=ic_optimized.hom 64 | EDGEPADDING=5 NANIFOUTSIDE=1 ROBUST_GRADIENT=3 GRAYMETHOD=1 inverse_compositional_algorithm $ref $im -f $HOMO -r $ROBUST -n $NSCALES -s $first -v 65 | EDGEPADDING=0 generate_output $ref $im $HOMO 66 | mv output_estimated.tiff $out 67 | mv diff_image_rmse.tiff $diff 68 | 69 | echo "Standard vs optimized" 70 | EDGEPADDING=0 generate_output $ref $im ic_standard.hom ic_optimized.hom 71 | mv epe.tiff epe_ic_vs_mic.tiff 72 | echo "Sift vs optimized" 73 | EDGEPADDING=0 generate_output $ref $im sift.hom ic_optimized.hom 74 | mv epe.tiff epe_sift_vs_mic.tiff 75 | echo "Sift vs standard" 76 | EDGEPADDING=0 generate_output $ref $im sift.hom ic_standard.hom 77 | mv epe.tiff epe_sift_vs_standard.tiff 78 | -------------------------------------------------------------------------------- /experiments/evaluation_modification.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -lt "3" ]; then 4 | echo "usage:\n\t$0 in number displacement_max_corner [dir]" 5 | echo "example toto.tiff 10 5" 6 | exit 1 7 | fi 8 | 9 | in=$1 10 | NUMBER=$2 11 | L=$3 12 | 13 | if [ -z "$NTHREADS" ]; then 14 | NTHREADS=1 15 | fi 16 | if [ -z "$BUILD_IMAGES" ]; then 17 | BUILD_IMAGES=1 18 | fi 19 | 20 | # create directory 21 | if [ -z "$4" ]; then 22 | dir=evaluation_modification 23 | else 24 | dir=$4 25 | fi 26 | 27 | ref=ref.tiff 28 | 29 | rm -rf $dir 30 | mkdir $dir 31 | cp $in $dir/$ref 32 | cd $dir 33 | 34 | # create burst 35 | echo "Creating burst of $NUMBER images with displacement of $L" 36 | interp=bicubic 37 | boundary=hsym 38 | base_out=burst 39 | transform=8 #homography 40 | if [ "$BUILD_IMAGES" -eq "1" ]; then 41 | create_burst $ref $base_out $NUMBER $interp $boundary $L $transform 42 | fi 43 | 44 | # sift parameters 45 | regpat=sift_%i.tiff #just used to set the name of the homography files ... 46 | regpat_sift=sift_%i.hom # to this value (shitty script) 47 | method=splineper #useless 48 | boundary=hsym #useless 49 | sr=sr 50 | field_sift=field_sift_%i.tiff 51 | rmse_sift=rmse_sift.txt 52 | max_sift=max_sift.txt 53 | time_sift=time_sift.txt 54 | ref_number=1 # the reference image is assumed to be the first image 55 | 56 | TIMEFORMAT="%U" 57 | 58 | # ICA parameters 59 | SAVE=1 60 | SCALES=5 61 | PRECISION=0.001 62 | 63 | # comparison fields 64 | centered=0 65 | w=`imprintf %w $ref` 66 | h=`imprintf %h $ref` 67 | opt=1 # to determine if comparison has h1-h2 (1) or h2^-1 o h1 - id (0) 68 | 69 | # image parameters 70 | INPAT=../${base_out}_%i.tiff 71 | INPAT_NOISY=noisy_%i.tiff 72 | TRUE_REGPAT=../${base_out}_%i.hom 73 | REF=`printf $INPAT_NOISY 1` 74 | 75 | # loop over the noise level 76 | for noise in 0 3 5 10 20 30 50; do 77 | echo "Noise level $noise" 78 | dir=noise$noise 79 | mkdir $dir 80 | cd $dir 81 | for i in `seq 1 $NUMBER`; do 82 | INi=`printf $INPAT $i` 83 | OUTi=`printf $INPAT_NOISY $i` 84 | add_noise $noise $INi $OUTi 85 | done 86 | 87 | # SIFT + RANSAC estimation 88 | echo "SIFT + RANSAC estimation" 89 | { time NTHREADS=$NTHREADS burst_registration_iteration.sh $INPAT_NOISY $regpat $ref_number $NUMBER $ref_number $method $boundary $sr 0 &> /dev/null; } 2> $time_sift 90 | 91 | # field comparison 92 | for i in `seq 2 $NUMBER`; do 93 | REGSIFTi=`printf $regpat_sift $i` 94 | REGi=`printf $TRUE_REGPAT $i` 95 | FIELDi=`printf $field_sift $i` 96 | compare_homography $w $h "`cat $REGSIFTi`" "`cat $REGi`" $FIELDi $opt 97 | compute mean $centered $FIELDi >> $rmse_sift 98 | rm $FIELDi $REGSIFTi 99 | done 100 | 101 | # ICA 102 | c=`imprintf %c $REF` 103 | echo "ICA estimation" 104 | if [ "$c" -eq "3" ]; then 105 | for GRAYMETHOD in 0 1; do 106 | for FIRST_SCALE in 0 1 2 3; do 107 | for NANIFOUTSIDE in 0 1; do 108 | for EDGEPADDING in 0 5; do 109 | if [ "$NANIFOUTSIDE" -eq "1" -o "$EDGEPADDING" -eq "0" ]; then 110 | for ROBUST_GRADIENT in 0 1 2 3 4 5; do 111 | for ROBUST in 0 3; do 112 | echo "graymethod $GRAYMETHOD save $SAVE first_scale ${FIRST_SCALE} edge ${EDGEPADDING} gradient ${ROBUST_GRADIENT} robust ${ROBUST} nanifoutside ${NANIFOUTSIDE}" 113 | basefile=graymethod${GRAYMETHOD}_save${SAVE}_scale${FIRST_SCALE}_edge${EDGEPADDING}_nan${NANIFOUTSIDE}_gradient${ROBUST_GRADIENT}_robust${ROBUST} 114 | regpat_ica=ica_${basefile}_%i.hom 115 | time_ica=time_ica_${basefile}.txt 116 | field_ica=field_ica_${basefile}_%i.tiff 117 | rmse_ica=rmse_ica_${basefile}.txt 118 | max_ica=max_ica_${basefile}.txt 119 | 120 | # ICA estimation 121 | { time for i in `seq 2 $NUMBER`; do 122 | INi=`printf $INPAT_NOISY $i` 123 | REGi=`printf $regpat_ica $i` 124 | cmd="GRAYMETHOD=$GRAYMETHOD SAVELONGER=$SAVE EDGEPADDING=$EDGEPADDING NANIFOUTSIDE=$NANIFOUTSIDE ROBUST_GRADIENT=$ROBUST_GRADIENT inverse_compositional_algorithm $REF $INi -f $REGi -n $SCALES -r $ROBUST -e $PRECISION -t $transform -s $FIRST_SCALE" 125 | echo "$cmd" 126 | done | parallel -j $NTHREADS &> /dev/null; } 2> $time_ica 127 | 128 | # field comparison 129 | for i in `seq 2 $NUMBER`; do 130 | REGICAi=`printf $regpat_ica $i` 131 | REGi=`printf $TRUE_REGPAT $i` 132 | FIELDi=`printf $field_ica $i` 133 | compare_homography $w $h "`cat $REGICAi`" "`cat $REGi`" $FIELDi $opt 134 | compute mean $centered $FIELDi >> $rmse_ica 135 | rm $FIELDi $REGICAi 136 | done 137 | done 138 | done 139 | fi 140 | done 141 | done 142 | done 143 | done 144 | else 145 | GRAYMETHOD=0 146 | for FIRST_SCALE in 0 1 2 3; do 147 | for EDGEPADDING in 0 5; do 148 | for NANIFOUTSIDE in 0 1; do 149 | if [ "$NANIFOUTSIDE" -eq "1" -o "$EDGEPADDING" -eq "0" ]; then 150 | for ROBUST_GRADIENT in 0 1 2 3 4 5; do 151 | for ROBUST in 0 3; do 152 | echo "graymethod $GRAYMETHOD save $SAVE first_scale ${FIRST_SCALE} edge ${EDGEPADDING} gradient ${ROBUST_GRADIENT} robust ${ROBUST} nanifoutside ${NANIFOUTSIDE}" 153 | basefile=graymethod${GRAYMETHOD}_save${SAVE}_scale${FIRST_SCALE}_edge${EDGEPADDING}_nan${NANIFOUTSIDE}_gradient${ROBUST_GRADIENT}_robust${ROBUST} 154 | regpat_ica=ica_${basefile}_%i.hom 155 | time_ica=time_ica_${basefile}.txt 156 | field_ica=field_ica_${basefile}_%i.tiff 157 | rmse_ica=rmse_ica_${basefile}.txt 158 | max_ica=max_ica_${basefile}.txt 159 | 160 | # ICA estimation 161 | { time for i in `seq 2 $NUMBER`; do 162 | INi=`printf $INPAT_NOISY $i` 163 | REGi=`printf $regpat_ica $i` 164 | cmd="GRAYMETHOD=$GRAYMETHOD SAVELONGER=$SAVE EDGEPADDING=$EDGEPADDING NANIFOUTSIDE=$NANIFOUTSIDE ROBUST_GRADIENT=$ROBUST_GRADIENT inverse_compositional_algorithm $REF $INi -f $REGi -n $SCALES -r $ROBUST -e $PRECISION -t $transform -s $FIRST_SCALE" 165 | echo "$cmd" 166 | done | parallel -j $NTHREADS &> /dev/null; } 2> $time_ica 167 | 168 | # field comparison 169 | for i in `seq 2 $NUMBER`; do 170 | REGICAi=`printf $regpat_ica $i` 171 | REGi=`printf $TRUE_REGPAT $i` 172 | FIELDi=`printf $field_ica $i` 173 | compare_homography $w $h "`cat $REGICAi`" "`cat $REGi`" $FIELDi $opt 174 | compute mean $centered $FIELDi >> $rmse_ica 175 | rm $FIELDi $REGICAi 176 | done 177 | done 178 | done 179 | fi 180 | done 181 | done 182 | done 183 | fi 184 | 185 | #clean 186 | for i in `seq 1 $NUMBER`; do 187 | OUTi=`printf $INPAT_NOISY $i` 188 | rm $OUTi 189 | done 190 | cd .. 191 | done 192 | 193 | cd .. 194 | -------------------------------------------------------------------------------- /experiments/evaluation_modification_all_images.sh: -------------------------------------------------------------------------------- 1 | dirimage=../input 2 | number=101 3 | L=20 4 | for image in affinity2 homography22 homography2 identity2 rotation_translation2 translation2 zoom2 zoom_rotation2 zoom_rotation_translation2 lena; do 5 | im=$dirimage/$image.png 6 | ./evaluation_modification.sh $im $number $L $image 7 | ./evaluation_modification_latex.sh $image > ${image}_L20_avocat.txt 8 | rm -rf $image 9 | done 10 | -------------------------------------------------------------------------------- /experiments/other-data/Beanbags/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Beanbags/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/Beanbags/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Beanbags/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/Dimetrodon/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Dimetrodon/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/Dimetrodon/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Dimetrodon/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/DogDance/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/DogDance/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/DogDance/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/DogDance/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/Grove2/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Grove2/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/Grove2/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Grove2/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/Grove3/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Grove3/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/Grove3/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Grove3/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/Hydrangea/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Hydrangea/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/Hydrangea/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Hydrangea/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/MiniCooper/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/MiniCooper/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/MiniCooper/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/MiniCooper/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/RubberWhale/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/RubberWhale/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/RubberWhale/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/RubberWhale/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/Urban2/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Urban2/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/Urban2/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Urban2/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/Urban3/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Urban3/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/Urban3/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Urban3/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/Venus/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Venus/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/Venus/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Venus/frame11.png -------------------------------------------------------------------------------- /experiments/other-data/Walking/frame10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Walking/frame10.png -------------------------------------------------------------------------------- /experiments/other-data/Walking/frame11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/experiments/other-data/Walking/frame11.png -------------------------------------------------------------------------------- /experiments/recalage_ic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -lt "18" ]; then 4 | echo "usage:\n\t$0 NUMBER INPAT_NOISY TRUE_REGPAT REF GRAYMETHOD SAVE FIRST_SCALE EDGEPADDING ROBUST_GRADIENT ROBUST NANIFOUTSIDE SCALES PRECISION transform NTHREADS w h opt" 5 | exit 1 6 | fi 7 | 8 | NUMBER=$1 9 | INPAT_NOISY=$2 10 | TRUE_REGPAT=$3 11 | REF=$4 12 | GRAYMETHOD=$5 13 | SAVE=$6 14 | FIRST_SCALE=$7 15 | EDGEPADDING=$8 16 | ROBUST_GRADIENT=$9 17 | ROBUST=${10} 18 | NANIFOUTSIDE=${11} 19 | SCALES=${12} 20 | PRECISION=${13} 21 | transform=${14} 22 | NTHREADS=${15} 23 | w=${16} 24 | h=${17} 25 | opt=${18} 26 | 27 | TIMEFORMAT="%U" 28 | 29 | #echo "graymethod $GRAYMETHOD save $SAVE first_scale ${FIRST_SCALE} edge ${EDGEPADDING} gradient ${ROBUST_GRADIENT} robust ${ROBUST} nanifoutside ${NANIFOUTSIDE}" 30 | basefile=graymethod${GRAYMETHOD}_save${SAVE}_scale${FIRST_SCALE}_edge${EDGEPADDING}_nan${NANIFOUTSIDE}_gradient${ROBUST_GRADIENT}_robust${ROBUST} 31 | regpat_ica=ica_${basefile}_%i.hom 32 | time_ica=time_ica_${basefile}.txt 33 | field_ica=field_ica_${basefile}_%i.tiff 34 | rmse_ica=rmse_ica_${basefile}.txt 35 | max_ica=max_ica_${basefile}.txt 36 | 37 | if [ ! -s $time_ica ]; then 38 | # ICA estimation 39 | { time for i in `seq 2 $NUMBER`; do 40 | INi=`printf $INPAT_NOISY $i` 41 | REGi=`printf $regpat_ica $i` 42 | # TEST 43 | #cmd="GRAYMETHOD=$GRAYMETHOD SAVELONGER=$SAVE EDGEPADDING=$EDGEPADDING NANIFOUTSIDE=$NANIFOUTSIDE ROBUST_GRADIENT=$ROBUST_GRADIENT inverse_compositional_algorithm $REF $INi -f $REGi -n $SCALES -r $ROBUST -e $PRECISION -t $transform -s $FIRST_SCALE" 44 | cmd="inverse_compositional_algorithm $INi $REF -f $REGi -n $SCALES -r $ROBUST -e $PRECISION -t $transform -s $FIRST_SCALE -c $GRAYMETHOD -d $EDGEPADDING -p $NANIFOUTSIDE -g $ROBUST_GRADIENT" 45 | # END TEST 46 | echo "$cmd" 47 | done | parallel -j $NTHREADS &> /dev/null; } 2> $time_ica 48 | 49 | # field comparison 50 | for i in `seq 2 $NUMBER`; do 51 | REGICAi=`printf $regpat_ica $i` 52 | REGi=`printf $TRUE_REGPAT $i` 53 | FIELDi=`printf $field_ica $i` 54 | homo1=`echo $(cat $REGICAi)` 55 | homo2=`echo $(cat $REGi)` 56 | cmd="compare_homography $w $h \"$homo1\" \"$homo2\" $FIELDi $opt" 57 | cmd="$cmd; compute mean 0 $FIELDi" 58 | cmd="$cmd; rm $FIELDi $REGICAi" 59 | echo "$cmd" 60 | done | parallel -j 7 >> $rmse_ica 61 | fi -------------------------------------------------------------------------------- /experiments/rmse_method.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -lt "4" ]; then 4 | echo "usage:\n\t$0 in noise n L" 5 | echo "image en chemin absolu" 6 | exit 1 7 | fi 8 | 9 | in=$1 10 | noise=$2 11 | NUMBER=$3 12 | L=$4 13 | 14 | if [ -z "$BUILD_IMAGES" ]; then 15 | BUILD_IMAGES=0; 16 | fi 17 | if [ -z "$NOISE" ]; then 18 | NOISE=0; 19 | fi 20 | if [ -z "$NTHREADS" ]; then 21 | NTHREADS=1 22 | fi 23 | if [ -z "$GRAYMETHOD" ]; then 24 | GRAYMETHOD=0 25 | fi 26 | if [ -z "$SAVELONGER" ]; then 27 | SAVELONGER=1 28 | fi 29 | if [ -z "$NANIFOUTSIDE" ]; then 30 | NANIFOUTSIDE=1 31 | fi 32 | if [ -z "$EDGEPADDING" ]; then 33 | EDGEPADDING=5 34 | fi 35 | if [ -z "$ROBUST_GRADIENT" ]; then 36 | ROBUST_GRADIENT=3 37 | fi 38 | if [ -z "$NSCALES" ]; then 39 | NSCALES=5 40 | fi 41 | if [ -z "$ROBUST" ]; then 42 | ROBUST=3 43 | fi 44 | if [ -z "$PRECISION" ]; then 45 | PRECISION=0.001 46 | fi 47 | if [ -z "$FIRST_SCALE" ]; then 48 | FIRST_SCALE=0 49 | fi 50 | 51 | echo "Experiments with GRAYMETHOD=$GRAYMETHOD SAVELONGER=$SAVELONGER EDGEPADDING=$EDGEPADDING NANIFOUTSIDE=$NANIFOUTSIDE ROBUST_GRADIENT=$ROBUST_GRADIENT NSCALES=$NSCALES PRECISION=$PRECISION FIRST_SCALE=$FIRST_SCALE ROBUST=$ROBUST" 52 | echo "image $in" 53 | 54 | TIMEFORMAT=%U 55 | 56 | dir=rmse_ica_fixed 57 | mkdir $dir 58 | cd $dir 59 | 60 | interp=bicubic 61 | #interp=splineper 62 | boundary=hsym 63 | base_out=burst 64 | transform=8 #homography 65 | if [ "$BUILD_IMAGES" -eq "1" ]; then 66 | create_burst $in $base_out $NUMBER $interp $boundary $L $transform 67 | fi 68 | 69 | # comparison fields 70 | centered=0 71 | w=`imprintf %w $in` 72 | h=`imprintf %h $in` 73 | opt=1 # to determine if comparison has h1-h2 (1) or h2^-1 o h1 - id (0) 74 | 75 | if [ "$NOISE" -eq "1" ]; then 76 | for i in `seq 1 $NUMBER`; do 77 | add_noise $noise ${base_out}_$i.tiff ${base_out}_noisy_$i.tiff 78 | done 79 | fi 80 | 81 | REF=${base_out}_noisy_1.tiff 82 | { time for i in `seq 2 $NUMBER`; do 83 | INi=${base_out}_noisy_$i.tiff 84 | REGi=${base_out}_estimated_$i.hom 85 | cmd="GRAYMETHOD=$GRAYMETHOD SAVELONGER=$SAVELONGER EDGEPADDING=$EDGEPADDING NANIFOUTSIDE=$NANIFOUTSIDE ROBUST_GRADIENT=$ROBUST_GRADIENT inverse_compositional_algorithm $REF $INi -f $REGi -n $NSCALES -r $ROBUST -e $PRECISION -t $transform -s $FIRST_SCALE" 86 | echo $cmd 87 | done | parallel -j $NTHREADS &> /dev/null; } 88 | 89 | # image parameters 90 | rmse_ica=rmse.txt 91 | rm $rmse_ica -f 92 | for i in `seq 2 $NUMBER`; do 93 | REGICAi=${base_out}_estimated_$i.hom 94 | REGi=${base_out}_$i.hom 95 | FIELDi=${base_out}_estimated_$i.tiff 96 | compare_homography $w $h "`cat $REGICAi`" "`cat $REGi`" $FIELDi $opt 97 | compute mean $centered $FIELDi >> $rmse_ica 98 | #rm $FIELDi #$REGICAi 99 | done 100 | mean_and_std $rmse_ica 0 101 | 102 | cd .. 103 | -------------------------------------------------------------------------------- /experiments/synthetic_color/plot_figure.m: -------------------------------------------------------------------------------- 1 | cd ~/these/inverse_compositional/experiments/synthetic_color 2 | % h=figure; 3 | % ref = imread('synthetic_1.png'); 4 | % imagesc(ref), axis 'image', set(gca,'xtick',[]), set(gca,'ytick',[]); 5 | 6 | %% 7 | a = 0.0015; 8 | h=figure; 9 | epe_ic = read_tiff('epe_ic_standard.tiff'); 10 | imagesc(epe_ic, [0 a]), axis 'image', colorbar, set(gca,'xtick',[]), set(gca,'ytick',[]); 11 | set(gcf,'color','white') 12 | saveas(h,'epe_ic.eps','epsc'); 13 | % 14 | h=figure; 15 | epe_mic = read_tiff('epe_ic_optimized.tiff'); 16 | imagesc(epe_mic, [0 a]), axis 'image', colorbar, set(gca,'xtick',[]), set(gca,'ytick',[]); 17 | set(gcf,'color','white') 18 | saveas(h,'epe_mic.eps','epsc'); 19 | % 20 | 21 | a=0.05; 22 | h=figure; 23 | diff_ic = read_tiff('diff_image_ic_standard.tiff'); 24 | [m,n] = size(diff_ic); 25 | 26 | for i=1:m 27 | for j=1:n 28 | if isnan(diff_ic(i,j)) 29 | diff_ic(i,j) = 0; 30 | end 31 | end 32 | end 33 | imagesc(diff_ic, [0 a]), axis 'image', colorbar, set(gca,'xtick',[]), set(gca,'ytick',[]); 34 | set(gcf,'color','white') 35 | saveas(h,'gt_diff_ic.eps','epsc'); 36 | 37 | % 38 | h=figure; 39 | diff_mic = read_tiff('diff_image_ic_optimized.tiff'); 40 | [m,n] = size(diff_mic); 41 | for i=1:m 42 | for j=1:n 43 | if isnan(diff_mic(i,j)) 44 | diff_mic(i,j) = 0; 45 | end 46 | end 47 | end 48 | imagesc(diff_mic, [0 a]), axis 'image', colorbar, set(gca,'xtick',[]), set(gca,'ytick',[]); 49 | set(gcf,'color','white') 50 | saveas(h,'gt_diff_mic.eps','epsc'); -------------------------------------------------------------------------------- /experiments/synthetic_color/script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ref=~/these/inverse_compositional/input/reverse/affinity1.png 4 | base_in=synthetic 5 | 6 | bc=hsym 7 | typeinterp=bicubic 8 | opt=1 9 | 10 | n=2 11 | L=20 12 | create_burst $ref $base_in $n $typeinterp $bc $L 13 | 14 | ref=${base_in}_2.tiff 15 | im=${base_in}_1.tiff 16 | homoGt=${base_in}_2.hom 17 | invert_homography_ica "`cat $homoGt`" $homoGt 18 | #convert_homography "`cat $homoGt`" $homoGt 19 | 20 | w=`identify -format %w $ref` 21 | h=`identify -format %h $ref` 22 | 23 | # sift 24 | out=sift.tiff 25 | # parameters for the matching 26 | M_MATCH=290 27 | M_RANGE=20 28 | 29 | # parameters for ransac 30 | RANSAC_N=10000 31 | RANSAC_E=0.5 32 | RANSAC_M=4 33 | 34 | PAIRS0i=file.pairs 35 | SIFT1=ref.sift 36 | SIFT2=transformed.sift 37 | HOMO=sift.hom 38 | MASK=mask.txt 39 | INLIERS=inliers.txt 40 | unisift2.sh ives $ref > $SIFT1 41 | unisift2.sh ives $im > $SIFT2 42 | siftu pairr $M_MATCH $SIFT1 $SIFT2 $M_RANGE $M_RANGE $PAIRS0i 43 | ransac2 hom $RANSAC_N $RANSAC_E $RANSAC_M /dev/null $HOMO $MASK $INLIERS /dev/null "$w $h" 1 < $PAIRS0i 44 | 45 | # compare_homography $w $h "`cat $HOMO`" "`cat $homoGt`" $out $opt 46 | # echo "Sift" > rmse_field.txt 47 | # compute rmse 0 $out >> rmse_field.txt 48 | # interpolation homi "`cat $HOMO`" $typeinterp $bc $im interp_$out 49 | # diff2 $ref interp_$out diff_$out 50 | 51 | convert_homography "`cat $HOMO`" $HOMO 52 | EDGEPADDING=0 generate_output $ref $im $HOMO $homoGt 53 | mv diff_image_rmse.tiff diff_image_sift.tiff 54 | mv epe.tiff epe_sift.tiff 55 | 56 | # # ic standard 57 | out=ic_standard.tiff 58 | HOMO=ic_standard.hom 59 | ROBUST=3 60 | GRAYMETHOD=0 EDGEPADDING=0 NANIFOUTSIDE=0 ROBUST_GRADIENT=0 inverse_compositional_algorithm $ref $im -f $HOMO -r $ROBUST -v 61 | 62 | EDGEPADDING=0 generate_output $ref $im $HOMO $homoGt 63 | mv diff_image_rmse.tiff diff_image_ic_standard.tiff 64 | mv epe.tiff epe_ic_standard.tiff 65 | 66 | # compare_homography $w $h "`cat $HOMO`" "`cat $homoGt`" $out $opt 67 | # echo "IC standard" >> rmse_field.txt 68 | # compute rmse 0 $out >> rmse_field.txt 69 | # interpolation homi "`cat $HOMO`" $typeinterp $bc $im interp_$out 70 | # diff2 $ref interp_$out diff_$out 71 | 72 | # ic optimized 73 | # out=ic_optimized.tiff 74 | # HOMO=ic_optimized.hom 75 | # ROBUST=3 76 | # EDGEPADDING=5 NANIFOUTSIDE=1 ROBUST_GRADIENT=3 inverse_compositional_algorithm $ref $im -f $HOMO -r $ROBUST -v 77 | # 78 | # 79 | # compare_homography $w $h "`cat $HOMO`" "`cat $homoGt`" $out $opt 80 | # echo "IC optimized" >> rmse_field.txt 81 | # compute rmse 0 $out >> rmse_field.txt 82 | # interpolation homi "`cat $HOMO`" $typeinterp $bc $im interp_$out 83 | # diff2 $ref interp_$out diff_$out 84 | 85 | # ic optimized gray 86 | out=ic_optimized.tiff 87 | HOMO=ic_optimized.hom 88 | ROBUST=3 89 | GRAYMETHOD=1 EDGEPADDING=5 NANIFOUTSIDE=1 ROBUST_GRADIENT=3 inverse_compositional_algorithm $ref $im -f $HOMO -r $ROBUST -v 90 | 91 | EDGEPADDING=0 generate_output $ref $im $HOMO $homoGt 92 | mv diff_image_rmse.tiff diff_image_ic_optimized.tiff 93 | mv epe.tiff epe_ic_optimized.tiff 94 | 95 | # compare_homography $w $h "`cat $HOMO`" "`cat $homoGt`" $out $opt 96 | # echo "IC optimized" >> rmse_field.txt 97 | # compute rmse 0 $out >> rmse_field.txt 98 | # interpolation homi "`cat $HOMO`" $typeinterp $bc $im interp_$out 99 | # diff2 $ref interp_$out diff_$out 100 | 101 | # to save images 102 | iion synthetic_1.tiff synthetic_1.png 103 | iion synthetic_2.tiff synthetic_2.png 104 | #affine0255 ic_optimized.tiff field_example.png 105 | -------------------------------------------------------------------------------- /experiments/synthetic_color/script2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | epstopdf.sh 4 | pdfcrop epe_ic.pdf epe_ic.pdf 5 | pdfcrop epe_mic.pdf epe_mic.pdf 6 | pdfcrop gt_diff_ic.pdf gt_diff_ic.pdf 7 | pdfcrop gt_diff_mic.pdf gt_diff_mic.pdf -------------------------------------------------------------------------------- /file.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #include 11 | #include 12 | #include "file.h" 13 | 14 | extern "C" 15 | { 16 | #include "iio.h" 17 | } 18 | 19 | /** 20 | * 21 | * Functions to read images using the iio library 22 | * It allocates memory for the image and returns true if it 23 | * correctly reads the image 24 | * 25 | */ 26 | bool read_image 27 | ( 28 | char *fname, //file name 29 | double **f, //output image 30 | int &nx, //number of columns of the image 31 | int &ny, //number of rows of the image 32 | int &nz //number of channels of the image 33 | ) 34 | { 35 | *f = iio_read_image_double_vec(fname, &nx, &ny, &nz); 36 | return *f ? true : false; 37 | } 38 | 39 | bool read_image 40 | ( 41 | char *fname, //file name 42 | float **f, //output image 43 | int &nx, //number of columns of the image 44 | int &ny, //number of rows of the image 45 | int &nz //number of channels of the image 46 | ) 47 | { 48 | *f = iio_read_image_float_vec(fname, &nx, &ny, &nz); 49 | return *f ? true : false; 50 | } 51 | 52 | /** 53 | * 54 | * Functions to save images using the iio library 55 | * 56 | */ 57 | void save_image 58 | ( 59 | char *fname, //file name 60 | double *f, //output image 61 | int nx, //number of columns of the image 62 | int ny, //number of rows of the image 63 | int nz //number of channels of the image 64 | ) 65 | { 66 | float *ff=new float[nx*ny*nz]; 67 | for(int i=0;imax)max=f[i]; 86 | } 87 | 88 | float *ff=new float[nx*ny*nz]; 89 | for(int i=0;imin) 91 | for(int i=0;i. 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #ifndef FILE_H 11 | #define FILE_H 12 | 13 | /** 14 | * 15 | * Functions to read images using the iio library 16 | * It allocates memory for the image and returns true if it 17 | * correctly reads the image 18 | * 19 | */ 20 | bool read_image 21 | ( 22 | char *fname, //file name 23 | double **f, //output image 24 | int &nx, //number of columns of the image 25 | int &ny, //number of rows of the image 26 | int &nz //number of channels of the image 27 | ); 28 | 29 | bool read_image 30 | ( 31 | char *fname, //file name 32 | float **f, //output image 33 | int &nx, //number of columns of the image 34 | int &ny, //number of rows of the image 35 | int &nz //number of channels of the image 36 | ); 37 | 38 | /** 39 | * 40 | * Functions to save images using the iio library 41 | * 42 | */ 43 | void save_image 44 | ( 45 | char *fname, //file name 46 | double *f, //output image 47 | int nx, //number of columns of the image 48 | int ny, //number of rows of the image 49 | int nz //number of channels of the image 50 | ); 51 | 52 | 53 | void save_normalize_image 54 | ( 55 | char *fname, //file name 56 | double *f, //output image 57 | int nx, //number of columns of the image 58 | int ny, //number of rows of the image 59 | int nz //number of channels of the image 60 | ); 61 | 62 | 63 | void save_image 64 | ( 65 | char *fname, //file name 66 | float *f, //output image 67 | int nx, //number of columns of the image 68 | int ny, //number of rows of the image 69 | int nz //number of channels of the image 70 | ); 71 | 72 | /** 73 | * 74 | * Function to save flow fields using the iio library 75 | * 76 | */ 77 | void save_flow 78 | ( 79 | char *file, //file name 80 | double *u, //x component of the optical flow 81 | double *v, //y component of the optical flow 82 | int nx, //number of columns 83 | int ny //number of rows 84 | ); 85 | 86 | /** 87 | * 88 | * Function to read the parameters in ascii format 89 | * It reads a header with: nparams nx ny 90 | * Then it reads the parameters for each pixel 91 | * 92 | */ 93 | void read 94 | ( 95 | char *file, //input file name 96 | double **p, //parameters to be read 97 | int &nparams, //number of parameters 98 | int &nx, //number of columns 99 | int &ny //number of rows 100 | ); 101 | 102 | /** 103 | * 104 | * Function to save the parameters in ascii format 105 | * It creates a header with: nparams nx ny 106 | * Then it stores the parameters for each pixel 107 | * 108 | */ 109 | void save 110 | ( 111 | char *file, //output file name 112 | double *p, //parameters to be saved 113 | int nparams, //number of parameters 114 | int nx, //number of columns 115 | int ny //number of rows 116 | ); 117 | 118 | /** 119 | * 120 | * Function to read the parameters in ascii format 121 | * It reads a header with: nparams nx ny 122 | * Then it reads the parameters 123 | * 124 | */ 125 | void read 126 | ( 127 | const char *file, //input file name 128 | double **p, //parameters to be read 129 | int &nparams //number of parameters 130 | ); 131 | 132 | /** 133 | * 134 | * Function to save the parameters in ascii format 135 | * It creates a header with: nparams nx ny 136 | * Then it stores the parameters 137 | * 138 | */ 139 | void save 140 | ( 141 | const char *file, //output file name 142 | double *p, //parameters to be saved 143 | int nparams //number of parameters 144 | ); 145 | 146 | /** 147 | * 148 | * Function to save the parameters in ascii format 149 | * 150 | */ 151 | void save_matrix 152 | ( 153 | const char *file, //output file name 154 | double *p, //parameters to be saved 155 | int nparams //number of parameters 156 | ); 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /iio.h: -------------------------------------------------------------------------------- 1 | #ifndef IIO_H 2 | #define IIO_H 3 | 4 | #include // for uint8_t 5 | #include // for bool 6 | 7 | 8 | // 9 | // 10 | // 11 | // IIO: "Image Input-Output" 12 | // 13 | // A set of C functions for reading and writing small images 14 | // 15 | // Philosophy: an image is an array of numbers (not colors, not intensities, 16 | // not luminances). These functions read and write numbers from and to files. 17 | // 18 | // 19 | // 20 | 21 | 22 | /////////////////////////////// 23 | // HIGH-LEVEL API FUNCTIONS // 24 | // (using only C constructs) // 25 | /////////////////////////////// 26 | 27 | 28 | 29 | // 30 | // basic float API for 2D images (returns a freeable pointer) 31 | // 32 | 33 | float *iio_read_image_float(const char *fname, int *w, int *h); 34 | // x[i+j*w] 35 | 36 | float *iio_read_image_float_vec(const char *fname, int *w, int *h, int *pd); 37 | // x[(i + j*w)*pd + l] 38 | 39 | float *iio_read_image_float_rgb(const char *fname, int *w, int *h); 40 | // x[(i + j*w)*3 + l] 41 | 42 | float *iio_read_image_float_split(const char *fname, int *w, int *h, int *pd); 43 | // x[w*h*l + i + j*w] 44 | 45 | // 46 | // convenience float API for 2D images (also returns a freeable pointer) 47 | // 48 | 49 | float **iio_read_image_float_matrix(const char *fname, int *w, int *h); 50 | // x[j][i] 51 | 52 | float (**iio_read_image_float_matrix_2vec(const char *fnam, int *w, int *h))[2]; 53 | float (**iio_read_image_float_matrix_3vec(const char *fnam, int *w, int *h))[3]; 54 | float (**iio_read_image_float_matrix_4vec(const char *fnam, int *w, int *h))[4]; 55 | float (**iio_read_image_float_matrix_rgb(const char *fnam, int *w, int *h))[3]; 56 | float (**iio_read_image_float_matrix_rgba(const char *fnam, int *w, int *h))[4]; 57 | // x[j][i][channel] 58 | // (The "rgb" and "rgba" functions may re-order the channels according to file 59 | // metadata. The "vec" functions should produce the data in the same order as 60 | // is stored, whatever that means.) 61 | void *iio_read_image_float_matrix_vec(const char *fnam, int *w, int *h, int *pd); 62 | 63 | 64 | 65 | // 66 | // So far, we have seen the functions for reading multi-channel "2D" images, 67 | // whose samples are of type "FLOAT", from a "NAMED FILE". The rest of the 68 | // API consists in variations of these functions, changing the quoted options 69 | // of the previous sentence in all possible ways. For instance, there are 70 | // the following variations of the function "iio_read_image_float": 71 | // 72 | // // read 3D image into floats, from a named file 73 | // float *iio_read_3d_image_float(char *fname, int *w, int *h, int *d); 74 | // 75 | // // read 2D image into bytes, from a named file 76 | // uint8_t *iio_read_image_uint8(char *fname, int *w, int *h); 77 | // 78 | // // read 2D image into floats, from an open stream 79 | // float *iio_read_image_float_f(FILE *f, int *w, int *h); 80 | // 81 | // // read 2D image into floats, from memory 82 | // float *iio_read_image_float_m(void *f, size_t s, int *w, int *h); 83 | // 84 | // // general forms of these functions 85 | // TYPE *iio_read{,_3d,_4d,_nd}_image_TYPE{,_f,_m}(...); 86 | // TYPE **iio_read{,_3d,_4d,_nd}_image_TYPE_matrix{,_f,_m}(...); 87 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_2vec{,_f,_m}(...))[2]; 88 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_3vec{,_f,_m}(...))[3]; 89 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_4vec{,_f,_m}(...))[4]; 90 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_rgb{,_f,_m}(...))[3]; 91 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_rgba{,_f,_m}(...))[4]; 92 | // 93 | // 94 | double *iio_read_image_double(const char *fname, int *w, int *h); 95 | double *iio_read_image_double_vec(const char *fname, int *w, int *h, int *pd); 96 | double *iio_read_image_double_split(const char *fname, int *w, int *h, int *pd); 97 | 98 | 99 | // All these functions are boring variations, and they are defined at the 100 | // end of this file. More interesting are the two following general 101 | // functions: 102 | 103 | void *iio_read_image_numbers_as_they_are_stored(char *fname, int *w, int *h, 104 | int *samples_per_pixel, int *sample_size, 105 | bool *ieeefp_samples, bool *signed_samples); 106 | 107 | void *iio_read_image_numbers_in_requested_format(char *fname, int *w, int *h, 108 | int *samples_per_pixel, int requested_sample_size, 109 | bool requested_ieeefp, bool requested_sign); 110 | 111 | // These two general functions have the usual versions for nD images and 112 | // streams. There exist also the following truly general functions, that 113 | // read images of any dimension: 114 | 115 | void *iio_read_nd_image_as_stored(char *fname, 116 | int *dimension, int *sizes, 117 | int *samples_per_pixel, int *sample_size, 118 | bool *ieeefp_samples, bool *signed_samples); 119 | 120 | void *iio_read_nd_image_as_desired(char *fname, 121 | int *dimension, int *sizes, 122 | int *samples_per_pixel, int desired_sample_size, 123 | bool desired_ieeefp_samples, bool desired_signed_samples); 124 | 125 | 126 | 127 | 128 | 129 | 130 | #ifdef UINT8_MAX 131 | 132 | // basic byte API (returns a freeable pointer) 133 | // 134 | 135 | uint8_t *iio_read_image_uint8(const char *fname, int *w, int *h); 136 | // x[i+j*w] 137 | 138 | uint8_t *iio_read_image_uint8_vec(const char *fname, int *w, int *h, int *nc); 139 | // x[(i + j*w)*nc + l] 140 | 141 | uint8_t (*iio_read_image_uint8_rgb(const char *fnam, int *w, int *h))[3]; 142 | // x[(i + j*w)*3 + l] 143 | 144 | 145 | // 146 | // convenience float API (also returns a freeable pointer) 147 | // 148 | 149 | uint8_t **iio_read_image_uint8_matrix(const char *fname, int *w, int *h); 150 | // x[j][i] 151 | 152 | uint8_t (**iio_read_image_uint8_matrix_2vec(const char *fnam, int *w, int *h))[2]; 153 | uint8_t (**iio_read_image_uint8_matrix_3vec(const char *fnam, int *w, int *h))[3]; 154 | uint8_t (**iio_read_image_uint8_matrix_4vec(const char *fnam, int *w, int *h))[4]; 155 | uint8_t (**iio_read_image_uint8_matrix_rgb(const char *fnam, int *w, int *h))[3]; 156 | uint8_t (**iio_read_image_uint8_matrix_rgba(const char *fnam, int *w, int *h))[4]; 157 | // x[j][i][channel] 158 | // (The "rgb" and "rgba" functions may re-order the channels according to file 159 | // metadata. The "vec" functions produce the data in the same order as is 160 | // stored.) 161 | uint8_t ***iio_read_image_uint8_matrix_vec(const char *fnam, int *w, int *h, int *pd); 162 | 163 | #endif//UINT8_MAX 164 | 165 | #ifdef UINT16_MAX 166 | uint16_t *iio_read_image_uint16_vec(const char *fname, int *w, int *h, int *pd); 167 | #endif//UINT16_MAX 168 | 169 | 170 | // functions for writing images, with the same conventions as for reding 171 | void iio_write_image_float_vec (char*, float* , int, int, int); 172 | void iio_write_image_float_split (char*, float* , int, int, int); 173 | void iio_write_image_double_vec (char*, double* , int, int, int); 174 | void iio_write_image_double_split (char*, double* , int, int, int); 175 | void iio_write_image_float (char*, float* , int, int ); 176 | void iio_write_image_double (char*, double* , int, int ); 177 | void iio_write_image_int (char*, int* , int, int ); 178 | void iio_write_image_int_vec (char*, int* , int, int, int); 179 | void iio_write_image_uint8_vec (char*, uint8_t* , int, int, int); 180 | void iio_write_image_uint8_split (char*, uint8_t* , int, int, int); 181 | void iio_write_image_uint16_vec (char*, uint16_t* , int, int, int); 182 | void iio_write_image_uint8_matrix_rgb(char*, uint8_t(**)[3], int, int ); 183 | void iio_write_image_uint8_matrix (char*, uint8_t** , int, int ); 184 | 185 | 186 | #define IIO_USE_INCONSISTENT_NAMES 187 | #ifdef IIO_USE_INCONSISTENT_NAMES 188 | // functions for writing images, with the same conventions as for reding 189 | // (note: these functions use the wording "save" instead of "write") 190 | void iio_save_image_float_vec(char *filename, float *x, int w, int h, int pd); 191 | void iio_save_image_float_split(char *filename, float *x, int w, int h, int pd); 192 | void iio_save_image_double_vec(char *filename, double *x, int w, int h, int pd); 193 | void iio_save_image_float(char *filename, float *x, int w, int h); 194 | void iio_save_image_double(char *filename, double *x, int w, int h); 195 | void iio_save_image_int(char *filename, int *x, int w, int h); 196 | void iio_save_image_int_vec(char *filename, int *x, int w, int h, int pd); 197 | void iio_save_image_uint8_vec(char *filename, uint8_t *x, int w, int h, int pd); 198 | void iio_save_image_uint16_vec(char *filename, uint16_t *x, int w, int h, int pd); 199 | void iio_save_image_uint8_matrix_rgb(char *f, unsigned char (**x)[3], int w, int h); 200 | void iio_save_image_uint8_matrix(char *f, unsigned char **x, int w, int h); 201 | #endif//IIO_USE_INCONSISTENT_NAMES 202 | 203 | // SAVING FORMATS: 204 | // (w, h; 1 uint8) => pgm, png, tiff, pfm 205 | // (w, h; 3 uint8) => ppm, png, tiff, pfm 206 | // (w, h; 1 uint16) => pgm, png, tiff, pfm 207 | // (w, h; 3 uint16) => ppm, png, tiff, pfm 208 | // (w, h; 1 float) => tiff, pfm 209 | // (w, h; 3 float) => tiff, pfm 210 | 211 | 212 | #endif//IIO_H 213 | -------------------------------------------------------------------------------- /input/affinity2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/affinity2.png -------------------------------------------------------------------------------- /input/clena_nb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/clena_nb.png -------------------------------------------------------------------------------- /input/homography.mat: -------------------------------------------------------------------------------- 1 | 8 2 | -0.2 0.1 -0.19 -0.13 0.1 -0.1 0.00010 0.0010 3 | 4 | -------------------------------------------------------------------------------- /input/homography1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/homography1.png -------------------------------------------------------------------------------- /input/homography2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/homography2.png -------------------------------------------------------------------------------- /input/homography22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/homography22.png -------------------------------------------------------------------------------- /input/identity2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/identity2.png -------------------------------------------------------------------------------- /input/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/lena.png -------------------------------------------------------------------------------- /input/lena_nb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/lena_nb.png -------------------------------------------------------------------------------- /input/rotation_translation2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/rotation_translation2.png -------------------------------------------------------------------------------- /input/script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for im in homography rotation rotation_translation translation zoom zoom_rotation_translation zoom_rotation homography2 identity; do 4 | cp ${im}1.png reverse/${im}2.png 5 | cp ${im}2.png reverse/${im}1.png 6 | invert_homography_ica "`cat ${im}.mat`" reverse/${im}.mat 7 | done 8 | -------------------------------------------------------------------------------- /input/traffic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/traffic.png -------------------------------------------------------------------------------- /input/translation2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/translation2.png -------------------------------------------------------------------------------- /input/zoom2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/zoom2.png -------------------------------------------------------------------------------- /input/zoom_rotation2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/zoom_rotation2.png -------------------------------------------------------------------------------- /input/zoom_rotation_translation2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/input/zoom_rotation_translation2.png -------------------------------------------------------------------------------- /inverse_compositional_algorithm.h: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #ifndef INVERSE_COMPOSITIONAL_ALGORITHM 11 | #define INVERSE_COMPOSITIONAL_ALGORITHM 12 | 13 | /** 14 | * 15 | * This code implements the 'modified inverse compositional algorithm'. 16 | * 17 | * The 'inverse compositional algorithm' was proposed in 18 | * [1] S. Baker, and I. Matthews. (2004). Lucas-kanade 20 years on: A 19 | * unifying framework. International Journal of Computer Vision, 20 | * 56(3), 221-255. 21 | * [2] S. Baker, R. Gross, I. Matthews, and T. Ishikawa. (2004). 22 | * Lucas-kanade 20 years on: A unifying framework: Part 2. 23 | * International Journal of Computer Vision, 56(3), 221-255. 24 | * 25 | * This implementation is for color images. It calculates the global 26 | * transform between two images. It uses robust error functions and a 27 | * coarse-to-fine strategy for computing large displacements 28 | * 29 | **/ 30 | 31 | #define QUADRATIC 0 32 | #define TRUNCATED_QUADRATIC 1 33 | #define GEMAN_MCCLURE 2 34 | #define LORENTZIAN 3 35 | #define CHARBONNIER 4 36 | 37 | #define MAX_ITER 30 38 | #define LAMBDA_0 80 39 | #define LAMBDA_N 5 40 | #define LAMBDA_RATIO 0.90 41 | 42 | #define PRECOMPUTATION_GTG //comment to remove the precomputation of GTG 43 | 44 | /** 45 | * 46 | * Derivative of robust error functions 47 | * 48 | */ 49 | double rhop( 50 | double t2, //squared difference of both images 51 | double sigma, //robust threshold 52 | int type //choice of the robust error function 53 | ); 54 | 55 | /** 56 | * 57 | * Inverse compositional algorithm 58 | * Quadratic version - L2 norm 59 | * 60 | * 61 | **/ 62 | void inverse_compositional_algorithm( 63 | double *I1, //first image 64 | double *I2, //second image 65 | double *p, //parameters of the transform (output) 66 | int nparams, //number of parameters of the transform 67 | int nx, //number of columns of the image 68 | int ny, //number of rows of the image 69 | int nz, //number of channels of the images 70 | double TOL, //tolerance used for the convergence in the iterations 71 | int nanifoutside, //parameter for discarding boundary pixels 72 | int delta, //distance to the boundary 73 | int type_gradient, //type of gradient 74 | int verbose=0 //enable verbose mode 75 | ); 76 | 77 | /** 78 | * 79 | * Inverse compositional algorithm 80 | * Version with robust error functions 81 | * 82 | **/ 83 | void robust_inverse_compositional_algorithm( 84 | double *I1, //first image 85 | double *I2, //second image 86 | double *p, //parameters of the transform (output) 87 | int nparams, //number of parameters of the transform 88 | int nx, //number of columns of the image 89 | int ny, //number of rows of the image 90 | int nz, //number of channels of the images 91 | double TOL, //Tolerance used for the convergence in the iterations 92 | int robust, //robust error function 93 | double lambda, //parameter of robust error function 94 | int nanifoutside, //parameter for discarding boundary pixels 95 | int delta, //distance to the boundary 96 | int type_gradient, //type of gradient 97 | int verbose=0 //enable verbose mode 98 | ); 99 | 100 | /** 101 | * 102 | * Multiscale approach for computing the optical flow 103 | * 104 | **/ 105 | void pyramidal_inverse_compositional_algorithm( 106 | double *I1, //first image 107 | double *I2, //second image 108 | double *p, //parameters of the transform 109 | int nparams, //number of parameters 110 | int nxx, //image width 111 | int nyy, //image height 112 | int nzz, //number of color channels in image 113 | int nscales, //number of scales 114 | double nu, //downsampling factor 115 | double TOL, //stopping criterion threshold 116 | int robust, //robust error function 117 | double lambda, //parameter of robust error function 118 | int first_scale, //number of the first scale 119 | int nanifoutside, //parameter for discarding boundary pixels 120 | int delta, //distance to the boundary 121 | int type_gradient, //type of gradient 122 | bool verbose //switch on messages 123 | ); 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Thibaud Briand 2 | Copyright (c) 2015, Javier Sánchez Pérez 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | 27 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -Wextra -O3 2 | LDFLAGS=-lm -lpng -ljpeg -ltiff -lstdc++ 3 | 4 | SRC1 := bicubic_interpolation.cpp inverse_compositional_algorithm.cpp mask.cpp transformation.cpp file.cpp matrix.cpp zoom.cpp 5 | SRC2 := iio.c mt19937ar.c 6 | 7 | INCLUDE = -I. 8 | 9 | #Replace suffix .cpp and .c by .o 10 | OBJ := $(addsuffix .o,$(basename $(SRC1))) $(addsuffix .o,$(basename $(SRC2))) 11 | 12 | #Binary file 13 | BIN = inverse_compositional_algorithm add_noise generate_output equalization 14 | 15 | #All is the target (you would run make all from the command line). 'all' is dependent 16 | all: $(BIN) 17 | 18 | #Generate executables 19 | inverse_compositional_algorithm: main.o $(OBJ) 20 | $(CXX) -std=c++11 $^ -o $@ $(LDFLAGS) 21 | 22 | add_noise: mt19937ar.o file.o iio.o noise.o 23 | $(CXX) -std=c++11 $^ -o $@ $(LDFLAGS) 24 | 25 | generate_output: output.o $(OBJ) 26 | $(CXX) -std=c++11 $^ -o $@ $(LDFLAGS) 27 | 28 | equalization: equalization.o iio.o 29 | $(CC) -std=c99 $^ -o $@ $(LDFLAGS) 30 | 31 | #each object file is dependent on its source file, and whenever make needs to create 32 | #an object file, to follow this rule: 33 | %.o: %.c 34 | $(CC) -std=c99 -c $< -o $@ $(INCLUDE) $(CFLAGS) -Wno-unused -pedantic -DNDEBUG -D_GNU_SOURCE 35 | 36 | %.o: %.cpp 37 | $(CXX) -std=c++11 -c $< -o $@ $(INCLUDE) $(CFLAGS) 38 | 39 | clean: 40 | rm -f $(OBJ) $(BIN) main.o output.o noise.o equalization.o 41 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/README.txt: -------------------------------------------------------------------------------- 1 | The Inverse Compositional Algorithm for Parametric Motion Estimation 2 | -------------------------------------------------------------------- 3 | 4 | ******* 5 | SUMMARY 6 | ******* 7 | 8 | This program implements the modified inverse compositional algorithm for 9 | parametric motion estimation. It computes a planar transformation between two 10 | images, including translations, similarities, affinities and homographies. It 11 | computes large displacements through a pyramidal scheme and uses robust 12 | functionals to deal with noise and occlusions. 13 | 14 | Reference articles: 15 | 16 | [1] S. Baker and I. Matthews, Lucas-kanade 20 years on: A unifying framework, 17 | International journal of computer vision, 56 (2004), pp. 221-255. 18 | 19 | [2] S. Baker, R. Gross, I. Matthews, and T. Ishikawa, Lucas-kanade 20 years 20 | on: A unifying framework: Part 2, Tech. Report CMU-RI-TR-03-01, Robotics 21 | Institute, Pittsburgh, PA, February 2003. 22 | 23 | This program is part of an IPOL publication: 24 | http://www.ipol.im/ 25 | 26 | 27 | ****** 28 | AUTHOR 29 | ****** 30 | 31 | Thibaud Briand 32 | Laboratoire d'information Gaspard Monge (LIGM) 33 | Ecole Nationale des Ponts et Chaussées (ENPC) 34 | 35 | Javier Sánchez Pérez 36 | Centro de Tecnologías de la Imagen (CTIM) 37 | Universidad de Las Palmas de Gran Canaria 38 | 39 | 40 | ******* 41 | VERSION 42 | ******* 43 | 44 | Version 1, released on ??? 45 | 46 | 47 | ******* 48 | LICENSE 49 | ******* 50 | 51 | This program is free software: you can use, modify and/or redistribute it 52 | under the terms of the simplified BSD License. You should have received a 53 | copy of this license along this program. If not, see 54 | . 55 | 56 | Copyright (C) 2018, Thibaud Briand 57 | Copyright (C) 2015, Javier Sánchez Pérez 58 | All rights reserved. 59 | 60 | 61 | *********** 62 | COMPILATION 63 | *********** 64 | 65 | Required environment: Any unix-like system with a standard compilation 66 | environment (make and C and C++ compilers) 67 | 68 | Required libraries: libpng, lipjpeg, libtiff 69 | 70 | Compilation instructions: run "make" to produce an executable 71 | "inverse_compositional_algorithm" 72 | 73 | 74 | ***** 75 | USAGE 76 | ***** 77 | 78 | The program reads two input images, take some parameters and produce a 79 | parametric model. The meaning of the parameters is thoroughly discussed on the 80 | accompanying IPOL article. Usage instructions: 81 | 82 | : inverse_compositional_algorithm image1 image2 [OPTIONS] 83 | 84 | OPTIONS: 85 | -------- 86 | -f name Name of the output filename that will contain the 87 | computed transformation 88 | Default value transform.mat 89 | -o N Output transformation format: 90 | 0-Parametrization 91 | 1-3x3 Projective matrix 92 | Default value 0 93 | -n N Number of scales for the coarse-to-fine scheme 94 | Default value 0 95 | -z F Zoom factor used in the coarse-to-fine scheme 96 | Values must be in the range (0,1) 97 | Default value 0.50 98 | -e F Threshold for the convergence criterion 99 | Default value 0.0010 100 | -t N Transformation type to be computed: 101 | 2-translation; 3-Euclidean transform; 4-similarity 102 | 6-affinity; 8-homography 103 | Default value 8 104 | -r N Use robust error functions: 105 | 0-Non robust (L2 norm); 1-truncated quadratic 106 | 2-Geman & McLure; 3-Lorentzian 4-Charbonnier 107 | Default value 3 108 | -l F Value of the parameter for the robust error function 109 | A value <=0 if it is automatically computed 110 | Default value 0 111 | -s N First scale used in the pyramid 112 | Default value 0 113 | -c N Use grayscale conversion (1) or not (0) 114 | Default value 1 115 | -d N Distance to the boundary 116 | Default value 5 117 | -p N Parameter to discards boudary pixels (1) or not (0) 118 | Default value 1 119 | -g N Use gradient type: 120 | 0-Central differences; 1-Hypomode 121 | 2-Farid 3x3; 3-Farid 5x5; 4-Sigma 3; 5-Sigma 6 122 | Default value 3 123 | -v Switch on verbose mode. 124 | 125 | Execution examples: 126 | 127 | 1.Default parameters: 128 | 129 | >inverse_compositional_algorithm data/homography1.png data/homography2.png 130 | 131 | 2.Computing an affinity with the truncated quadratic and verbose mode: 132 | 133 | >inverse_compositional_algorithm data/homography1.png data/homography2.png 134 | -t 6 -r 1 -v 135 | 136 | If a parameter is given an invalid value it will take a default value. 137 | 138 | 139 | ************* 140 | LIST OF FILES 141 | ************* 142 | bicubic_interpolation.cpp: Computes the bicubic interpolation of an image 143 | file.cpp: Functions for input/output 144 | iio.c: Functions to read and write images 145 | inverse_compositional_algorithm.cpp: Implementation of the method 146 | main.cpp: Main algorithm to read the command line parameters 147 | mask.cpp: Function to compute the gradient of an image and apply a Gaussian 148 | matrix.cpp: Multiplication of matrices and vectors and calculating the inverse 149 | transformation.cpp: Compute the Jacobian and the composition of transformations 150 | zoom.cpp: Compute the zoom-out of an image and the zoom-in of the parameters 151 | 152 | Complementary programs (used for the online demo only): 153 | output.cpp: Program to compute some images and error metrics from the results 154 | noise.cpp: Program to add Gaussian noise to the input images 155 | mt19937ar.c: Program to generate random numbers, used in noise.cpp 156 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/bicubic_interpolation.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #include "bicubic_interpolation.h" 12 | #include "transformation.h" 13 | #include 14 | #include 15 | #include 16 | 17 | /** 18 | * 19 | * Neumann boundary condition test 20 | * 21 | **/ 22 | static int 23 | neumann_bc( 24 | int x, //index 25 | int nx //size 26 | ) 27 | { 28 | if (x<0) 29 | x = 0; 30 | else if (x >= nx) 31 | x = nx - 1; 32 | return x; 33 | } 34 | 35 | /** 36 | * 37 | * Bicubic interpolation in one dimension 38 | * 39 | **/ 40 | static double 41 | cubic_interpolation( 42 | double v[4], //interpolation points 43 | double x //point to be interpolated 44 | ) 45 | { 46 | return v[1] + 0.5 * x * (v[2] - v[0] 47 | + x * (2.0 * v[0] - 5.0 * v[1] + 4.0 * v[2] - v[3] 48 | + x * (3.0 * (v[1] - v[2]) + v[3] - v[0]))); 49 | } 50 | 51 | /** 52 | * 53 | * Bicubic interpolation in two dimension 54 | * 55 | **/ 56 | static double 57 | bicubic_interpolation( 58 | double p[4][4], //array containing the interpolation points 59 | double x, //x position to be interpolated 60 | double y //y position to be interpolated 61 | ) 62 | { 63 | double v[4]; 64 | v[0] = cubic_interpolation (p[0], y); 65 | v[1] = cubic_interpolation (p[1], y); 66 | v[2] = cubic_interpolation (p[2], y); 67 | v[3] = cubic_interpolation (p[3], y); 68 | return cubic_interpolation (v, x); 69 | } 70 | 71 | /** 72 | * 73 | * Compute the bicubic interpolation of a point in an image. 74 | * Detects if the point goes outside the image domain 75 | * 76 | **/ 77 | double 78 | bicubic_interpolation( 79 | double *input, //image to be interpolated 80 | double uu, //x component of the vector field 81 | double vv, //y component of the vector field 82 | int nx, //width of the image 83 | int ny, //height of the image 84 | int nz, //number of channels of the image 85 | int k //actual channel 86 | ) 87 | { 88 | int sx = (uu < 0) ? -1 : 1; 89 | int sy = (vv < 0) ? -1 : 1; 90 | 91 | int x, y, mx, my, dx, dy, ddx, ddy; 92 | 93 | x = neumann_bc ((int) uu, nx); 94 | y = neumann_bc ((int) vv, ny); 95 | mx = neumann_bc ((int) uu - sx, nx); 96 | my = neumann_bc ((int) vv - sx, ny); 97 | dx = neumann_bc ((int) uu + sx, nx); 98 | dy = neumann_bc ((int) vv + sy, ny); 99 | ddx = neumann_bc ((int) uu + 2 * sx, nx); 100 | ddy = neumann_bc ((int) vv + 2 * sy, ny); 101 | 102 | //obtain the interpolation points of the image 103 | double p11 = input[(mx + nx * my) * nz + k]; 104 | double p12 = input[(x + nx * my) * nz + k]; 105 | double p13 = input[(dx + nx * my) * nz + k]; 106 | double p14 = input[(ddx + nx * my) * nz + k]; 107 | 108 | double p21 = input[(mx + nx * y) * nz + k]; 109 | double p22 = input[(x + nx * y) * nz + k]; 110 | double p23 = input[(dx + nx * y) * nz + k]; 111 | double p24 = input[(ddx + nx * y) * nz + k]; 112 | 113 | double p31 = input[(mx + nx * dy) * nz + k]; 114 | double p32 = input[(x + nx * dy) * nz + k]; 115 | double p33 = input[(dx + nx * dy) * nz + k]; 116 | double p34 = input[(ddx + nx * dy) * nz + k]; 117 | 118 | double p41 = input[(mx + nx * ddy) * nz + k]; 119 | double p42 = input[(x + nx * ddy) * nz + k]; 120 | double p43 = input[(dx + nx * ddy) * nz + k]; 121 | double p44 = input[(ddx + nx * ddy) * nz + k]; 122 | 123 | //create array 124 | double pol[4][4] = { 125 | {p11, p21, p31, p41}, {p12, p22, p32, p42}, 126 | {p13, p23, p33, p43}, {p14, p24, p34, p44} 127 | }; 128 | 129 | //return interpolation 130 | return bicubic_interpolation (pol, (double) uu - x, (double) vv - y); 131 | } 132 | 133 | /** 134 | * 135 | * Compute the bicubic interpolation of an image from a parametric transform 136 | * 137 | **/ 138 | void bicubic_interpolation( 139 | double *input, //image to be warped 140 | double *output, //warped output image with bicubic interpolation 141 | double *params, //parameters of the transformation 142 | int nparams, //number of parameters of the transform 143 | int nx, //width of the image 144 | int ny, //height of the image 145 | int nz, //number of channels of the image 146 | int delta, //distance to the boundary 147 | int nanifoutside //parameter for discarding boudary pixels 148 | ) 149 | { 150 | double out_value = ( nanifoutside ) ? NAN : 0; 151 | 152 | for (int i=0; i nx-1-delta 162 | || y < delta || y > ny-1-delta ) 163 | out = true; 164 | 165 | if ( out ) { 166 | for(int k=0; k. 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #ifndef BICUBIC_INTERPOLATION_H 12 | #define BICUBIC_INTERPOLATION_H 13 | 14 | double 15 | bicubic_interpolation( 16 | double *input, //image to be interpolated 17 | double uu, //x component of the vector field 18 | double vv, //y component of the vector field 19 | int nx, //width of the image 20 | int ny, //height of the image 21 | int nz, //number of channels of the image 22 | int k //actual channel 23 | ); 24 | 25 | /** 26 | * 27 | * Compute the bicubic interpolation of an image from a parametric trasform 28 | * 29 | **/ 30 | void bicubic_interpolation( 31 | double *input, //image to be warped 32 | double *output, //warped output image with bicubic interpolation 33 | double *params, //x component of the vector field 34 | int nparams, //number of parameters of the transform 35 | int nx, //width of the image 36 | int ny, //height of the image 37 | int nz, //number of channels of the image 38 | int delta, //distance to the boundary 39 | int nanifoutside //parameter for discarding boudary pixels 40 | ); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/data/homography.mat: -------------------------------------------------------------------------------- 1 | 8 2 | -0.2 0.1 -0.19 -0.13 0.1 -0.1 0.00010 0.0010 3 | 4 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/data/homography1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/mInverseCompositional_1.00/data/homography1.png -------------------------------------------------------------------------------- /mInverseCompositional_1.00/data/homography2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbriand/inverse_compositional/30dc11836b927e37f54dae0cc7d5c2c718d08692/mInverseCompositional_1.00/data/homography2.png -------------------------------------------------------------------------------- /mInverseCompositional_1.00/equalization.c: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // All rights reserved. 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "iio.h" 14 | 15 | // function for comparing two values 16 | static int f_compare (const void * a, const void * b) 17 | { 18 | if(*(const float*)a < *(const float*)b) 19 | return -1; 20 | return *(const float*)a > *(const float*)b; 21 | } 22 | 23 | // histogram equalization of two images (it is not Midway !) 24 | static void equalization_histo(float *ref, float *modified, float *out, int w, 25 | int h, int pd) 26 | { 27 | /* mix values and indexes to keep track of pixels' location */ 28 | float *sort_values_ref = malloc(2*w*h*sizeof*sort_values_ref); 29 | float *sort_values_modified = malloc(2*w*h*sizeof*sort_values_modified); 30 | 31 | for (int l=0; l 1 ? v[1] : "-"; 194 | char *filename_modified = c > 2 ? v[2] : "-"; 195 | char *filename_out = c > 3 ? v[3] : "-"; 196 | char *equalization_type = c > 4 ? v[4] : "-"; 197 | 198 | // read images 199 | int w, h, pd; 200 | float *ref = iio_read_image_float_split(filename_ref, &w, &h, &pd); 201 | int w2, h2 , pd2; 202 | float *modified = iio_read_image_float_split(filename_modified, &w2, &h2, &pd2); 203 | 204 | // sanity check 205 | if ( pd != pd2 ) { 206 | fprintf(stderr,"Images should have the same number of channel\n"); 207 | return EXIT_FAILURE; 208 | } 209 | 210 | // memory allocation 211 | float *out = malloc(w2*h2*pd2*sizeof*out); 212 | 213 | // Contrast equalization 214 | if ( 0 == strcmp(equalization_type, "histo") ) { 215 | if( w!=w2 || h!=h2 || pd!=pd2 ) { 216 | fprintf(stderr,"Size of images should be the same\n"); 217 | return EXIT_FAILURE; 218 | } 219 | equalization_histo(ref, modified, out, w, h, pd); 220 | } 221 | else if ( 0 == strcmp(equalization_type, "affine") ) 222 | equalization_affine(ref, modified, out, w, h, w2, h2, pd); 223 | else if ( 0 == strcmp(equalization_type, "meanp") ) 224 | equalization_meanp(ref, modified, out, w, h, w2, h2, pd); 225 | else if ( 0 == strcmp(equalization_type, "meanx") ) 226 | equalization_meanx(ref, modified, out, w, h, w2, h2, pd); 227 | else { 228 | fprintf(stderr,"Unknown equalization type\n"); 229 | return EXIT_FAILURE; 230 | } 231 | 232 | // write output 233 | iio_write_image_float_split(filename_out, out, w2, h2, pd2); 234 | 235 | // free memory 236 | free(ref); 237 | free(modified); 238 | free(out); 239 | 240 | return EXIT_SUCCESS; 241 | } 242 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/file.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #include 11 | #include 12 | #include "file.h" 13 | 14 | extern "C" 15 | { 16 | #include "iio.h" 17 | } 18 | 19 | /** 20 | * 21 | * Functions to read images using the iio library 22 | * It allocates memory for the image and returns true if it 23 | * correctly reads the image 24 | * 25 | */ 26 | bool read_image 27 | ( 28 | char *fname, //file name 29 | double **f, //output image 30 | int &nx, //number of columns of the image 31 | int &ny, //number of rows of the image 32 | int &nz //number of channels of the image 33 | ) 34 | { 35 | *f = iio_read_image_double_vec(fname, &nx, &ny, &nz); 36 | return *f ? true : false; 37 | } 38 | 39 | bool read_image 40 | ( 41 | char *fname, //file name 42 | float **f, //output image 43 | int &nx, //number of columns of the image 44 | int &ny, //number of rows of the image 45 | int &nz //number of channels of the image 46 | ) 47 | { 48 | *f = iio_read_image_float_vec(fname, &nx, &ny, &nz); 49 | return *f ? true : false; 50 | } 51 | 52 | /** 53 | * 54 | * Functions to save images using the iio library 55 | * 56 | */ 57 | void save_image 58 | ( 59 | char *fname, //file name 60 | double *f, //output image 61 | int nx, //number of columns of the image 62 | int ny, //number of rows of the image 63 | int nz //number of channels of the image 64 | ) 65 | { 66 | float *ff=new float[nx*ny*nz]; 67 | for(int i=0;imax)max=f[i]; 86 | } 87 | 88 | float *ff=new float[nx*ny*nz]; 89 | for(int i=0;imin) 91 | for(int i=0;i. 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #ifndef FILE_H 11 | #define FILE_H 12 | 13 | /** 14 | * 15 | * Functions to read images using the iio library 16 | * It allocates memory for the image and returns true if it 17 | * correctly reads the image 18 | * 19 | */ 20 | bool read_image 21 | ( 22 | char *fname, //file name 23 | double **f, //output image 24 | int &nx, //number of columns of the image 25 | int &ny, //number of rows of the image 26 | int &nz //number of channels of the image 27 | ); 28 | 29 | bool read_image 30 | ( 31 | char *fname, //file name 32 | float **f, //output image 33 | int &nx, //number of columns of the image 34 | int &ny, //number of rows of the image 35 | int &nz //number of channels of the image 36 | ); 37 | 38 | /** 39 | * 40 | * Functions to save images using the iio library 41 | * 42 | */ 43 | void save_image 44 | ( 45 | char *fname, //file name 46 | double *f, //output image 47 | int nx, //number of columns of the image 48 | int ny, //number of rows of the image 49 | int nz //number of channels of the image 50 | ); 51 | 52 | 53 | void save_normalize_image 54 | ( 55 | char *fname, //file name 56 | double *f, //output image 57 | int nx, //number of columns of the image 58 | int ny, //number of rows of the image 59 | int nz //number of channels of the image 60 | ); 61 | 62 | 63 | void save_image 64 | ( 65 | char *fname, //file name 66 | float *f, //output image 67 | int nx, //number of columns of the image 68 | int ny, //number of rows of the image 69 | int nz //number of channels of the image 70 | ); 71 | 72 | /** 73 | * 74 | * Function to save flow fields using the iio library 75 | * 76 | */ 77 | void save_flow 78 | ( 79 | char *file, //file name 80 | double *u, //x component of the optical flow 81 | double *v, //y component of the optical flow 82 | int nx, //number of columns 83 | int ny //number of rows 84 | ); 85 | 86 | /** 87 | * 88 | * Function to read the parameters in ascii format 89 | * It reads a header with: nparams nx ny 90 | * Then it reads the parameters for each pixel 91 | * 92 | */ 93 | void read 94 | ( 95 | char *file, //input file name 96 | double **p, //parameters to be read 97 | int &nparams, //number of parameters 98 | int &nx, //number of columns 99 | int &ny //number of rows 100 | ); 101 | 102 | /** 103 | * 104 | * Function to save the parameters in ascii format 105 | * It creates a header with: nparams nx ny 106 | * Then it stores the parameters for each pixel 107 | * 108 | */ 109 | void save 110 | ( 111 | char *file, //output file name 112 | double *p, //parameters to be saved 113 | int nparams, //number of parameters 114 | int nx, //number of columns 115 | int ny //number of rows 116 | ); 117 | 118 | /** 119 | * 120 | * Function to read the parameters in ascii format 121 | * It reads a header with: nparams nx ny 122 | * Then it reads the parameters 123 | * 124 | */ 125 | void read 126 | ( 127 | const char *file, //input file name 128 | double **p, //parameters to be read 129 | int &nparams //number of parameters 130 | ); 131 | 132 | /** 133 | * 134 | * Function to save the parameters in ascii format 135 | * It creates a header with: nparams nx ny 136 | * Then it stores the parameters 137 | * 138 | */ 139 | void save 140 | ( 141 | const char *file, //output file name 142 | double *p, //parameters to be saved 143 | int nparams //number of parameters 144 | ); 145 | 146 | /** 147 | * 148 | * Function to save the parameters in ascii format 149 | * 150 | */ 151 | void save_matrix 152 | ( 153 | const char *file, //output file name 154 | double *p, //parameters to be saved 155 | int nparams //number of parameters 156 | ); 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/iio.h: -------------------------------------------------------------------------------- 1 | #ifndef IIO_H 2 | #define IIO_H 3 | 4 | #include // for uint8_t 5 | #include // for bool 6 | 7 | 8 | // 9 | // 10 | // 11 | // IIO: "Image Input-Output" 12 | // 13 | // A set of C functions for reading and writing small images 14 | // 15 | // Philosophy: an image is an array of numbers (not colors, not intensities, 16 | // not luminances). These functions read and write numbers from and to files. 17 | // 18 | // 19 | // 20 | 21 | 22 | /////////////////////////////// 23 | // HIGH-LEVEL API FUNCTIONS // 24 | // (using only C constructs) // 25 | /////////////////////////////// 26 | 27 | 28 | 29 | // 30 | // basic float API for 2D images (returns a freeable pointer) 31 | // 32 | 33 | float *iio_read_image_float(const char *fname, int *w, int *h); 34 | // x[i+j*w] 35 | 36 | float *iio_read_image_float_vec(const char *fname, int *w, int *h, int *pd); 37 | // x[(i + j*w)*pd + l] 38 | 39 | float *iio_read_image_float_rgb(const char *fname, int *w, int *h); 40 | // x[(i + j*w)*3 + l] 41 | 42 | float *iio_read_image_float_split(const char *fname, int *w, int *h, int *pd); 43 | // x[w*h*l + i + j*w] 44 | 45 | // 46 | // convenience float API for 2D images (also returns a freeable pointer) 47 | // 48 | 49 | float **iio_read_image_float_matrix(const char *fname, int *w, int *h); 50 | // x[j][i] 51 | 52 | float (**iio_read_image_float_matrix_2vec(const char *fnam, int *w, int *h))[2]; 53 | float (**iio_read_image_float_matrix_3vec(const char *fnam, int *w, int *h))[3]; 54 | float (**iio_read_image_float_matrix_4vec(const char *fnam, int *w, int *h))[4]; 55 | float (**iio_read_image_float_matrix_rgb(const char *fnam, int *w, int *h))[3]; 56 | float (**iio_read_image_float_matrix_rgba(const char *fnam, int *w, int *h))[4]; 57 | // x[j][i][channel] 58 | // (The "rgb" and "rgba" functions may re-order the channels according to file 59 | // metadata. The "vec" functions should produce the data in the same order as 60 | // is stored, whatever that means.) 61 | void *iio_read_image_float_matrix_vec(const char *fnam, int *w, int *h, int *pd); 62 | 63 | 64 | 65 | // 66 | // So far, we have seen the functions for reading multi-channel "2D" images, 67 | // whose samples are of type "FLOAT", from a "NAMED FILE". The rest of the 68 | // API consists in variations of these functions, changing the quoted options 69 | // of the previous sentence in all possible ways. For instance, there are 70 | // the following variations of the function "iio_read_image_float": 71 | // 72 | // // read 3D image into floats, from a named file 73 | // float *iio_read_3d_image_float(char *fname, int *w, int *h, int *d); 74 | // 75 | // // read 2D image into bytes, from a named file 76 | // uint8_t *iio_read_image_uint8(char *fname, int *w, int *h); 77 | // 78 | // // read 2D image into floats, from an open stream 79 | // float *iio_read_image_float_f(FILE *f, int *w, int *h); 80 | // 81 | // // read 2D image into floats, from memory 82 | // float *iio_read_image_float_m(void *f, size_t s, int *w, int *h); 83 | // 84 | // // general forms of these functions 85 | // TYPE *iio_read{,_3d,_4d,_nd}_image_TYPE{,_f,_m}(...); 86 | // TYPE **iio_read{,_3d,_4d,_nd}_image_TYPE_matrix{,_f,_m}(...); 87 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_2vec{,_f,_m}(...))[2]; 88 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_3vec{,_f,_m}(...))[3]; 89 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_4vec{,_f,_m}(...))[4]; 90 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_rgb{,_f,_m}(...))[3]; 91 | // TYPE (**iio_read{,_3d,_4d,_nd}_image_TYPE_matrix_rgba{,_f,_m}(...))[4]; 92 | // 93 | // 94 | double *iio_read_image_double(const char *fname, int *w, int *h); 95 | double *iio_read_image_double_vec(const char *fname, int *w, int *h, int *pd); 96 | double *iio_read_image_double_split(const char *fname, int *w, int *h, int *pd); 97 | 98 | 99 | // All these functions are boring variations, and they are defined at the 100 | // end of this file. More interesting are the two following general 101 | // functions: 102 | 103 | void *iio_read_image_numbers_as_they_are_stored(char *fname, int *w, int *h, 104 | int *samples_per_pixel, int *sample_size, 105 | bool *ieeefp_samples, bool *signed_samples); 106 | 107 | void *iio_read_image_numbers_in_requested_format(char *fname, int *w, int *h, 108 | int *samples_per_pixel, int requested_sample_size, 109 | bool requested_ieeefp, bool requested_sign); 110 | 111 | // These two general functions have the usual versions for nD images and 112 | // streams. There exist also the following truly general functions, that 113 | // read images of any dimension: 114 | 115 | void *iio_read_nd_image_as_stored(char *fname, 116 | int *dimension, int *sizes, 117 | int *samples_per_pixel, int *sample_size, 118 | bool *ieeefp_samples, bool *signed_samples); 119 | 120 | void *iio_read_nd_image_as_desired(char *fname, 121 | int *dimension, int *sizes, 122 | int *samples_per_pixel, int desired_sample_size, 123 | bool desired_ieeefp_samples, bool desired_signed_samples); 124 | 125 | 126 | 127 | 128 | 129 | 130 | #ifdef UINT8_MAX 131 | 132 | // basic byte API (returns a freeable pointer) 133 | // 134 | 135 | uint8_t *iio_read_image_uint8(const char *fname, int *w, int *h); 136 | // x[i+j*w] 137 | 138 | uint8_t *iio_read_image_uint8_vec(const char *fname, int *w, int *h, int *nc); 139 | // x[(i + j*w)*nc + l] 140 | 141 | uint8_t (*iio_read_image_uint8_rgb(const char *fnam, int *w, int *h))[3]; 142 | // x[(i + j*w)*3 + l] 143 | 144 | 145 | // 146 | // convenience float API (also returns a freeable pointer) 147 | // 148 | 149 | uint8_t **iio_read_image_uint8_matrix(const char *fname, int *w, int *h); 150 | // x[j][i] 151 | 152 | uint8_t (**iio_read_image_uint8_matrix_2vec(const char *fnam, int *w, int *h))[2]; 153 | uint8_t (**iio_read_image_uint8_matrix_3vec(const char *fnam, int *w, int *h))[3]; 154 | uint8_t (**iio_read_image_uint8_matrix_4vec(const char *fnam, int *w, int *h))[4]; 155 | uint8_t (**iio_read_image_uint8_matrix_rgb(const char *fnam, int *w, int *h))[3]; 156 | uint8_t (**iio_read_image_uint8_matrix_rgba(const char *fnam, int *w, int *h))[4]; 157 | // x[j][i][channel] 158 | // (The "rgb" and "rgba" functions may re-order the channels according to file 159 | // metadata. The "vec" functions produce the data in the same order as is 160 | // stored.) 161 | uint8_t ***iio_read_image_uint8_matrix_vec(const char *fnam, int *w, int *h, int *pd); 162 | 163 | #endif//UINT8_MAX 164 | 165 | #ifdef UINT16_MAX 166 | uint16_t *iio_read_image_uint16_vec(const char *fname, int *w, int *h, int *pd); 167 | #endif//UINT16_MAX 168 | 169 | 170 | // functions for writing images, with the same conventions as for reding 171 | void iio_write_image_float_vec (char*, float* , int, int, int); 172 | void iio_write_image_float_split (char*, float* , int, int, int); 173 | void iio_write_image_double_vec (char*, double* , int, int, int); 174 | void iio_write_image_double_split (char*, double* , int, int, int); 175 | void iio_write_image_float (char*, float* , int, int ); 176 | void iio_write_image_double (char*, double* , int, int ); 177 | void iio_write_image_int (char*, int* , int, int ); 178 | void iio_write_image_int_vec (char*, int* , int, int, int); 179 | void iio_write_image_uint8_vec (char*, uint8_t* , int, int, int); 180 | void iio_write_image_uint8_split (char*, uint8_t* , int, int, int); 181 | void iio_write_image_uint16_vec (char*, uint16_t* , int, int, int); 182 | void iio_write_image_uint8_matrix_rgb(char*, uint8_t(**)[3], int, int ); 183 | void iio_write_image_uint8_matrix (char*, uint8_t** , int, int ); 184 | 185 | 186 | #define IIO_USE_INCONSISTENT_NAMES 187 | #ifdef IIO_USE_INCONSISTENT_NAMES 188 | // functions for writing images, with the same conventions as for reding 189 | // (note: these functions use the wording "save" instead of "write") 190 | void iio_save_image_float_vec(char *filename, float *x, int w, int h, int pd); 191 | void iio_save_image_float_split(char *filename, float *x, int w, int h, int pd); 192 | void iio_save_image_double_vec(char *filename, double *x, int w, int h, int pd); 193 | void iio_save_image_float(char *filename, float *x, int w, int h); 194 | void iio_save_image_double(char *filename, double *x, int w, int h); 195 | void iio_save_image_int(char *filename, int *x, int w, int h); 196 | void iio_save_image_int_vec(char *filename, int *x, int w, int h, int pd); 197 | void iio_save_image_uint8_vec(char *filename, uint8_t *x, int w, int h, int pd); 198 | void iio_save_image_uint16_vec(char *filename, uint16_t *x, int w, int h, int pd); 199 | void iio_save_image_uint8_matrix_rgb(char *f, unsigned char (**x)[3], int w, int h); 200 | void iio_save_image_uint8_matrix(char *f, unsigned char **x, int w, int h); 201 | #endif//IIO_USE_INCONSISTENT_NAMES 202 | 203 | // SAVING FORMATS: 204 | // (w, h; 1 uint8) => pgm, png, tiff, pfm 205 | // (w, h; 3 uint8) => ppm, png, tiff, pfm 206 | // (w, h; 1 uint16) => pgm, png, tiff, pfm 207 | // (w, h; 3 uint16) => ppm, png, tiff, pfm 208 | // (w, h; 1 float) => tiff, pfm 209 | // (w, h; 3 float) => tiff, pfm 210 | 211 | 212 | #endif//IIO_H 213 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/inverse_compositional_algorithm.h: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #ifndef INVERSE_COMPOSITIONAL_ALGORITHM 11 | #define INVERSE_COMPOSITIONAL_ALGORITHM 12 | 13 | /** 14 | * 15 | * This code implements the 'modified inverse compositional algorithm'. 16 | * 17 | * The 'inverse compositional algorithm' was proposed in 18 | * [1] S. Baker, and I. Matthews. (2004). Lucas-kanade 20 years on: A 19 | * unifying framework. International Journal of Computer Vision, 20 | * 56(3), 221-255. 21 | * [2] S. Baker, R. Gross, I. Matthews, and T. Ishikawa. (2004). 22 | * Lucas-kanade 20 years on: A unifying framework: Part 2. 23 | * International Journal of Computer Vision, 56(3), 221-255. 24 | * 25 | * This implementation is for color images. It calculates the global 26 | * transform between two images. It uses robust error functions and a 27 | * coarse-to-fine strategy for computing large displacements 28 | * 29 | **/ 30 | 31 | #define QUADRATIC 0 32 | #define TRUNCATED_QUADRATIC 1 33 | #define GEMAN_MCCLURE 2 34 | #define LORENTZIAN 3 35 | #define CHARBONNIER 4 36 | 37 | #define MAX_ITER 30 38 | #define LAMBDA_0 80 39 | #define LAMBDA_N 5 40 | #define LAMBDA_RATIO 0.90 41 | 42 | #define PRECOMPUTATION_GTG //comment to remove the precomputation of GTG 43 | 44 | /** 45 | * 46 | * Derivative of robust error functions 47 | * 48 | */ 49 | double rhop( 50 | double t2, //squared difference of both images 51 | double sigma, //robust threshold 52 | int type //choice of the robust error function 53 | ); 54 | 55 | /** 56 | * 57 | * Inverse compositional algorithm 58 | * Quadratic version - L2 norm 59 | * 60 | * 61 | **/ 62 | void inverse_compositional_algorithm( 63 | double *I1, //first image 64 | double *I2, //second image 65 | double *p, //parameters of the transform (output) 66 | int nparams, //number of parameters of the transform 67 | int nx, //number of columns of the image 68 | int ny, //number of rows of the image 69 | int nz, //number of channels of the images 70 | double TOL, //tolerance used for the convergence in the iterations 71 | int nanifoutside, //parameter for discarding boundary pixels 72 | int delta, //distance to the boundary 73 | int type_gradient, //type of gradient 74 | int verbose=0 //enable verbose mode 75 | ); 76 | 77 | /** 78 | * 79 | * Inverse compositional algorithm 80 | * Version with robust error functions 81 | * 82 | **/ 83 | void robust_inverse_compositional_algorithm( 84 | double *I1, //first image 85 | double *I2, //second image 86 | double *p, //parameters of the transform (output) 87 | int nparams, //number of parameters of the transform 88 | int nx, //number of columns of the image 89 | int ny, //number of rows of the image 90 | int nz, //number of channels of the images 91 | double TOL, //Tolerance used for the convergence in the iterations 92 | int robust, //robust error function 93 | double lambda, //parameter of robust error function 94 | int nanifoutside, //parameter for discarding boundary pixels 95 | int delta, //distance to the boundary 96 | int type_gradient, //type of gradient 97 | int verbose=0 //enable verbose mode 98 | ); 99 | 100 | /** 101 | * 102 | * Multiscale approach for computing the optical flow 103 | * 104 | **/ 105 | void pyramidal_inverse_compositional_algorithm( 106 | double *I1, //first image 107 | double *I2, //second image 108 | double *p, //parameters of the transform 109 | int nparams, //number of parameters 110 | int nxx, //image width 111 | int nyy, //image height 112 | int nzz, //number of color channels in image 113 | int nscales, //number of scales 114 | double nu, //downsampling factor 115 | double TOL, //stopping criterion threshold 116 | int robust, //robust error function 117 | double lambda, //parameter of robust error function 118 | int first_scale, //number of the first scale 119 | int nanifoutside, //parameter for discarding boundary pixels 120 | int delta, //distance to the boundary 121 | int type_gradient, //type of gradient 122 | bool verbose //switch on messages 123 | ); 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/mask.h: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #ifndef MASK_H 12 | #define MASK_H 13 | 14 | /** 15 | * 16 | * Compute the gradient with central differences 17 | * 18 | */ 19 | void gradient( 20 | double *input, //input image 21 | double *dx, //computed x derivative 22 | double *dy, //computed y derivative 23 | int nx, //image width 24 | int ny, //image height 25 | int nz //number of color channels in the image 26 | ); 27 | 28 | /** 29 | * 30 | * Compute the gradient estimator 31 | * dx = d * k^t * I 32 | * dy = k * d^t * I 33 | * where * denotes the convolution operator 34 | * 35 | */ 36 | void gradient_robust (double *input, //input image 37 | double *dx, //computed x derivative 38 | double *dy, //computed y derivative 39 | int nx, //image width 40 | int ny, //image height 41 | int nz, //number of color channels in the image 42 | int gradientType //type of gradient 43 | ); 44 | 45 | /** 46 | * 47 | * Prefiltering of an image compatible with the gradient 48 | * I <-- k * k^t * I 49 | * where * denotes the convolution operator 50 | * 51 | */ 52 | void prefiltering_robust ( 53 | double *I, //input/output image 54 | int nx, //image width 55 | int ny, //image height 56 | int nz, //number of color channels in the image 57 | int gradientType //type of gradient 58 | ); 59 | 60 | /** 61 | * 62 | * Convolution with a Gaussian kernel 63 | * 64 | */ 65 | void gaussian ( 66 | double *I, //input/output image 67 | int xdim, //image width 68 | int ydim, //image height 69 | int zdim, //number of color channels in the image 70 | double sigma, //Gaussian sigma 71 | int bc = 1, //boundary condition 72 | int precision = 5 //defines the size of the window 73 | ); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/matrix.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #include "matrix.h" 11 | #include 12 | 13 | //Multiplication of a square matrix and a vector 14 | void Axb(double *A, double *b, double *p, int n) 15 | { 16 | for(int i=0; imax){ 111 | i_max=j; max=fabs(PASO[j*2*N+i]); 112 | } 113 | } 114 | 115 | if(max<10e-30){ 116 | delete []PASO; 117 | return -1; 118 | } 119 | if(i_max>i){ 120 | for(k=0;k<2*N;k++){ 121 | paso=PASO[i*2*N+k]; 122 | PASO[i*2*N+k]=PASO[i_max*2*N+k]; 123 | PASO[i_max*2*N+k]=paso; 124 | } 125 | } 126 | 127 | for(j=i+1;j0;i--){ 139 | for(j=i-1;j>=0;j--){ 140 | mul=-PASO[j*2*N+i]/PASO[i*2*N+i]; 141 | for(k=i;k<2*N;k++) PASO[j*2*N+k]+=mul*PASO[i*2*N+k]; 142 | } 143 | } 144 | for(i=0;i. 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #ifndef MATRIX_H 11 | #define MATRIX_H 12 | 13 | //Multiplication of a square matrix and a vector 14 | void Axb(double *A, double *b, double *p, int n); 15 | 16 | //Multiplication of the transpose of a matrix and a vector 17 | //p should be initialized to zero outside 18 | void Atb(double *A, double *b, double *p, int n, int m); 19 | 20 | //Multiplication of the transpose of a matrix, a vector and a scalar 21 | //p should be initialized to zero outside 22 | void sAtb(double s, double *A, double *b, double *p, int n, int m); 23 | 24 | //Multiplication of the transpose of a matrix and itself 25 | //B should be initialized to zero outside 26 | void AtA(double *A, double *B, int n, int m); 27 | 28 | //Multiplication of the transpose of a matrix and itself with a scalar 29 | //B should be initialized to zero outside 30 | void sAtA(double s, double *A, double *B, int n, int m); 31 | 32 | //Multiplication with a scalar 33 | //B should be initialized to zero outside 34 | void sA(double s, double *A, double *B, int m); 35 | 36 | //Function to compute the inverse of a matrix 37 | //through Gaussian elimination 38 | int inverse(double *A, double *A_1, int N = 3); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/mt19937ar.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. The names of its contributors may not be used to endorse or promote 17 | * products derived from this software without specific prior written 18 | * permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | 36 | /* Period parameters */ 37 | #define MT_N 624 38 | #define MT_M 397 39 | #define MT_MATRIX_A 0x9908b0dfUL /**< constant vector a */ 40 | #define MT_UPPER_MASK 0x80000000UL /**< most significant w-r bits */ 41 | #define MT_LOWER_MASK 0x7fffffffUL /**< least significant r bits */ 42 | 43 | static unsigned long mt[MT_N]; /**< the array for the state vector */ 44 | static int mti = MT_N + 1; /**< mti==MT_N+1 means mt[MT_N] 45 | * is not initialized */ 46 | 47 | /** 48 | * initializes mt[MT_N] with a seed 49 | */ 50 | static void init_genrand(unsigned long s) { 51 | mt[0] = s & 0xffffffffUL; 52 | for (mti = 1; mti < MT_N; mti++) { 53 | mt[mti] = (1812433253UL * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti); 54 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 55 | /* In the previous versions, MSBs of the seed affect */ 56 | /* only MSBs of the array mt[]. */ 57 | /* 2002/01/09 modified by Makoto Matsumoto */ 58 | mt[mti] &= 0xffffffffUL; 59 | /* for >32 bit machines */ 60 | } 61 | } 62 | 63 | /** 64 | * generates a random number on [0,0xffffffff]-interval 65 | */ 66 | static unsigned long genrand_int32(void) { 67 | unsigned long y; 68 | static unsigned long mag01[2] = { 0x0UL, MT_MATRIX_A }; 69 | /* mag01[x] = x * MT_MATRIX_A for x=0,1 */ 70 | 71 | if (mti >= MT_N) { /* generate MT_N words at one time */ 72 | int kk; 73 | 74 | if (mti == MT_N + 1) /* if init_genrand() has not been called, */ 75 | init_genrand(5489UL); /* a default initial seed is used */ 76 | 77 | for (kk = 0; kk < MT_N - MT_M; kk++) { 78 | y = (mt[kk] & MT_UPPER_MASK) | (mt[kk + 1] & MT_LOWER_MASK); 79 | mt[kk] = mt[kk + MT_M] ^ (y >> 1) ^ mag01[y & 0x1UL]; 80 | } 81 | for (; kk < MT_N - 1; kk++) { 82 | y = (mt[kk] & MT_UPPER_MASK) | (mt[kk + 1] & MT_LOWER_MASK); 83 | mt[kk] = mt[kk + (MT_M - MT_N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; 84 | } 85 | y = (mt[MT_N - 1] & MT_UPPER_MASK) | (mt[0] & MT_LOWER_MASK); 86 | mt[MT_N - 1] = mt[MT_M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL]; 87 | 88 | mti = 0; 89 | } 90 | 91 | y = mt[mti++]; 92 | 93 | /* Tempering */ 94 | y ^= (y >> 11); 95 | y ^= (y << 7) & 0x9d2c5680UL; 96 | y ^= (y << 15) & 0xefc60000UL; 97 | y ^= (y >> 18); 98 | 99 | return y; 100 | } 101 | 102 | /** 103 | * generates a random number on [0,1) with 53-bit resolution 104 | */ 105 | static double genrand_res53(void) { 106 | unsigned long a = genrand_int32() >> 5, b = genrand_int32() >> 6; 107 | return (1.0 * a * 67108864.0 + b) * (1.0 / 9007199254740992.0); 108 | } 109 | 110 | #undef MT_N 111 | #undef MT_M 112 | #undef MT_MATRIX_A 113 | #undef MT_UPPER_MASK 114 | #undef MT_LOWER_MASK 115 | 116 | /* 117 | * non-static original content 118 | */ 119 | 120 | /** @file mt19937ar.c 121 | * @brief Mersenne Twister pseudo-RNG code 122 | * 123 | * This is the original code by Takuji Nishimura and Makoto Matsumoto, 124 | * amended to keep only the parts used. 125 | * Source : http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html 126 | * 127 | * @author Makoto Matsumoto (1997 - 2002) 128 | * @author Takuji Nishimura (1997 - 2002) 129 | * 130 | */ 131 | 132 | /* ensure consistency */ 133 | #include "mt19937ar.h" 134 | 135 | /* string tag inserted into the binary, helps tracking versions */ 136 | char _mt19937ar_tag[] = "using mt19937ar " MT19937AR_VERSION; 137 | 138 | /** 139 | * @brief initializes the generator with a seed 140 | */ 141 | void mt_init_genrand(unsigned long s) { 142 | init_genrand(s); 143 | return; 144 | } 145 | 146 | /** 147 | * @brief generates a random number on [0,1) with 53-bit resolution 148 | */ 149 | double mt_genrand_res53(void) { 150 | return genrand_res53(); 151 | } 152 | 153 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/mt19937ar.h: -------------------------------------------------------------------------------- 1 | #ifndef _MT19937AR_H 2 | #define _MT19937AR_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define MT19937AR_VERSION "0.20100917" 9 | 10 | void mt_init_genrand(unsigned long s); 11 | double mt_genrand_res53(void); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif /* !_MT19937AR_H */ 18 | 19 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/noise.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "mt19937ar.h" 17 | #include "file.h" 18 | 19 | // function to add Gaussian White noise of std sigma 20 | void add_noise(double *u, double *v, double sigma, int size) { 21 | //random seed initialization using the time 22 | mt_init_genrand((unsigned long int) time (NULL) + (unsigned long int) getpid()); 23 | 24 | //add noise pixel by pixel 25 | for (int i=0; i< size; i++) 26 | { 27 | double a=mt_genrand_res53(); 28 | double b=mt_genrand_res53(); 29 | double z = (sigma)*sqrt(-2.0*log(a))*cos(2.0*M_PI*b); 30 | 31 | v[i] = u[i] + z; 32 | } 33 | } 34 | 35 | //main function for adding noise to an image 36 | int main (int argc, char *argv[]) 37 | { 38 | //read parameters 39 | if(argc<4) 40 | printf("\n\n: %s input_image output_image sigma\n\n", argv[0]); 41 | else 42 | { 43 | //read the parameters from console 44 | char *image1=argv[1], *image2=argv[2]; 45 | int nx, ny, nz; 46 | double *I; 47 | double sigma=atof(argv[3]); 48 | 49 | if(read_image(image1, &I, nx, ny, nz)) 50 | { 51 | double *F=new double[nx*ny*nz]; 52 | 53 | //only add noise if necessary 54 | if(sigma>0) 55 | { 56 | add_noise(I, F, sigma, nx*ny*nz); 57 | save_image(image2, F, nx, ny, nz); 58 | } 59 | else 60 | save_image(image2, I, nx, ny, nz); 61 | 62 | free(I); 63 | delete []F; 64 | } 65 | else 66 | printf("Cannot read the image\n"); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/output.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "bicubic_interpolation.h" 15 | #include "file.h" 16 | #include "inverse_compositional_algorithm.h" 17 | #include "transformation.h" 18 | 19 | /********************************************************************* 20 | * NOTE: * 21 | * This file generates some information for the online demo in IPOL * 22 | * It can be removed for using the program outside the demo system * 23 | * * 24 | *********************************************************************/ 25 | 26 | /** 27 | * 28 | * Function to project a point with two transformations and 29 | * compute the distance between them 30 | * 31 | */ 32 | double distance( 33 | double *m1, //first transformation 34 | double *m2, //second transformation 35 | double x, //x point coordinate 36 | double y //y point coordinate 37 | ) 38 | { 39 | double x1=99999,y1=99999,z1=m1[6]*x+m1[7]*y+1; 40 | double x2=99999,y2=99999,z2=m2[6]*x+m2[7]*y+1; 41 | if(z1*z1>1E-10 && z2*z2>1E-10) 42 | { 43 | x1=(m1[0]*x+m1[1]*y+m1[2])/z1; 44 | y1=(m1[3]*x+m1[4]*y+m1[5])/z1; 45 | x2=(m2[0]*x+m2[1]*y+m2[2])/z2; 46 | y2=(m2[3]*x+m2[4]*y+m2[5])/z2; 47 | } 48 | double d=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); 49 | return sqrt(d); 50 | } 51 | 52 | /** 53 | * 54 | * Function to write some output information for the demo 55 | * 56 | */ 57 | void print_output( 58 | double *I1, //first image 59 | double *I2, //second image 60 | double *p, //parametric model 61 | double *p2, //parametric model 62 | int nparams, //number of parameters 63 | int nparams2,//number of parameters 64 | int nx, //number of columns 65 | int ny, //number of rows 66 | int nz //number of channels 67 | ) 68 | { 69 | double *Iw=new double[nx*ny*nz]; 70 | double *DI=new double[nx*ny*nz]; 71 | double *DIrmse= new double[nx*ny]; 72 | double *EPE=new double[nx*ny]; 73 | 74 | //compute the interpolated image I2(x') 75 | bicubic_interpolation(I2, Iw, p, nparams, nx, ny, nz, 0, 1); 76 | char outfile[50]="output_estimated.tiff"; 77 | save_image(outfile, Iw, nx, ny, nz); 78 | char outfile2[50]="output_estimated.png"; 79 | save_image(outfile2, Iw, nx, ny, nz); 80 | 81 | //compute the difference image I2(x') - I1(x) and the RMSE 82 | double sum=0.0, rmse=9999; 83 | int size = 0; 84 | for (int i=0; i 0) 92 | rmse = sqrt(sum/size); 93 | printf("RMSE(I1(x),I2(x'))=%lf\n",rmse); 94 | char diff_image[50]="diff_image.tiff"; 95 | save_image(diff_image, DI, nx, ny, nz); 96 | char diff_image2[50]="diff_image.png"; 97 | save_normalize_image(diff_image2, DI, nx, ny, nz); 98 | 99 | //compute the pointwise rmse of the difference image 100 | for(int p=0; p 5) { 152 | printf(": %s image1 image2 transform1 [transform2]\n", v[0]); 153 | return(EXIT_FAILURE); 154 | } 155 | 156 | int nx, ny, nz, nx1, ny1, nz1; 157 | 158 | char *image1= v[1]; 159 | char *image2= v[2]; 160 | const char *transform1= v[3]; 161 | const char *transform2= c > 4 ? v[4] : "-"; 162 | 163 | //read the input images 164 | double *I1, *I2; 165 | bool correct1=read_image(image1, &I1, nx, ny, nz); 166 | bool correct2=read_image(image2, &I2, nx1, ny1, nz1); 167 | 168 | if ( ! (correct1 && correct2 && nx == nx1 && ny == ny1 && nz == nz1) ) 169 | { 170 | printf("Images should have the same size\n"); 171 | return(EXIT_FAILURE); 172 | } 173 | 174 | int n1 = 0, n2 = 0; 175 | double *p1=NULL, *p2=NULL; 176 | read(transform1, &p1, n1); 177 | read(transform2, &p2, n2); 178 | 179 | print_output(I1, I2, p1, p2, n1, n2, nx, ny, nz); 180 | 181 | //free memory 182 | free (I1); 183 | free (I2); 184 | delete []p1; 185 | delete []p2; 186 | 187 | return(EXIT_SUCCESS); 188 | } 189 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/transform.mat: -------------------------------------------------------------------------------- 1 | 2.0891988965679 -0.13301130709075 -28.718667831462 1.0963238092487 1.2663314103607 -69.765614552706 0.0049537540605594 -0.0014796566351459 1 2 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/transformation.h: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #ifndef TRANSFORMATION_H 11 | #define TRANSFORMATION_H 12 | 13 | //types of transformations 14 | #define TRANSLATION_TRANSFORM 2 15 | #define EUCLIDEAN_TRANSFORM 3 16 | #define SIMILARITY_TRANSFORM 4 17 | #define AFFINITY_TRANSFORM 6 18 | #define HOMOGRAPHY_TRANSFORM 8 19 | 20 | /** 21 | * 22 | * Function to compute the Jacobian matrix 23 | * These parametrizations of the Jacobian are taken from the book of Zselinski 24 | * (chapter 6 and 9) 25 | * 26 | */ 27 | void jacobian 28 | ( 29 | double *J, //computed Jacobian 30 | int nparams, //number of parameters 31 | int nx, //number of columns of the image 32 | int ny //number of rows of the image 33 | ); 34 | 35 | /** 36 | * 37 | * Function to update the current transform with the computed increment 38 | * x'(x;p) = x'(x;p) o x'(x;dp)^-1 39 | * 40 | */ 41 | void update_transform 42 | ( 43 | double *p, //output accumulated transform 44 | double *dp, //computed increment 45 | int nparams //number of parameters 46 | ); 47 | 48 | /** 49 | * 50 | * Function to transform a 2D point (x,y) through a parametric model 51 | * 52 | */ 53 | void project 54 | ( 55 | int x, //x component of the 2D point 56 | int y, //y component of the 2D point 57 | double *p, //parameters of the transformation 58 | double &xp, //x component of the transformed point 59 | double &yp, //y component of the transformed point 60 | int nparams //number of parameters 61 | ); 62 | 63 | /** 64 | * 65 | * Function to convert a parametric model to its matrix representation 66 | * 67 | */ 68 | void params2matrix 69 | ( 70 | double *p, //input parametric model 71 | double *matrix, //output matrix 72 | int nparams //number of parameters 73 | ); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/zoom.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #include 12 | #include 13 | 14 | #include "zoom.h" 15 | #include "mask.h" 16 | #include "bicubic_interpolation.h" 17 | #include "transformation.h" 18 | 19 | #define ZOOM_SIGMA_ZERO 0.6 20 | 21 | /** 22 | * 23 | * Compute the size of a zoomed image from the zoom factor 24 | * 25 | **/ 26 | void zoom_size 27 | ( 28 | int nx, //width of the orignal image 29 | int ny, //height of the orignal image 30 | int &nxx, //width of the zoomed image 31 | int &nyy, //height of the zoomed image 32 | double factor //zoom factor between 0 and 1 33 | ) 34 | { 35 | nxx = (int) ((double) nx * factor + 0.5); 36 | nyy = (int) ((double) ny * factor + 0.5); 37 | } 38 | 39 | /** 40 | * 41 | * Function to downsample the image 42 | * 43 | **/ 44 | void zoom_out 45 | ( 46 | double *I, //input image 47 | double *Iout, //output image 48 | int nx, //image width 49 | int ny, //image height 50 | int nz, // number of color channels in image 51 | double factor //zoom factor between 0 and 1 52 | ) 53 | { 54 | int nxx, nyy, original_size =nx*ny*nz; 55 | double ifactor = 1.0/factor; 56 | double *Is=new double[original_size]; 57 | 58 | for (int i=0; ifactory)?factorx:factory; 116 | 117 | switch(nparams) { 118 | default: case TRANSLATION_TRANSFORM: //p=(tx, ty) 119 | pout[0]=p[0]*nu; 120 | pout[1]=p[1]*nu; 121 | break; 122 | case EUCLIDEAN_TRANSFORM: //p=(tx, ty, tita) 123 | pout[0]=p[0]*nu; 124 | pout[1]=p[1]*nu; 125 | pout[2]=p[2]; 126 | break; 127 | case SIMILARITY_TRANSFORM: //p=(tx, ty, a, b) 128 | pout[0]=p[0]*nu; 129 | pout[1]=p[1]*nu; 130 | pout[2]=p[2]; 131 | pout[3]=p[3]; 132 | break; 133 | case AFFINITY_TRANSFORM: //p=(tx, ty, a00, a01, a10, a11) 134 | pout[0]=p[0]*nu; 135 | pout[1]=p[1]*nu; 136 | pout[2]=p[2]; 137 | pout[3]=p[3]; 138 | pout[4]=p[4]; 139 | pout[5]=p[5]; 140 | break; 141 | case HOMOGRAPHY_TRANSFORM: //p=(h00, h01,..., h21) 142 | pout[0]=p[0]; 143 | pout[1]=p[1]; 144 | pout[2]=p[2]*nu; 145 | pout[3]=p[3]; 146 | pout[4]=p[4]; 147 | pout[5]=p[5]*nu; 148 | pout[6]=p[6]/nu; 149 | pout[7]=p[7]/nu; 150 | break; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /mInverseCompositional_1.00/zoom.h: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #ifndef ZOOM_H 12 | #define ZOOM_H 13 | 14 | /** 15 | * 16 | * Compute the size of a zoomed image from the zoom factor 17 | * 18 | **/ 19 | void zoom_size 20 | ( 21 | int nx, //width of the orignal image 22 | int ny, //height of the orignal image 23 | int &nxx, //width of the zoomed image 24 | int &nyy, //height of the zoomed image 25 | double factor = 0.5 //zoom factor between 0 and 1 26 | ); 27 | 28 | /** 29 | * 30 | * Function to downsample the image 31 | * 32 | **/ 33 | void zoom_out 34 | ( 35 | double *I, //input image 36 | double *Iout, //output image 37 | int nx, //image width 38 | int ny, //image height 39 | int nz, // number of color channels in image 40 | double factor = 0.5 //zoom factor between 0 and 1 41 | ); 42 | 43 | /** 44 | * 45 | * Function to upsample the parameters of the transformation 46 | * 47 | **/ 48 | void zoom_in_parameters 49 | ( 50 | double *p, //input image 51 | double *pout, //output image 52 | int nparams, //number of parameters 53 | int nx, //width of the original image 54 | int ny, //height of the original image 55 | int nxx, //width of the zoomed image 56 | int nyy //height of the zoomed image 57 | ); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /mask.h: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #ifndef MASK_H 12 | #define MASK_H 13 | 14 | /** 15 | * 16 | * Compute the gradient with central differences 17 | * 18 | */ 19 | void gradient( 20 | double *input, //input image 21 | double *dx, //computed x derivative 22 | double *dy, //computed y derivative 23 | int nx, //image width 24 | int ny, //image height 25 | int nz //number of color channels in the image 26 | ); 27 | 28 | /** 29 | * 30 | * Compute the gradient estimator 31 | * dx = d * k^t * I 32 | * dy = k * d^t * I 33 | * where * denotes the convolution operator 34 | * 35 | */ 36 | void gradient_robust (double *input, //input image 37 | double *dx, //computed x derivative 38 | double *dy, //computed y derivative 39 | int nx, //image width 40 | int ny, //image height 41 | int nz, //number of color channels in the image 42 | int gradientType //type of gradient 43 | ); 44 | 45 | /** 46 | * 47 | * Prefiltering of an image compatible with the gradient 48 | * I <-- k * k^t * I 49 | * where * denotes the convolution operator 50 | * 51 | */ 52 | void prefiltering_robust ( 53 | double *I, //input/output image 54 | int nx, //image width 55 | int ny, //image height 56 | int nz, //number of color channels in the image 57 | int gradientType //type of gradient 58 | ); 59 | 60 | /** 61 | * 62 | * Convolution with a Gaussian kernel 63 | * 64 | */ 65 | void gaussian ( 66 | double *I, //input/output image 67 | int xdim, //image width 68 | int ydim, //image height 69 | int zdim, //number of color channels in the image 70 | double sigma, //Gaussian sigma 71 | int bc = 1, //boundary condition 72 | int precision = 5 //defines the size of the window 73 | ); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /matrix.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #include "matrix.h" 11 | #include 12 | 13 | //Multiplication of a square matrix and a vector 14 | void Axb(double *A, double *b, double *p, int n) 15 | { 16 | for(int i=0; imax){ 111 | i_max=j; max=fabs(PASO[j*2*N+i]); 112 | } 113 | } 114 | 115 | if(max<10e-30){ 116 | delete []PASO; 117 | return -1; 118 | } 119 | if(i_max>i){ 120 | for(k=0;k<2*N;k++){ 121 | paso=PASO[i*2*N+k]; 122 | PASO[i*2*N+k]=PASO[i_max*2*N+k]; 123 | PASO[i_max*2*N+k]=paso; 124 | } 125 | } 126 | 127 | for(j=i+1;j0;i--){ 139 | for(j=i-1;j>=0;j--){ 140 | mul=-PASO[j*2*N+i]/PASO[i*2*N+i]; 141 | for(k=i;k<2*N;k++) PASO[j*2*N+k]+=mul*PASO[i*2*N+k]; 142 | } 143 | } 144 | for(i=0;i. 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #ifndef MATRIX_H 11 | #define MATRIX_H 12 | 13 | //Multiplication of a square matrix and a vector 14 | void Axb(double *A, double *b, double *p, int n); 15 | 16 | //Multiplication of the transpose of a matrix and a vector 17 | //p should be initialized to zero outside 18 | void Atb(double *A, double *b, double *p, int n, int m); 19 | 20 | //Multiplication of the transpose of a matrix, a vector and a scalar 21 | //p should be initialized to zero outside 22 | void sAtb(double s, double *A, double *b, double *p, int n, int m); 23 | 24 | //Multiplication of the transpose of a matrix and itself 25 | //B should be initialized to zero outside 26 | void AtA(double *A, double *B, int n, int m); 27 | 28 | //Multiplication of the transpose of a matrix and itself with a scalar 29 | //B should be initialized to zero outside 30 | void sAtA(double s, double *A, double *B, int n, int m); 31 | 32 | //Multiplication with a scalar 33 | //B should be initialized to zero outside 34 | void sA(double s, double *A, double *B, int m); 35 | 36 | //Function to compute the inverse of a matrix 37 | //through Gaussian elimination 38 | int inverse(double *A, double *A_1, int N = 3); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /mt19937ar.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. The names of its contributors may not be used to endorse or promote 17 | * products derived from this software without specific prior written 18 | * permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | 36 | /* Period parameters */ 37 | #define MT_N 624 38 | #define MT_M 397 39 | #define MT_MATRIX_A 0x9908b0dfUL /**< constant vector a */ 40 | #define MT_UPPER_MASK 0x80000000UL /**< most significant w-r bits */ 41 | #define MT_LOWER_MASK 0x7fffffffUL /**< least significant r bits */ 42 | 43 | static unsigned long mt[MT_N]; /**< the array for the state vector */ 44 | static int mti = MT_N + 1; /**< mti==MT_N+1 means mt[MT_N] 45 | * is not initialized */ 46 | 47 | /** 48 | * initializes mt[MT_N] with a seed 49 | */ 50 | static void init_genrand(unsigned long s) { 51 | mt[0] = s & 0xffffffffUL; 52 | for (mti = 1; mti < MT_N; mti++) { 53 | mt[mti] = (1812433253UL * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti); 54 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 55 | /* In the previous versions, MSBs of the seed affect */ 56 | /* only MSBs of the array mt[]. */ 57 | /* 2002/01/09 modified by Makoto Matsumoto */ 58 | mt[mti] &= 0xffffffffUL; 59 | /* for >32 bit machines */ 60 | } 61 | } 62 | 63 | /** 64 | * generates a random number on [0,0xffffffff]-interval 65 | */ 66 | static unsigned long genrand_int32(void) { 67 | unsigned long y; 68 | static unsigned long mag01[2] = { 0x0UL, MT_MATRIX_A }; 69 | /* mag01[x] = x * MT_MATRIX_A for x=0,1 */ 70 | 71 | if (mti >= MT_N) { /* generate MT_N words at one time */ 72 | int kk; 73 | 74 | if (mti == MT_N + 1) /* if init_genrand() has not been called, */ 75 | init_genrand(5489UL); /* a default initial seed is used */ 76 | 77 | for (kk = 0; kk < MT_N - MT_M; kk++) { 78 | y = (mt[kk] & MT_UPPER_MASK) | (mt[kk + 1] & MT_LOWER_MASK); 79 | mt[kk] = mt[kk + MT_M] ^ (y >> 1) ^ mag01[y & 0x1UL]; 80 | } 81 | for (; kk < MT_N - 1; kk++) { 82 | y = (mt[kk] & MT_UPPER_MASK) | (mt[kk + 1] & MT_LOWER_MASK); 83 | mt[kk] = mt[kk + (MT_M - MT_N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; 84 | } 85 | y = (mt[MT_N - 1] & MT_UPPER_MASK) | (mt[0] & MT_LOWER_MASK); 86 | mt[MT_N - 1] = mt[MT_M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL]; 87 | 88 | mti = 0; 89 | } 90 | 91 | y = mt[mti++]; 92 | 93 | /* Tempering */ 94 | y ^= (y >> 11); 95 | y ^= (y << 7) & 0x9d2c5680UL; 96 | y ^= (y << 15) & 0xefc60000UL; 97 | y ^= (y >> 18); 98 | 99 | return y; 100 | } 101 | 102 | /** 103 | * generates a random number on [0,1) with 53-bit resolution 104 | */ 105 | static double genrand_res53(void) { 106 | unsigned long a = genrand_int32() >> 5, b = genrand_int32() >> 6; 107 | return (1.0 * a * 67108864.0 + b) * (1.0 / 9007199254740992.0); 108 | } 109 | 110 | #undef MT_N 111 | #undef MT_M 112 | #undef MT_MATRIX_A 113 | #undef MT_UPPER_MASK 114 | #undef MT_LOWER_MASK 115 | 116 | /* 117 | * non-static original content 118 | */ 119 | 120 | /** @file mt19937ar.c 121 | * @brief Mersenne Twister pseudo-RNG code 122 | * 123 | * This is the original code by Takuji Nishimura and Makoto Matsumoto, 124 | * amended to keep only the parts used. 125 | * Source : http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html 126 | * 127 | * @author Makoto Matsumoto (1997 - 2002) 128 | * @author Takuji Nishimura (1997 - 2002) 129 | * 130 | */ 131 | 132 | /* ensure consistency */ 133 | #include "mt19937ar.h" 134 | 135 | /* string tag inserted into the binary, helps tracking versions */ 136 | char _mt19937ar_tag[] = "using mt19937ar " MT19937AR_VERSION; 137 | 138 | /** 139 | * @brief initializes the generator with a seed 140 | */ 141 | void mt_init_genrand(unsigned long s) { 142 | init_genrand(s); 143 | return; 144 | } 145 | 146 | /** 147 | * @brief generates a random number on [0,1) with 53-bit resolution 148 | */ 149 | double mt_genrand_res53(void) { 150 | return genrand_res53(); 151 | } 152 | 153 | -------------------------------------------------------------------------------- /mt19937ar.h: -------------------------------------------------------------------------------- 1 | #ifndef _MT19937AR_H 2 | #define _MT19937AR_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define MT19937AR_VERSION "0.20100917" 9 | 10 | void mt_init_genrand(unsigned long s); 11 | double mt_genrand_res53(void); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif /* !_MT19937AR_H */ 18 | 19 | -------------------------------------------------------------------------------- /noise.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "mt19937ar.h" 17 | #include "file.h" 18 | 19 | // function to add Gaussian White noise of std sigma 20 | void add_noise(double *u, double *v, double sigma, int size) { 21 | //random seed initialization using the time 22 | mt_init_genrand((unsigned long int) time (NULL) + (unsigned long int) getpid()); 23 | 24 | //add noise pixel by pixel 25 | for (int i=0; i< size; i++) 26 | { 27 | double a=mt_genrand_res53(); 28 | double b=mt_genrand_res53(); 29 | double z = (sigma)*sqrt(-2.0*log(a))*cos(2.0*M_PI*b); 30 | 31 | v[i] = u[i] + z; 32 | } 33 | } 34 | 35 | //main function for adding noise to an image 36 | int main (int argc, char *argv[]) 37 | { 38 | //read parameters 39 | if(argc<4) 40 | printf("\n\n: %s input_image output_image sigma\n\n", argv[0]); 41 | else 42 | { 43 | //read the parameters from console 44 | char *image1=argv[1], *image2=argv[2]; 45 | int nx, ny, nz; 46 | double *I; 47 | double sigma=atof(argv[3]); 48 | 49 | if(read_image(image1, &I, nx, ny, nz)) 50 | { 51 | double *F=new double[nx*ny*nz]; 52 | 53 | //only add noise if necessary 54 | if(sigma>0) 55 | { 56 | add_noise(I, F, sigma, nx*ny*nz); 57 | save_image(image2, F, nx, ny, nz); 58 | } 59 | else 60 | save_image(image2, I, nx, ny, nz); 61 | 62 | free(I); 63 | delete []F; 64 | } 65 | else 66 | printf("Cannot read the image\n"); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /output.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "bicubic_interpolation.h" 15 | #include "file.h" 16 | #include "inverse_compositional_algorithm.h" 17 | #include "transformation.h" 18 | 19 | /********************************************************************* 20 | * NOTE: * 21 | * This file generates some information for the online demo in IPOL * 22 | * It can be removed for using the program outside the demo system * 23 | * * 24 | *********************************************************************/ 25 | 26 | /** 27 | * 28 | * Function to project a point with two transformations and 29 | * compute the distance between them 30 | * 31 | */ 32 | double distance( 33 | double *m1, //first transformation 34 | double *m2, //second transformation 35 | double x, //x point coordinate 36 | double y //y point coordinate 37 | ) 38 | { 39 | double x1=99999,y1=99999,z1=m1[6]*x+m1[7]*y+1; 40 | double x2=99999,y2=99999,z2=m2[6]*x+m2[7]*y+1; 41 | if(z1*z1>1E-10 && z2*z2>1E-10) 42 | { 43 | x1=(m1[0]*x+m1[1]*y+m1[2])/z1; 44 | y1=(m1[3]*x+m1[4]*y+m1[5])/z1; 45 | x2=(m2[0]*x+m2[1]*y+m2[2])/z2; 46 | y2=(m2[3]*x+m2[4]*y+m2[5])/z2; 47 | } 48 | double d=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); 49 | return sqrt(d); 50 | } 51 | 52 | /** 53 | * 54 | * Function to write some output information for the demo 55 | * 56 | */ 57 | void print_output( 58 | double *I1, //first image 59 | double *I2, //second image 60 | double *p, //parametric model 61 | double *p2, //parametric model 62 | int nparams, //number of parameters 63 | int nparams2,//number of parameters 64 | int nx, //number of columns 65 | int ny, //number of rows 66 | int nz //number of channels 67 | ) 68 | { 69 | double *Iw=new double[nx*ny*nz]; 70 | double *DI=new double[nx*ny*nz]; 71 | double *DIrmse= new double[nx*ny]; 72 | double *EPE=new double[nx*ny]; 73 | 74 | //compute the interpolated image I2(x') 75 | bicubic_interpolation(I2, Iw, p, nparams, nx, ny, nz, 0, 1); 76 | char outfile[50]="output_estimated.tiff"; 77 | save_image(outfile, Iw, nx, ny, nz); 78 | char outfile2[50]="output_estimated.png"; 79 | save_image(outfile2, Iw, nx, ny, nz); 80 | 81 | //compute the difference image I2(x') - I1(x) and the RMSE 82 | double sum=0.0, rmse=9999; 83 | int size = 0; 84 | for (int i=0; i 0) 92 | rmse = sqrt(sum/size); 93 | printf("RMSE(I1(x),I2(x'))=%lf\n",rmse); 94 | char diff_image[50]="diff_image.tiff"; 95 | save_image(diff_image, DI, nx, ny, nz); 96 | char diff_image2[50]="diff_image.png"; 97 | save_normalize_image(diff_image2, DI, nx, ny, nz); 98 | 99 | //compute the pointwise rmse of the difference image 100 | for(int p=0; p 5) { 152 | printf(": %s image1 image2 transform1 [transform2]\n", v[0]); 153 | return(EXIT_FAILURE); 154 | } 155 | 156 | int nx, ny, nz, nx1, ny1, nz1; 157 | 158 | char *image1= v[1]; 159 | char *image2= v[2]; 160 | const char *transform1= v[3]; 161 | const char *transform2= c > 4 ? v[4] : "-"; 162 | 163 | //read the input images 164 | double *I1, *I2; 165 | bool correct1=read_image(image1, &I1, nx, ny, nz); 166 | bool correct2=read_image(image2, &I2, nx1, ny1, nz1); 167 | 168 | if ( ! (correct1 && correct2 && nx == nx1 && ny == ny1 && nz == nz1) ) 169 | { 170 | printf("Images should have the same size\n"); 171 | return(EXIT_FAILURE); 172 | } 173 | 174 | int n1 = 0, n2 = 0; 175 | double *p1=NULL, *p2=NULL; 176 | read(transform1, &p1, n1); 177 | read(transform2, &p2, n2); 178 | 179 | print_output(I1, I2, p1, p2, n1, n2, nx, ny, nz); 180 | 181 | //free memory 182 | free (I1); 183 | free (I2); 184 | delete []p1; 185 | delete []p2; 186 | 187 | return(EXIT_SUCCESS); 188 | } 189 | -------------------------------------------------------------------------------- /smapa.h: -------------------------------------------------------------------------------- 1 | 2 | // a smart parameter is just like a regular parameter, but it can be 3 | // re-defined at the shell-environment. Instead of 4 | // 5 | // #define NUMBER 42 6 | // ... 7 | // printf("%g", NUMBER); 8 | // 9 | // do 10 | // SMART_PARAMETER(NUMBER,42) 11 | // ... 12 | // printf("%g", NUMBER()); 13 | // 14 | // Notice that the environment only gets queried once, at the first use. 15 | // 16 | #define SMART_PARAMETER(n,v) static double n(void)\ 17 | {\ 18 | static bool smapa_known_ ## n = false;\ 19 | static double smapa_value_ ## n = v;\ 20 | if (!smapa_known_ ## n)\ 21 | {\ 22 | fprintf(stderr,"scanning the environment for \"%s\"... ", #n);\ 23 | int r;\ 24 | char *sv = getenv(#n);\ 25 | double y;\ 26 | if (sv)\ 27 | r = sscanf(sv, "%lf", &y);\ 28 | if (sv && r == 1)\ 29 | {\ 30 | fprintf(stderr, "got value %g\n", y);\ 31 | smapa_value_ ## n = y;\ 32 | } else {\ 33 | fprintf(stderr, "kept default value %g\n",\ 34 | smapa_value_ ## n);\ 35 | }\ 36 | smapa_known_ ## n = true;\ 37 | }\ 38 | return smapa_value_ ## n;\ 39 | } 40 | 41 | #define SMART_PARAMETER_SILENT(n,v) static double n(void)\ 42 | {\ 43 | static bool smapa_known_ ## n = false;\ 44 | static double smapa_value_ ## n = v;\ 45 | if (!smapa_known_ ## n)\ 46 | {\ 47 | int r;\ 48 | char *sv = getenv(#n);\ 49 | double y;\ 50 | if (sv)\ 51 | r = sscanf(sv, "%lf", &y);\ 52 | if (sv && r == 1)\ 53 | smapa_value_ ## n = y;\ 54 | smapa_known_ ## n = true;\ 55 | }\ 56 | return smapa_value_ ## n;\ 57 | } 58 | -------------------------------------------------------------------------------- /transformation.h: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // All rights reserved. 9 | 10 | #ifndef TRANSFORMATION_H 11 | #define TRANSFORMATION_H 12 | 13 | //types of transformations 14 | #define TRANSLATION_TRANSFORM 2 15 | #define EUCLIDEAN_TRANSFORM 3 16 | #define SIMILARITY_TRANSFORM 4 17 | #define AFFINITY_TRANSFORM 6 18 | #define HOMOGRAPHY_TRANSFORM 8 19 | 20 | /** 21 | * 22 | * Function to compute the Jacobian matrix 23 | * These parametrizations of the Jacobian are taken from the book of Zselinski 24 | * (chapter 6 and 9) 25 | * 26 | */ 27 | void jacobian 28 | ( 29 | double *J, //computed Jacobian 30 | int nparams, //number of parameters 31 | int nx, //number of columns of the image 32 | int ny //number of rows of the image 33 | ); 34 | 35 | /** 36 | * 37 | * Function to update the current transform with the computed increment 38 | * x'(x;p) = x'(x;p) o x'(x;dp)^-1 39 | * 40 | */ 41 | void update_transform 42 | ( 43 | double *p, //output accumulated transform 44 | double *dp, //computed increment 45 | int nparams //number of parameters 46 | ); 47 | 48 | /** 49 | * 50 | * Function to transform a 2D point (x,y) through a parametric model 51 | * 52 | */ 53 | void project 54 | ( 55 | int x, //x component of the 2D point 56 | int y, //y component of the 2D point 57 | double *p, //parameters of the transformation 58 | double &xp, //x component of the transformed point 59 | double &yp, //y component of the transformed point 60 | int nparams //number of parameters 61 | ); 62 | 63 | /** 64 | * 65 | * Function to convert a parametric model to its matrix representation 66 | * 67 | */ 68 | void params2matrix 69 | ( 70 | double *p, //input parametric model 71 | double *matrix, //output matrix 72 | int nparams //number of parameters 73 | ); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /zoom.cpp: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #include 12 | #include 13 | 14 | #include "zoom.h" 15 | #include "mask.h" 16 | #include "bicubic_interpolation.h" 17 | #include "transformation.h" 18 | 19 | #define ZOOM_SIGMA_ZERO 0.6 20 | 21 | /** 22 | * 23 | * Compute the size of a zoomed image from the zoom factor 24 | * 25 | **/ 26 | void zoom_size 27 | ( 28 | int nx, //width of the orignal image 29 | int ny, //height of the orignal image 30 | int &nxx, //width of the zoomed image 31 | int &nyy, //height of the zoomed image 32 | double factor //zoom factor between 0 and 1 33 | ) 34 | { 35 | nxx = (int) ((double) nx * factor + 0.5); 36 | nyy = (int) ((double) ny * factor + 0.5); 37 | } 38 | 39 | /** 40 | * 41 | * Function to downsample the image 42 | * 43 | **/ 44 | void zoom_out 45 | ( 46 | double *I, //input image 47 | double *Iout, //output image 48 | int nx, //image width 49 | int ny, //image height 50 | int nz, // number of color channels in image 51 | double factor //zoom factor between 0 and 1 52 | ) 53 | { 54 | int nxx, nyy, original_size =nx*ny*nz; 55 | double ifactor = 1.0/factor; 56 | double *Is=new double[original_size]; 57 | 58 | for (int i=0; ifactory)?factorx:factory; 116 | 117 | switch(nparams) { 118 | default: case TRANSLATION_TRANSFORM: //p=(tx, ty) 119 | pout[0]=p[0]*nu; 120 | pout[1]=p[1]*nu; 121 | break; 122 | case EUCLIDEAN_TRANSFORM: //p=(tx, ty, tita) 123 | pout[0]=p[0]*nu; 124 | pout[1]=p[1]*nu; 125 | pout[2]=p[2]; 126 | break; 127 | case SIMILARITY_TRANSFORM: //p=(tx, ty, a, b) 128 | pout[0]=p[0]*nu; 129 | pout[1]=p[1]*nu; 130 | pout[2]=p[2]; 131 | pout[3]=p[3]; 132 | break; 133 | case AFFINITY_TRANSFORM: //p=(tx, ty, a00, a01, a10, a11) 134 | pout[0]=p[0]*nu; 135 | pout[1]=p[1]*nu; 136 | pout[2]=p[2]; 137 | pout[3]=p[3]; 138 | pout[4]=p[4]; 139 | pout[5]=p[5]; 140 | break; 141 | case HOMOGRAPHY_TRANSFORM: //p=(h00, h01,..., h21) 142 | pout[0]=p[0]; 143 | pout[1]=p[1]; 144 | pout[2]=p[2]*nu; 145 | pout[3]=p[3]; 146 | pout[4]=p[4]; 147 | pout[5]=p[5]*nu; 148 | pout[6]=p[6]/nu; 149 | pout[7]=p[7]/nu; 150 | break; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /zoom.h: -------------------------------------------------------------------------------- 1 | // This program is free software: you can use, modify and/or redistribute it 2 | // under the terms of the simplified BSD License. You should have received a 3 | // copy of this license along this program. If not, see 4 | // . 5 | // 6 | // Copyright (C) 2018, Thibaud Briand 7 | // Copyright (C) 2015, Javier Sánchez Pérez 8 | // Copyright (C) 2014, Nelson Monzón López 9 | // All rights reserved. 10 | 11 | #ifndef ZOOM_H 12 | #define ZOOM_H 13 | 14 | /** 15 | * 16 | * Compute the size of a zoomed image from the zoom factor 17 | * 18 | **/ 19 | void zoom_size 20 | ( 21 | int nx, //width of the orignal image 22 | int ny, //height of the orignal image 23 | int &nxx, //width of the zoomed image 24 | int &nyy, //height of the zoomed image 25 | double factor = 0.5 //zoom factor between 0 and 1 26 | ); 27 | 28 | /** 29 | * 30 | * Function to downsample the image 31 | * 32 | **/ 33 | void zoom_out 34 | ( 35 | double *I, //input image 36 | double *Iout, //output image 37 | int nx, //image width 38 | int ny, //image height 39 | int nz, // number of color channels in image 40 | double factor = 0.5 //zoom factor between 0 and 1 41 | ); 42 | 43 | /** 44 | * 45 | * Function to upsample the parameters of the transformation 46 | * 47 | **/ 48 | void zoom_in_parameters 49 | ( 50 | double *p, //input image 51 | double *pout, //output image 52 | int nparams, //number of parameters 53 | int nx, //width of the original image 54 | int ny, //height of the original image 55 | int nxx, //width of the zoomed image 56 | int nyy //height of the zoomed image 57 | ); 58 | 59 | #endif 60 | --------------------------------------------------------------------------------