Ajout prototype Wrapper ROS matcher

This commit is contained in:
Unknown 2018-08-01 15:23:50 +02:00
parent f17bbbcc51
commit 373a75ae87
409 changed files with 133617 additions and 507 deletions

View file

@ -1,3 +1,6 @@
#ifndef ASIFTMATCHER_HPP
#define ASIFTMATCHER_HPP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -94,3 +97,5 @@ protected:
bool _resize_imgs;// = false; //Resize images to IM_X/IM_Y ?
bool _showDebug;// = 0; //Show debugging messages ?
};
#endif

View file

@ -17,10 +17,6 @@ SET(CMAKE_MAKEFILE_DEPENDS
"io_png/libs/zlib/CMakeLists.txt"
"libMatch/CMakeLists.txt"
"libNumerics/CMakeLists.txt"
"/usr/share/OpenCV/OpenCVConfig-version.cmake"
"/usr/share/OpenCV/OpenCVConfig.cmake"
"/usr/share/OpenCV/OpenCVModules-release.cmake"
"/usr/share/OpenCV/OpenCVModules.cmake"
"/usr/share/cmake-2.8/Modules/CMakeCInformation.cmake"
"/usr/share/cmake-2.8/Modules/CMakeCXXInformation.cmake"
"/usr/share/cmake-2.8/Modules/CMakeCommonLanguageInclude.cmake"

View file

@ -6,3 +6,81 @@
#IncludeRegexTransform:
./io_png/libs/png/png.h
../zlib/zlib.h
./io_png/libs/zlib/zlib.h
pngconf.h
./io_png/libs/png/pngconf.h
crtdbg.h
-
./io_png/libs/png/pngconf.h
pngusr.h
./io_png/libs/png/pngusr.h
config.h
./io_png/libs/png/config.h
windows.h
-
stdio.h
-
stdio.h
-
sys/types.h
-
setjmp.h
-
strings.h
-
string.h
-
stdlib.h
-
fp.h
-
math.h
-
m68881.h
-
mem.h
-
alloc.h
-
malloc.h
-
time.h
-
dos.h
-
./io_png/libs/zlib/zconf.h
windows.h
-
sys/types.h
-
unistd.h
-
unixio.h
-
./io_png/libs/zlib/zlib.h
zconf.h
./io_png/libs/zlib/zconf.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/io_png/io_png.c
stdlib.h
-
stdio.h
-
math.h
-
assert.h
-
png.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/io_png/png.h
png.h
-
io_png.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/io_png/io_png.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/io_png/io_png.h

View file

@ -6,143 +6,3 @@
#IncludeRegexTransform:
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/compute_asift_keypoints.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
demo_lib_sift.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/demo_lib_sift.h
frot.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/frot.h
fproj.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/fproj.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/compute_asift_matches.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
demo_lib_sift.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/demo_lib_sift.h
frot.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/frot.h
fproj.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/fproj.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/demo_ASIFT.cpp
stdio.h
-
stdlib.h
-
string.h
-
time.h
-
vector
-
omp.h
-
demo_lib_sift.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/demo_lib_sift.h
io_png/io_png.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/io_png/io_png.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
frot.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/frot.h
fproj.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/fproj.h
compute_asift_keypoints.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/compute_asift_keypoints.h
compute_asift_matches.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/compute_asift_matches.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/demo_lib_sift.h
stdlib.h
-
assert.h
-
numerics1.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/numerics1.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
filter.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/filter.h
domain.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/domain.h
splines.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/splines.h
flimage.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/flimage.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/domain.h
numerics1.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/numerics1.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
splines.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/splines.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/filter.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/flimage.h
iostream
-
string
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/fproj.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/frot.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/io_png/io_png.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
stdio.h
-
stdlib.h
-
math.h
-
time.h
-
float.h
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/numerics1.h
stdio.h
-
stdlib.h
-
math.h
-
fstream
-
iostream
-
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/splines.h
numerics1.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/numerics1.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
string.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/string.h
vector
-

View file

@ -37,7 +37,6 @@ SET(CMAKE_C_TARGET_INCLUDE_PATH
"."
"./io_png"
"./io_png/libs/png"
"/usr/include/opencv"
)
SET(CMAKE_CXX_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH})
SET(CMAKE_Fortran_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH})

View file

@ -3,11 +3,11 @@
# compile C with /usr/bin/cc
# compile CXX with /usr/bin/c++
C_FLAGS = -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/. -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png/libs/png -I/usr/include/opencv
C_FLAGS = -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/. -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png/libs/png
C_DEFINES =
CXX_FLAGS = -fopenmp -Wall -Wno-strict-aliasing -Wextra -Wno-write-strings -Wno-deprecated -ansi -O2 -ftree-vectorize -funroll-loops -L/usr/X11R6/lib -lm -lpthread -lX11 -std=c++11 -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/. -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png/libs/png -I/usr/include/opencv
CXX_FLAGS = -fopenmp -Wall -Wno-strict-aliasing -Wextra -Wno-write-strings -Wno-deprecated -ansi -O2 -ftree-vectorize -funroll-loops -L/usr/X11R6/lib -lm -lpthread -lX11 -std=c++11 -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/. -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png/libs/png
CXX_DEFINES =

View file

@ -6,353 +6,3 @@
#IncludeRegexTransform:
./io_png/libs/png/png.h
../zlib/zlib.h
./io_png/libs/zlib/zlib.h
pngconf.h
./io_png/libs/png/pngconf.h
crtdbg.h
-
./io_png/libs/png/pngconf.h
pngusr.h
./io_png/libs/png/pngusr.h
config.h
./io_png/libs/png/config.h
windows.h
-
stdio.h
-
stdio.h
-
sys/types.h
-
setjmp.h
-
strings.h
-
string.h
-
stdlib.h
-
fp.h
-
math.h
-
m68881.h
-
mem.h
-
alloc.h
-
malloc.h
-
time.h
-
dos.h
-
./io_png/libs/zlib/zconf.h
windows.h
-
sys/types.h
-
unistd.h
-
unixio.h
-
./io_png/libs/zlib/zlib.h
zconf.h
./io_png/libs/zlib/zconf.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/ASIFT_matcher.hpp
stdio.h
-
stdlib.h
-
string.h
-
time.h
-
vector
-
sstream
-
omp.h
-
demo_lib_sift.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/demo_lib_sift.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
frot.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/frot.h
fproj.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/fproj.h
compute_asift_keypoints.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/compute_asift_keypoints.h
compute_asift_matches.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/compute_asift_matches.h
CImg.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/CImg.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/CImg.h
cstdio
-
cstdlib
-
cstdarg
-
cstring
-
cmath
-
cfloat
-
climits
-
ctime
-
exception
-
algorithm
-
stdio.h
-
sys/types.h
-
sys/time.h
-
sys/stat.h
-
unistd.h
-
dirent.h
-
fnmatch.h
-
windows.h
-
shlobj.h
-
process.h
-
io.h
-
initializer_list
-
utility
-
X11/Xlib.h
-
X11/Xutil.h
-
X11/keysym.h
-
pthread.h
-
sys/ipc.h
-
sys/shm.h
-
X11/extensions/XShm.h
-
X11/extensions/Xrandr.h
-
omp.h
-
cstddef
-
cv.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/cv.h
highgui.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/highgui.h
png.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/png.h
jpeglib.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/jpeglib.h
setjmp.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/setjmp.h
tiffio.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/tiffio.h
minc_io_simple_volume.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/minc_io_simple_volume.h
minc_1_simple.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/minc_1_simple.h
minc_1_simple_rw.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/minc_1_simple_rw.h
zlib.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/zlib.h
curl/curl.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/curl/curl.h
Magick++.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/Magick++.h
fftw3.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/fftw3.h
Board.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/Board.h
ImfRgbaFile.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/ImfRgbaFile.h
ImfInputFile.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/ImfInputFile.h
ImfChannelList.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/ImfChannelList.h
ImfMatrixAttribute.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/ImfMatrixAttribute.h
ImfArray.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/ImfArray.h
tinyexr.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/tinyexr.h
CImg.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/CImg.h
stdint.h
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/compute_asift_keypoints.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
demo_lib_sift.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/demo_lib_sift.h
frot.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/frot.h
fproj.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/fproj.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/compute_asift_matches.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
demo_lib_sift.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/demo_lib_sift.h
frot.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/frot.h
fproj.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/fproj.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/demo_lib_sift.h
stdlib.h
-
assert.h
-
numerics1.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/numerics1.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
filter.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/filter.h
domain.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/domain.h
splines.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/splines.h
flimage.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/flimage.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/domain.h
numerics1.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/numerics1.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
splines.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/splines.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/filter.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/flimage.h
iostream
-
string
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/fproj.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/frot.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
stdio.h
-
stdlib.h
-
math.h
-
time.h
-
float.h
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/numerics1.h
stdio.h
-
stdlib.h
-
math.h
-
fstream
-
iostream
-
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/splines.h
numerics1.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/numerics1.h
library.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/library.h
string.h
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/string.h
vector
-
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/test_ASIFT.cpp
ASIFT_matcher.hpp
/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/ASIFT_matcher.hpp
/usr/include/opencv/cv.h
opencv2/core/core_c.h
/usr/include/opencv/opencv2/core/core_c.h
opencv2/core/core.hpp
/usr/include/opencv/opencv2/core/core.hpp
opencv2/imgproc/imgproc_c.h
/usr/include/opencv/opencv2/imgproc/imgproc_c.h
opencv2/imgproc/imgproc.hpp
/usr/include/opencv/opencv2/imgproc/imgproc.hpp
opencv2/video/tracking.hpp
/usr/include/opencv/opencv2/video/tracking.hpp
opencv2/features2d/features2d.hpp
/usr/include/opencv/opencv2/features2d/features2d.hpp
opencv2/flann/flann.hpp
/usr/include/opencv/opencv2/flann/flann.hpp
opencv2/calib3d/calib3d.hpp
/usr/include/opencv/opencv2/calib3d/calib3d.hpp
opencv2/objdetect/objdetect.hpp
/usr/include/opencv/opencv2/objdetect/objdetect.hpp
opencv2/legacy/compat.hpp
/usr/include/opencv/opencv2/legacy/compat.hpp
opencv2/core/internal.hpp
/usr/include/opencv/opencv2/core/internal.hpp
/usr/include/opencv/highgui.h
opencv2/core/core_c.h
/usr/include/opencv/opencv2/core/core_c.h
opencv2/core/core.hpp
/usr/include/opencv/opencv2/core/core.hpp
opencv2/highgui/highgui_c.h
/usr/include/opencv/opencv2/highgui/highgui_c.h
opencv2/highgui/highgui.hpp
/usr/include/opencv/opencv2/highgui/highgui.hpp

View file

@ -38,7 +38,6 @@ SET(CMAKE_C_TARGET_INCLUDE_PATH
"."
"./io_png"
"./io_png/libs/png"
"/usr/include/opencv"
)
SET(CMAKE_CXX_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH})
SET(CMAKE_Fortran_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH})

View file

@ -3,11 +3,11 @@
# compile C with /usr/bin/cc
# compile CXX with /usr/bin/c++
C_FLAGS = -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/. -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png/libs/png -I/usr/include/opencv
C_FLAGS = -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/. -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png/libs/png
C_DEFINES =
CXX_FLAGS = -fopenmp -Wall -Wno-strict-aliasing -Wextra -Wno-write-strings -Wno-deprecated -ansi -O2 -ftree-vectorize -funroll-loops -L/usr/X11R6/lib -lm -lpthread -lX11 -std=c++11 -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/. -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png/libs/png -I/usr/include/opencv
CXX_FLAGS = -fopenmp -Wall -Wno-strict-aliasing -Wextra -Wno-write-strings -Wno-deprecated -ansi -O2 -ftree-vectorize -funroll-loops -L/usr/X11R6/lib -lm -lpthread -lX11 -std=c++11 -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/. -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png -I/home/harle/catkin_ws/src/BaxterInterface/ASIFT_tests/demo_ASIFT_src/./io_png/libs/png
CXX_DEFINES =

View file

@ -45,13 +45,14 @@ set(ASIFT_srcs
include_directories(.
./io_png
./io_png/libs/png)
./io_png/libs/png
)
add_executable(demo_ASIFT demo_ASIFT.cpp ${ASIFT_srcs})
TARGET_LINK_LIBRARIES(demo_ASIFT png zlib Match Numerics)
find_package( OpenCV REQUIRED )
#find_package( OpenCV REQUIRED )
add_executable(test_ASIFT test_ASIFT.cpp ASIFT_matcher.cpp ${ASIFT_srcs})
TARGET_LINK_LIBRARIES(test_ASIFT png zlib Match Numerics X11) #${OpenCV_LIBS})
TARGET_LINK_LIBRARIES(test_ASIFT png zlib Match Numerics X11)

View file

@ -27,8 +27,8 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra -Wno-write-strings")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -ansi")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -ftree-vectorize -funroll-loops")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L/usr/X11R6/lib -lm -lpthread -lX11")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
@ -45,13 +45,14 @@ set(ASIFT_srcs
include_directories(.
./io_png
./io_png/libs/png)
./io_png/libs/png
)
add_executable(demo_ASIFT demo_ASIFT.cpp ${ASIFT_srcs})
TARGET_LINK_LIBRARIES(demo_ASIFT png zlib Match Numerics)
find_package( OpenCV REQUIRED )
#find_package( OpenCV REQUIRED )
add_executable(test_ASIFT test_ASIFT.cpp ASIFT_matcher.cpp ${ASIFT_srcs})
TARGET_LINK_LIBRARIES(test_ASIFT png zlib Match Numerics X11 ${OpenCV_LIBS})
TARGET_LINK_LIBRARIES(test_ASIFT zlib Match Numerics X11)

195
asift_match/CMakeLists.txt Normal file
View file

@ -0,0 +1,195 @@
cmake_minimum_required(VERSION 2.8.3)
project(asift_matching)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(cmake_modules)
IF(cmake_modules_FOUND)
find_package(Eigen REQUIRED)
ELSE()
find_package(Eigen3 REQUIRED)
set(Eigen_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIRS})
ENDIF()
FIND_PACKAGE(OpenMP)
if (OPENMP_FOUND)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif (OPENMP_FOUND)
IF(MSVC)
ADD_DEFINITIONS(/arch:SSE2)
ENDIF(MSVC)
find_package(catkin REQUIRED COMPONENTS
roscpp
tf
rospy
pcl_conversions
pcl_ros
sensor_msgs
)
#find_package(Eigen3 REQUIRED)
#find_package(cmake_modules REQUIRED)
## Compile as C++11, supported in ROS Kinetic and newer
#add_compile_options(-std=c++11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -ftree-vectorize -funroll-loops -L/usr/X11R6/lib -lm -lpthread -lX11 -std=c++11")
################################################
## Declare ROS messages, services and actions ##
################################################
## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
## * add a build_depend tag for "message_generation"
## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
## but can be declared for certainty nonetheless:
## * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
## * add "message_generation" and every package in MSG_DEP_SET to
## find_package(catkin REQUIRED COMPONENTS ...)
## * add "message_runtime" and every package in MSG_DEP_SET to
## catkin_package(CATKIN_DEPENDS ...)
## * uncomment the add_*_files sections below as needed
## and list every .msg/.srv/.action file to be processed
## * uncomment the generate_messages entry below
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
## Generate messages in the 'msg' folder
#add_message_files(
# FILES
#)
## Generate services in the 'srv' folder
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
## Generate actions in the 'action' folder
# add_action_files(
# FILES
# Action1.action
# Action2.action
# )
## Generate added messages and services with any dependencies listed here
#generate_messages(
# DEPENDENCIES
# std_msgs
# geometry_msgs
#)
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#CATKIN_DEPENDS roscpp tf message_runtime
#INCLUDE_DIRS include
)
###########
## Build ##
###########
set(ASIFT_srcs
src/numerics1.cpp src/frot.cpp src/splines.cpp src/fproj.cpp
src/library.cpp src/flimage.cpp src/filter.cpp
src/demo_lib_sift.cpp src/compute_asift_keypoints.cpp
src/compute_asift_matches.cpp
src/orsa.cpp
src/ASIFT_matcher.cpp
src/ROS_matcher.cpp
src/ROS_matcher_node.cpp
)
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
.
#include
${catkin_INCLUDE_DIRS}
${Eigen_INCLUDE_DIRS}
)
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(ASIFT_matcher ${ASIFT_srcs})
target_link_libraries(ASIFT_matcher
${catkin_LIBRARIES}
${Eigen_LIBRARIES}
X11
)
## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
#add_dependencies(ASIFT_matcher ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
#############
## Install ##
#############
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
#install(PROGRAMS
#scripts/basic_controls.py
#scripts/cube.py
#scripts/menu.py
#scripts/simple_marker.py
#DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
#)
## Mark executables and/or libraries for installation
#install(TARGETS
# ASIFT_matcher
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
#)
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
# # myfile1
# # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_beginner_tutorials.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

192
asift_match/CMakeLists.txt~ Normal file
View file

@ -0,0 +1,192 @@
cmake_minimum_required(VERSION 2.8.3)
project(asift_matching)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(cmake_modules)
IF(cmake_modules_FOUND)
find_package(Eigen REQUIRED)
ELSE()
find_package(Eigen3 REQUIRED)
set(Eigen_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIRS})
ENDIF()
FIND_PACKAGE(OpenMP)
if (OPENMP_FOUND)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif (OPENMP_FOUND)
IF(MSVC)
ADD_DEFINITIONS(/arch:SSE2)
ENDIF(MSVC)
find_package(catkin REQUIRED COMPONENTS
roscpp
tf
rospy
)
#find_package(Eigen3 REQUIRED)
#find_package(cmake_modules REQUIRED)
## Compile as C++11, supported in ROS Kinetic and newer
#add_compile_options(-std=c++11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -ftree-vectorize -funroll-loops -L/usr/X11R6/lib -lm -lpthread -lX11 -std=c++11")
################################################
## Declare ROS messages, services and actions ##
################################################
## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
## * add a build_depend tag for "message_generation"
## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
## but can be declared for certainty nonetheless:
## * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
## * add "message_generation" and every package in MSG_DEP_SET to
## find_package(catkin REQUIRED COMPONENTS ...)
## * add "message_runtime" and every package in MSG_DEP_SET to
## catkin_package(CATKIN_DEPENDS ...)
## * uncomment the add_*_files sections below as needed
## and list every .msg/.srv/.action file to be processed
## * uncomment the generate_messages entry below
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
## Generate messages in the 'msg' folder
#add_message_files(
# FILES
#)
## Generate services in the 'srv' folder
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
## Generate actions in the 'action' folder
# add_action_files(
# FILES
# Action1.action
# Action2.action
# )
## Generate added messages and services with any dependencies listed here
#generate_messages(
# DEPENDENCIES
# std_msgs
# geometry_msgs
#)
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#CATKIN_DEPENDS roscpp tf message_runtime
#INCLUDE_DIRS include
)
###########
## Build ##
###########
set(ASIFT_srcs
src/numerics1.cpp src/frot.cpp src/splines.cpp src/fproj.cpp
src/library.cpp src/flimage.cpp src/filter.cpp
src/demo_lib_sift.cpp src/compute_asift_keypoints.cpp
src/compute_asift_matches.cpp
src/orsa.cpp
src/ASIFT_matcher.cpp
src/ROS_matcher.cpp
src/ROS_matcher_node.cpp
)
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
.
#include
${catkin_INCLUDE_DIRS}
${Eigen_INCLUDE_DIRS}
)
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(ASIFT_matcher ${ASIFT_srcs})
target_link_libraries(ASIFT_matcher
${catkin_LIBRARIES}
${Eigen_LIBRARIES}
X11
)
## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
#add_dependencies(ASIFT_matcher ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
#############
## Install ##
#############
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
#install(PROGRAMS
#scripts/basic_controls.py
#scripts/cube.py
#scripts/menu.py
#scripts/simple_marker.py
#DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
#)
## Mark executables and/or libraries for installation
#install(TARGETS
# ASIFT_matcher
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
#)
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
# # myfile1
# # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_beginner_tutorials.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

73
asift_match/package.xml Normal file
View file

@ -0,0 +1,73 @@
<?xml version="1.0"?>
<package>
<name>asift_matching</name>
<version>0.0.0</version>
<description>ASIFT based matching package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="blue@todo.todo">blue</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>DREAM</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/rviz_interface</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<!-- <exec_depend>message_runtime</exec_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>tf</build_depend>
<build_depend>pcl_conversions</build_depend>
<build_depend>pcl_ros</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>libpcl-all-dev</build_depend>
<run_depend>libpcl-all</run_depend>
<run_depend>pcl_conversions</run_depend>
<run_depend>pcl_ros</run_depend>
<run_depend>roscpp</run_depend>
<run_depend>sensor_msgs</run_depend>
<run_depend>roscpp</run_depend>
<run_depend>tf</run_depend>
<!--run_depend>message_runtime</run_depend-->
<export>
</export>
</package>

79
asift_match/package.xml~ Normal file
View file

@ -0,0 +1,79 @@
<?xml version="1.0"?>
<package>
<name>asift_matching</name>
<version>0.0.0</version>
<description>ASIFT based matching package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="blue@todo.todo">blue</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>DREAM</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/rviz_interface</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<!-- <exec_depend>message_runtime</exec_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>tf</build_depend>
<build_depend>pcl_conversions</build_depend>
<build_depend>pcl_ros</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_export_depend>pcl_conversions</build_export_depend>
<build_export_depend>pcl_ros</build_export_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>sensor_msgs</build_export_depend>
<exec_depend>pcl_conversions</exec_depend>
<exec_depend>pcl_ros</exec_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<build_depend>libpcl-all-dev</build_depend>
<exec_depend>libpcl-all</exec_depend>
<run_depend>roscpp</run_depend>
<run_depend>tf</run_depend>
<!--run_depend>message_runtime</run_depend-->
<export>
</export>
</package>

View file

@ -0,0 +1,717 @@
#include "ASIFT_matcher.hpp"
ASIFT_matcher::ASIFT_matcher(): _nb_refs(0), _total_num_matchings(0), _resize_imgs(false), _showDebug(false)
{
default_sift_parameters(_siftParam);
}
ASIFT_matcher::ASIFT_matcher(const char* ref_path): ASIFT_matcher()
{
if(!loadReferences(ref_path))
{
std::cerr<<"Error : Failed to load references"<<std::endl;
}
}
// ASIFT_matcher::~ASIFT_matcher()
// {
// }
//Return true if successfull
bool ASIFT_matcher::addReference(const char* image_path, unsigned int num_tilts)
{
///// Read input
// float * iarr1;
// size_t w1, h1;
// if (NULL == (iarr1 = read_png_f32_gray(image_path, &w1, &h1))) {
// std::cerr << "Unable to load image file " << image_path << std::endl;
// return false;
// }
// std::vector<float> ipixels1(iarr1, iarr1 + w1 * h1);
// free(iarr1); /*memcheck*/
// cout<<"Size : "<<w1<<"/"<<h1<<" - "<<ipixels1.size()<<endl;
cimg_library::CImg<float> image;
try
{
image.assign(image_path);
}
catch(cimg_library::CImgIOException)
{
std::cerr << "Unable to load image file " << image_path << std::endl;
return false;
}
//Convert to grayscale
cimg_library::CImg<float> gray(image.width(), image.height(), 1, 1, 0);
cimg_forXY(image,x,y) {
// Separation of channels
int R = (int)image(x,y,0,0);
int G = (int)image(x,y,0,1);
int B = (int)image(x,y,0,2);
// Arithmetic addition of channels for gray
// int grayValue = (int)(0.33*R + 0.33*G + 0.33*B);
// Real weighted addition of channels for gray
int grayValueWeight = (int)(0.299*R + 0.587*G + 0.114*B);
// saving píxel values into image information
// gray(x,y,0,0) = grayValue;
gray(x,y,0,0) = grayValueWeight;
}
std::vector<float> ipixels1;
size_t w1=gray.width(), h1=gray.height();
ipixels1.assign(gray.begin(), gray.end());
std::cout<<"Building reference from "<< image_path << std::endl;
return addReference(ipixels1, w1, h1, num_tilts);
}
//Image : Gray scale image (image size = w*h)
bool ASIFT_matcher::addReference(const vector<float>& image, unsigned int w, unsigned int h, unsigned int num_tilts)
{
if(image.size()!=w*h)
{
cerr<<"Error : Input image size doesn't correspond with parameters"<<endl;
return false;
}
int w1=w, h1=h;
vector<float> ipixels1 = image;
///// Resize the images to area wS*hW in remaining the apsect-ratio
///// Resize if the resize flag is not set or if the flag is set unequal to 0
float wS = IM_X;
float hS = IM_Y;
float zoom1=0;
int wS1=0, hS1=0;
vector<float> ipixels1_zoom;
if(_resize_imgs)
{
cout << "WARNING: The input image is resized to " << wS << "x" << hS << " for ASIFT. " << endl
<< " But the results will be normalized to the original image size." << endl << endl;
float InitSigma_aa = 1.6;
float fproj_p, fproj_bg;
char fproj_i;
float *fproj_x4, *fproj_y4;
int fproj_o;
fproj_o = 3;
fproj_p = 0;
fproj_i = 0;
fproj_bg = 0;
fproj_x4 = 0;
fproj_y4 = 0;
float areaS = wS * hS;
// Resize image 1
float area1 = w1 * h1;
zoom1 = sqrt(area1/areaS);
wS1 = (int) (w1 / zoom1);
hS1 = (int) (h1 / zoom1);
int fproj_sx = wS1;
int fproj_sy = hS1;
float fproj_x1 = 0;
float fproj_y1 = 0;
float fproj_x2 = wS1;
float fproj_y2 = 0;
float fproj_x3 = 0;
float fproj_y3 = hS1;
/* Anti-aliasing filtering along vertical direction */
if ( zoom1 > 1 )
{
float sigma_aa = InitSigma_aa * zoom1 / 2;
GaussianBlur1D(ipixels1,w1,h1,sigma_aa,1);
GaussianBlur1D(ipixels1,w1,h1,sigma_aa,0);
}
// simulate a tilt: subsample the image along the vertical axis by a factor of t.
ipixels1_zoom.resize(wS1*hS1);
fproj (ipixels1, ipixels1_zoom, w1, h1, &fproj_sx, &fproj_sy, &fproj_bg, &fproj_o, &fproj_p,
&fproj_i , fproj_x1 , fproj_y1 , fproj_x2 , fproj_y2 , fproj_x3 , fproj_y3, fproj_x4, fproj_y4);
}
else
{
ipixels1_zoom.resize(w1*h1);
ipixels1_zoom = ipixels1;
wS1 = w1;
hS1 = h1;
zoom1 = 1;
}
///// Compute ASIFT keypoints
asift_keypoints keys;
int num_keys = 0;
time_t tstart, tend;
tstart = time(0);
num_keys = compute_asift_keypoints(ipixels1_zoom, wS1, hS1, num_tilts, _showDebug, keys, _siftParam);
tend = time(0);
//Save data
_im_refs.push_back(ipixels1_zoom);
_size_refs.push_back(make_pair(wS1,hS1));
_zoom_refs.push_back(zoom1);
_num_keys.push_back(num_keys);
_num_tilts.push_back(num_tilts);
_keys.push_back(keys);
_nb_refs++;
cout<<"Reference built in "<< difftime(tend, tstart) << " seconds." << endl;
cout<<" "<< num_keys <<" ASIFT keypoints found."<< endl;
return true;
}
//Return number of match
unsigned int ASIFT_matcher::match(const char* image_path, unsigned int num_tilts)
{
if(_nb_refs<=0)
{
cout<<"ASIFT_matcher Error : Trying to match without reference"<<endl;
return 0;
}
///// Read input
// float * iarr1;
// size_t w1, h1;
// if (NULL == (iarr1 = read_png_f32_gray(image_path, &w1, &h1))) {
// std::cerr << "Unable to load image file " << image_path << std::endl;
// return 1;
// }
// std::vector<float> ipixels1(iarr1, iarr1 + w1 * h1);
// free(iarr1); /*memcheck*/
cimg_library::CImg<float> image;
try
{
image.assign(image_path);
}
catch(cimg_library::CImgIOException)
{
std::cerr << "Unable to load image file " << image_path << std::endl;
return 0;
}
//Convert to grayscale
cimg_library::CImg<float> gray(image.width(), image.height(), 1, 1, 0);
cimg_forXY(image,x,y) {
// Separation of channels
int R = (int)image(x,y,0,0);
int G = (int)image(x,y,0,1);
int B = (int)image(x,y,0,2);
// Arithmetic addition of channels for gray
// int grayValue = (int)(0.33*R + 0.33*G + 0.33*B);
// Real weighted addition of channels for gray
int grayValueWeight = (int)(0.299*R + 0.587*G + 0.114*B);
// saving píxel values into image information
// gray(x,y,0,0) = grayValue;
gray(x,y,0,0) = grayValueWeight;
}
vector<float> ipixels1;
size_t w1=gray.width(), h1=gray.height();
ipixels1.assign(gray.begin(), gray.end());
std::cout<<"Matching from "<<image_path<<std::endl;
return match(ipixels1, w1, h1, num_tilts);
}
//Image : Gray scale image (image size = w*h)
//Return number of match
unsigned int ASIFT_matcher::match(const vector<float>& image, unsigned int w, unsigned int h, unsigned int num_tilts)
{
if(image.size()!=w*h)
{
cerr<<"Error : Input image size doesn't correspond with parameters"<<endl;
return 0;
}
int w1=w, h1=h;
vector<float> ipixels1 = image;
///// Resize the images to area wS*hW in remaining the apsect-ratio
///// Resize if the resize flag is not set or if the flag is set unequal to 0
float wS = IM_X;
float hS = IM_Y;
float zoom1=0;
int wS1=0, hS1=0;
vector<float> ipixels1_zoom;
if(_resize_imgs)
{
cout << "WARNING: The input image is resized to " << wS << "x" << hS << " for ASIFT. " << endl
<< " But the results will be normalized to the original image size." << endl << endl;
float InitSigma_aa = 1.6;
float fproj_p, fproj_bg;
char fproj_i;
float *fproj_x4, *fproj_y4;
int fproj_o;
fproj_o = 3;
fproj_p = 0;
fproj_i = 0;
fproj_bg = 0;
fproj_x4 = 0;
fproj_y4 = 0;
float areaS = wS * hS;
// Resize image 1
float area1 = w1 * h1;
zoom1 = sqrt(area1/areaS);
wS1 = (int) (w1 / zoom1);
hS1 = (int) (h1 / zoom1);
int fproj_sx = wS1;
int fproj_sy = hS1;
float fproj_x1 = 0;
float fproj_y1 = 0;
float fproj_x2 = wS1;
float fproj_y2 = 0;
float fproj_x3 = 0;
float fproj_y3 = hS1;
/* Anti-aliasing filtering along vertical direction */
if ( zoom1 > 1 )
{
float sigma_aa = InitSigma_aa * zoom1 / 2;
GaussianBlur1D(ipixels1,w1,h1,sigma_aa,1);
GaussianBlur1D(ipixels1,w1,h1,sigma_aa,0);
}
// simulate a tilt: subsample the image along the vertical axis by a factor of t.
ipixels1_zoom.resize(wS1*hS1);
fproj (ipixels1, ipixels1_zoom, w1, h1, &fproj_sx, &fproj_sy, &fproj_bg, &fproj_o, &fproj_p,
&fproj_i , fproj_x1 , fproj_y1 , fproj_x2 , fproj_y2 , fproj_x3 , fproj_y3, fproj_x4, fproj_y4);
}
else
{
ipixels1_zoom.resize(w1*h1);
ipixels1_zoom = ipixels1;
wS1 = w1;
hS1 = h1;
zoom1 = 1;
}
///// Compute ASIFT keypoints
asift_keypoints keys;
int num_keys = 0;
time_t tstart, tend;
tstart = time(0);
num_keys = compute_asift_keypoints(ipixels1_zoom, wS1, hS1, num_tilts, _showDebug, keys, _siftParam);
tend = time(0);
cout<< "Keypoints computation accomplished in " << difftime(tend, tstart) << " seconds." << endl;
cout<<" "<< num_keys <<" ASIFT keypoints found."<< endl;
//// Match ASIFT keypoints
_total_num_matchings=0;
for(unsigned int i = 0; i<_nb_refs;i++)
{
int num_matchings = 0;
matchingslist matchings;
cout << "Matching the keypoints..." << endl;
tstart = time(0);
try
{
num_matchings = compute_asift_matches(num_tilts, _num_tilts[i], w, h, _size_refs[i].first, _size_refs[i].second, _showDebug, keys, _keys[i], matchings, _siftParam);
}
catch(const bad_alloc& ba)
{
cerr<<"ERROR: ASIFT_matcher::match - ";
cerr << ba.what() << endl;
}
// cout<< _keys[i].size()<< " " << _keys[i][0].size() <<" "<< _keys[i][0][0].size()<<endl;
tend = time(0);
cout << "Keypoints matching accomplished in " << difftime(tend, tstart) << " seconds." << endl;
_num_matchings.push_back(num_matchings);
_total_num_matchings += num_matchings;
_matchings.push_back(matchings);
}
return _total_num_matchings;
}
//Return true if successfull
bool ASIFT_matcher::computeROI(int& x, int& y, unsigned int& h, unsigned int& w) const
{
if(getNbMatch()==0)
{
cerr<<"Error : cannot compute ROI without matchs"<<endl;
return false;
}
pair<int,int> upLe, doRi; //UpLeft / DownRight
//Initialisation
for(unsigned int i=0;i<_matchings.size();i++)
{
if(getNbMatchs()[i]!=0)
{
upLe = make_pair(_matchings[i][0].first.x,_matchings[i][0].first.y);
doRi = make_pair(_matchings[i][0].first.x,_matchings[i][0].first.y);
}
}
//Compute ROI
for(unsigned int i=0;i<_matchings.size();i++)
{
for(unsigned int j=0;j<_matchings[i].size();j++)
{
keypoint kp = _matchings[i][j].first;
if(kp.x<upLe.first)
upLe.first = kp.x;
if(kp.y<upLe.second)
upLe.second=kp.y;
if(kp.x>doRi.first)
doRi.first=kp.x;
if(kp.y>doRi.second)
doRi.second=kp.y;
}
}
x=upLe.first; //Système de coordonée ? (devrait etre bon)
y=upLe.second;
h=doRi.second-y;
w=doRi.first-x;
return true;
}
//Return true if successfull
bool ASIFT_matcher::computeCenter(int& cx, int& cy) const
{
if(getNbMatch()==0)
{
cerr<<"Error : cannot compute Center without matchs"<<endl;
return false;
}
unsigned int total_kp =0;
cx=0;cy=0;
for(unsigned int i=0;i<_matchings.size();i++)
{
for(unsigned int j=0;j<_matchings[i].size();j++)
{
keypoint kp = _matchings[i][j].first;
cx+=kp.x;
cy+=kp.y;
}
total_kp += _matchings[i].size();
}
cx/=total_kp;
cy/=total_kp;
return true;
}
//Filter keypoint which are far (Euclidian distance) from the center.
//Not optimized
//threshold : 1-68%/2-95%/3-99%
//Return true if successfull
bool ASIFT_matcher::distFilter(int threshold=2)
{
cout<<"filtering keypoint..."<<endl;
if(getNbMatch()==0)
{
cerr<<"Error : cannot filter points without matchs"<<endl;
return false;
}
//Compute standard deviation
int cx, cy;
unsigned int total_kp =0;
unsigned int euc_dist, dist_avg =0, dist_var=0, std_dev;
vector< vector< int > > kp_euc_dist;
if(computeCenter(cx,cy))
{
// cout<<"Center : "<<cx<<" / "<<cy<<endl;
//Compute means/average distance to center + euclidian distances to center for each keypoint
for(unsigned int i=0;i<_matchings.size();i++)
{
vector<int> temp_euc_dist;
for(unsigned int j=0;j<_matchings[i].size();j++)
{
keypoint kp = _matchings[i][j].first;
euc_dist =sqrt((kp.x-cx)*(kp.x-cx)+(kp.y-cy)+(kp.y-cy));
dist_avg+=euc_dist;
temp_euc_dist.push_back(euc_dist);
}
total_kp += _matchings[i].size();
kp_euc_dist.push_back(temp_euc_dist);
}
dist_avg/=total_kp;
// cout<<"Dist avg: "<<dist_avg<<endl;
//Compute variance
for(unsigned int i=0;i<_matchings.size();i++)
{
for(unsigned int j=0;j<_matchings[i].size();j++)
{
euc_dist =kp_euc_dist[i][j];
dist_var+=(euc_dist-dist_avg)*(euc_dist-dist_avg);
}
}
dist_var/=total_kp;
//Compute standard deviation
std_dev=sqrt(dist_var);
// cout<<"Standard Deviation : "<<std_dev<<endl;
//Filter
vector< matchingslist > filtered_match;
for(unsigned int i=0;i<_matchings.size();i++)
{
matchingslist new_match;
for(unsigned int j=0;j<_matchings[i].size();j++)
{
euc_dist =kp_euc_dist[i][j];
if(euc_dist<dist_avg+threshold*std_dev) //Filtering Condition
{
new_match.push_back(_matchings[i][j]);
}
}
filtered_match.push_back(new_match);
_num_matchings[i]=new_match.size();
}
//Save filtered matchs
_matchings = filtered_match;
return true;
}
return false;
}
//Save reference data necessary for the matching
//Doesn't save references images or Sift parameters
bool ASIFT_matcher::saveReferences(const char* ref_path) const
{
// Write all the keypoints (row, col, scale, orientation, desciptor (128 integers))
std::ofstream file_key1(ref_path);
if (file_key1.is_open())
{
file_key1<<_nb_refs<<" "<<std::endl;
for(unsigned int j=0; j<_keys.size();j++)
{
asift_keypoints kps =_keys[j];
// Follow the same convention of David Lowe:
// the first line contains the number of keypoints and the length of the desciptors (128)
// Added number of tilts
// Added sizes
file_key1 << _num_keys[j] << " " << VecLength << " " <<_size_refs[j].first<<" "<<_size_refs[j].second<<" "<<std::endl; //<<_num_tilts[j] << " "
for (int tt = 0; tt < (int) kps.size(); tt++)
{
for (int rr = 0; rr < (int) kps[tt].size(); rr++)
{
keypointslist::iterator ptr = kps[tt][rr].begin();
for(int i=0; i < (int) kps[tt][rr].size(); i++, ptr++)
{
file_key1 << _zoom_refs[j]*ptr->x << " " << _zoom_refs[j]*ptr->y << " " << _zoom_refs[j]*ptr->scale << " " << ptr->angle;
for (int ii = 0; ii < (int) VecLength; ii++)
{
file_key1 << " " << ptr->vec[ii];
}
file_key1 << std::endl;
}
}
}
// file_key1<<std::endl;
}
}
else
{
std::cerr << "Unable to open the file :"<<ref_path;
return false;
}
file_key1.close();
return true;
}
//Load reference data necessary for the matching
//Doesn't load references images or Sift parameters
//TODO : split data between different tilts
bool ASIFT_matcher::loadReferences(const char* ref_path)
{
std::ifstream ref_file(ref_path);
std::string line, tmp;
std::stringstream iss;
pair<int,int> size_tmp;
if (ref_file.is_open())
{
std::getline(ref_file, line);
std::string::size_type sz;
// _nb_refs = std::stoi(line, &sz); //C++11
_nb_refs = atoi(line.c_str());
_keys = std::vector<asift_keypoints>(_nb_refs);
_num_keys = std::vector< int >(_nb_refs);
_size_refs= std::vector< pair<int,int> >(_nb_refs);
_num_tilts = std::vector< int >(_nb_refs,1);
_zoom_refs = std::vector<float>(_nb_refs,1);
for(unsigned int i = 0; i<_nb_refs;i++)
{
std::getline(ref_file, line);
std::stringstream iss(line);
std::getline(iss,tmp,' ');
_num_keys[i]=atoi(tmp.c_str());
std::getline(iss,tmp,' ');
if(VecLength!=atoi(tmp.c_str()))
{
std::cerr<<"Error VecLength doesn't correspond..."<<std::endl;
return false;
}
// std::getline(iss,tmp,' ');
// _num_tilts[i]=atoi(tmp.c_str());
std::getline(iss,tmp,' ');
size_tmp.first=atoi(tmp.c_str());
std::getline(iss,tmp,' ');
size_tmp.second=atoi(tmp.c_str());
_size_refs[i]=size_tmp;
keypointslist list;
for(unsigned int j =0; j<(unsigned int)_num_keys[i];j++)
{
keypoint nkp;
std::getline(ref_file, line);
std::stringstream iss(line);
// if(j==0)
// cout<<line<<endl;
std::getline(iss,tmp,' ');
// std::stof(nb_ref, nkp.x); //C++11
nkp.x=atof(tmp.c_str());
// if(j<5)
// cout<<"x : "<<nkp.x<<endl;
std::getline(iss,tmp,' ');
nkp.y=atof(tmp.c_str());
// if(j<5)
// cout<<"y : "<<nkp.y<<endl;
std::getline(iss,tmp,' ');
nkp.scale=atof(tmp.c_str());
// if(j<5)
// cout<<"Scale : "<<nkp.scale<<endl;
std::getline(iss,tmp,' ');
nkp.angle=atof(tmp.c_str());
for(unsigned int k=0; k<(int) VecLength; k++)
{
std::getline(iss,tmp,' ');
nkp.vec[k]=atof(tmp.c_str());
}
list.push_back(nkp);
// if(j<5)
// {
// cout<<"x : "<<list[j].x<<endl;
// cout<<"y : "<<list[j].y<<endl;
// cout<<"Scale : "<<list[j].scale<<endl;
// }
}
std::vector< keypointslist > vkps(1,list);
asift_keypoints akps(1,vkps);
_keys[i]=akps;
// std::getline(ref_file, line);
}
}
else
{
std::cerr << "Unable to open the file :"<<ref_path;
return false;
}
ref_file.close();
return true;
}
ASIFT_matcher& ASIFT_matcher::operator=(const ASIFT_matcher& m)
{
_nb_refs=m.getNbRef();
_im_refs=m.getRefImgs();
_size_refs=m.getSizeRef();
_zoom_refs=m.getZoomRef();
_num_keys=m.getNumKeys();
_num_tilts=m.getNumTilts();
_keys=m.getKeys();
_total_num_matchings=m.getNbMatch();
_num_matchings=getNbMatchs();
_matchings=m.getMatch();
_siftParam=m.getSiftPar();
_resize_imgs=m.isResizingImg();
_showDebug=m.isShowingDebug();
return *this;
}
//Debugging function
void ASIFT_matcher::print() const
{
for(unsigned int i=0; i< _keys.size();i++)
{
cout<<"Ref size:"<<i<<" - size :"<<_keys[i].size()<<endl;
for(unsigned int j=0; j<_keys[i].size();j++)
{
cout<<" "<<j<<" - size :"<<_keys[i][j].size()<<endl;
for(unsigned int k=0; k<_keys[i][j].size();k++)
{
cout<<" "<<k<<" - size :"<<_keys[i][j][k].size()<<endl;
double sx=0,sy=0,ss=0,sa=0, sv=0;
for(unsigned int l=0; l<_keys[i][j][k].size();l++)
{
sx+=_keys[i][j][k][l].x;
sy+=_keys[i][j][k][l].y;
ss+=_keys[i][j][k][l].scale;
sa+=_keys[i][j][k][l].angle;
for(unsigned int v=0;v<VecLength;v++)
{
sv+=_keys[i][j][k][l].vec[v];
}
// cout<<" "<<sx<<"-"<<sy<<"-"<<ss<<"-"<<sa<<"-"<<sv<<endl;
}
cout<<" "<<sx<<"-"<<sy<<"-"<<ss<<"-"<<sa<<"-"<<sv<<endl;
}
}
}
}

View file

@ -0,0 +1,101 @@
#ifndef ASIFTMATCHER_HPP
#define ASIFTMATCHER_HPP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <vector>
#include <sstream>
#ifdef _OPENMP
#include <omp.h>
#endif
#include "demo_lib_sift.h"
// #include "io_png/io_png.h"
#include "library.h"
#include "frot.h"
#include "fproj.h"
#include "compute_asift_keypoints.h"
#include "compute_asift_matches.h"
#include "CImg.h" //Need ImageMagick package
# define IM_X 800
# define IM_Y 600
using namespace std;
typedef vector< vector< keypointslist > > asift_keypoints;
//ASIFT wrapper
class ASIFT_matcher
{
public:
ASIFT_matcher();
ASIFT_matcher(const char* ref_path);
ASIFT_matcher(const ASIFT_matcher& matcher) { *this = matcher;}
// virtual ~ASIFT_matcher();
bool addReference(const char* image_path, unsigned int num_tilts=1);
bool addReference(const vector<float>& image, unsigned int w, unsigned int h, unsigned int num_tilts =1);
unsigned int match(const char* image_path, unsigned int num_tilts =1);
unsigned int match(const vector<float>& image, unsigned int w, unsigned int h, unsigned int num_tilts =1);
bool computeROI(int& x, int& y, unsigned int& h, unsigned int& w) const; //Compute the bounding rectangle of the keypoints
bool computeCenter(int& cx, int& cy) const;
bool distFilter(int threshold); //Filter keypoint which are far (Euclidian distance) from the center.
bool saveReferences(const char* ref_path) const;
bool loadReferences(const char* ref_path);
ASIFT_matcher& operator=(const ASIFT_matcher& m);
unsigned int getNbRef() const{ return _nb_refs;}
const vector< vector< float > >& getRefImgs() const{ return _im_refs;}
const vector< pair<int,int> >& getSizeRef() const{ return _size_refs;}
const vector<float>& getZoomRef() const{ return _zoom_refs;}
const std::vector<int>& getNumKeys() const{ return _num_keys;}
const std::vector<int>& getNumTilts() const{ return _num_tilts;}
const std::vector< asift_keypoints >& getKeys() const{ return _keys;}
const vector < unsigned int >& getNbMatchs() const{ return _num_matchings;}
unsigned int getNbMatch() const{ return _total_num_matchings;}
const vector< matchingslist >& getMatch() const{ return _matchings;}
vector< matchingslist >& getMatch(){ return _matchings;}
const siftPar& getSiftPar() const{ return _siftParam;}
void setSiftPar(const siftPar &newSiftPar){ _siftParam = newSiftPar;}
bool isResizingImg() const{ return _resize_imgs;}
void setResizeImg(bool resize_imgs){ _resize_imgs=resize_imgs;}
bool isShowingDebug() const{ return _showDebug;}
void showDebug(bool showDebug){ _showDebug=showDebug;}
void print() const; //Debugging function
protected:
//Reference Images
// vector< image > _im_refs;
unsigned int _nb_refs;// = 0; //Number of reference images
vector< vector< float > > _im_refs; //Reference images used for matching
vector< pair<int,int> > _size_refs; //Width/Height
vector<float> _zoom_refs; //Zoom coeffs
//ASIFT Keypoints
vector< int > _num_keys; //Number of keypoint/reference
vector< int > _num_tilts; //Number of tilts/reference (Speed VS Precision)
vector< asift_keypoints > _keys; //Keypoints
//Matchs
unsigned int _total_num_matchings;
vector < unsigned int > _num_matchings; //Number of match/reference
vector< matchingslist > _matchings; //Matchs
siftPar _siftParam; //SIFT parameters
//Flags
bool _resize_imgs;// = false; //Resize images to IM_X/IM_Y ?
bool _showDebug;// = 0; //Show debugging messages ?
};
#endif

60936
asift_match/src/CImg.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,57 @@
#include "ROS_matcher.hpp"
ROS_matcher::ROS_matcher(): _num_tilt(1), _status(MATCHER_STATUS_WAITING_INIT)
{
_center_pub = _nh.advertise<geometry_msgs::PointStamped>("/ROS_matcher/center", 10);
message_filters::Subscriber<sensor_msgs::CameraInfo> info_sub(_nh, "/camera/rgb/camera_info", 1);
message_filters::Subscriber<sensor_msgs::Image> image_sub(_nh, "/camera/rgb/image_raw", 1);
message_filters::Subscriber<sensor_msgs::PointCloud2> pointcloud_sub(_nh, "/camera/depth_registered/points", 1);
message_filters::TimeSynchronizer<sensor_msgs::CameraInfo, sensor_msgs::Image, sensor_msgs::PointCloud2> sync(info_sub, image_sub, pointcloud_sub, 10);
sync.registerCallback(boost::bind(&ROS_matcher::cameraCallback, this, _1, _2, _3));
unsigned int nb_ref =2;
std::string refData[] = {
"book_training/train_image_000.png",
"book_training/train_image_001.png",
"book_training/train_image_002.png",
"book_training/train_image_003.png"};
for(unsigned int i=0; i<nb_ref;i++)
{
matcher.addReference(refData[i].c_str(), _num_tilt);
}
}
void ROS_matcher::cameraCallback(const sensor_msgs::CameraInfo::ConstPtr& info_msg, const sensor_msgs::Image::ConstPtr& image_msg, const sensor_msgs::PointCloud2::ConstPtr& pointcloud_msg)
{
if(_status == MATCHER_STATUS_IDLE)
{
unsigned int width = image_msg->width, height = image_msg->height;
std::vector<float> image(height*width);
//Conversion en niveau de gris
if(image_msg->encoding == "yuv422")
{
for(unsigned int i=0; i<height*width; i++)
{
image[i]=image_msg->data[3*i];
}
}
else
{
ROS_WARN("Encoding doesn't correspond to yuv422");
return;
}
int nb_match=0;
nb_match = matcher.match(image, width, height, _num_tilt);
ROS_INFO("Match : %d", nb_match);
}
else
{
ROS_INFO("Matcher not ready to process");
}
}

View file

@ -0,0 +1,45 @@
#ifndef ROSMATCHER_HPP
#define ROSMATCHER_HPP
#include <ros/ros.h>
#include <tf/tf.h>
#include <message_filters/subscriber.h>
#include <message_filters/time_synchronizer.h>
#include <sensor_msgs/CameraInfo.h>
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/Image.h>
#include <geometry_msgs/PointStamped.h>
#include "ASIFT_matcher.hpp"
enum MATCHER_STATUS{
MATCHER_STATUS_IDLE=0,
MATCHER_STATUS_PROCESSING,
MATCHER_STATUS_WAITING_INIT};
class ROS_matcher
{
protected:
ros::NodeHandle _nh;
//Publisher ROS
ros::Publisher _center_pub;
//Subscriber ROS
// ros::Subscriber _image_sub;
//Matcher
int _num_tilt;
ASIFT_matcher matcher;
MATCHER_STATUS _status;
public:
ROS_matcher();
// ~ROS_matcher();
void cameraCallback(const sensor_msgs::CameraInfo::ConstPtr& info_msg, const sensor_msgs::Image::ConstPtr& image_msg, const sensor_msgs::PointCloud2::ConstPtr& pointcloud_msg);
};
#endif

View file

@ -0,0 +1,12 @@
#include "ROS_matcher.hpp"
int main(int argc, char *argv[])
{
ros::init(argc, argv, "ROS_matcher");
ROS_matcher ros_matcher;
ros::spin();
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

View file

@ -0,0 +1,8 @@
Book cMo for training image 005
rows: 4
cols: 4
data:
- [-0.2314201876, -0.9583649151, 0.1672763771, 0.09835545579]
- [0.7484075924, -0.06552319445, 0.6599945353, -0.0974700766]
- [-0.6215551242, 0.2779269699, 0.7324109687, 0.5499983612]
- [0; 0; 0; 1]

View file

@ -0,0 +1,8 @@
Book cMo for training image 008
rows: 4
cols: 4
data:
- [0.02063568325, -0.5653102458, -0.8246202123, 0.0403687505]
- [0.8210674394, 0.4801939642, -0.3086454546, -0.1745029756]
- [0.5704580865, -0.6706996964, 0.4740669666, 0.4630312508]
- [0, 0, 0, 1]

View file

@ -0,0 +1,9 @@
Book cMo for training image 007
rows: 4
cols: 4
data:
- [-0.03609085509, -0.3148440768, 0.9484569877, 0.04713881051]
- [-0.8006242946, 0.5771011583, 0.1611055304, 0.02971868344]
- [-0.5980787482, -0.7535432704, -0.2728998912, 0.6240615433]
- [0, 0, 0, 1]

View file

@ -0,0 +1,569 @@
// Copyright (c) 2008-2011, Guoshen Yu <yu@cmap.polytechnique.fr>
// Copyright (c) 2008-2011, Jean-Michel Morel <morel@cmla.ens-cachan.fr>
//
// WARNING:
// This file implements an algorithm possibly linked to the patent
//
// Jean-Michel Morel and Guoshen Yu, Method and device for the invariant
// affine recognition recognition of shapes (WO/2009/150361), patent pending.
//
// This file is made available for the exclusive aim of serving as
// scientific tool to verify of the soundness and
// completeness of the algorithm description. Compilation,
// execution and redistribution of this file may violate exclusive
// patents rights in certain countries.
// The situation being different for every country and changing
// over time, it is your responsibility to determine which patent
// rights restrictions apply to you before you compile, use,
// modify, or redistribute this file. A patent lawyer is qualified
// to make this determination.
// If and only if they don't conflict with any patent terms, you
// can benefit from the following license terms attached to this
// file.
//
// This program is provided for scientific and educational only:
// you can use and/or modify it for these purposes, but you are
// not allowed to redistribute this work or derivative works in
// source or executable form. A license must be obtained from the
// patent right holders for any other use.
//
//
//*------------------------ compute_asift_keypoints -------------------------*/
// Compute the ASIFT keypoints on the input image.
//
// Please report bugs and/or send comments to Guoshen Yu yu@cmap.polytechnique.fr
//
// Reference: J.M. Morel and G.Yu, ASIFT: A New Framework for Fully Affine Invariant Image
// Comparison, SIAM Journal on Imaging Sciences, vol. 2, issue 2, pp. 438-469, 2009.
// Reference: ASIFT online demo (You can try ASIFT with your own images online.)
// http://www.ipol.im/pub/algo/my_affine_sift/
/*---------------------------------------------------------------------------*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include "compute_asift_keypoints.h"
#ifdef _OPENMP
#include <omp.h>
#endif
#define ABS(x) (((x) > 0) ? (x) : (-(x)))
/* InitSigma gives the amount of smoothing applied to the image at the
first level of each octave. In effect, this determines the sampling
needed in the image domain relative to amount of smoothing. Good
values determined experimentally are in the range 1.2 to 1.8.
*/
/* float InitSigma_aa = 1.0;*/
static float InitSigma_aa = 1.6;
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
/* Gaussian convolution kernels are truncated at this many sigmas from
the center. While it is more efficient to keep this value small,
experiments show that for consistent scale-space analysis it needs
a value of about 3.0, at which point the Gaussian has fallen to
only 1% of its central value. A value of 2.0 greatly reduces
keypoint consistency, and a value of 4.0 is better than 3.0.
*/
const float GaussTruncate1 = 4.0;
/* --------------------------- Blur image --------------------------- */
/* Same as ConvBuffer, but implemented with loop unrolling for increased
speed. This is the most time intensive routine in keypoint detection,
so deserves careful attention to efficiency. Loop unrolling simply
sums 5 multiplications at a time to allow the compiler to schedule
operations better and avoid loop overhead. This almost triples
speed of previous version on a Pentium with gcc.
*/
void ConvBufferFast(float *buffer, float *kernel, int rsize, int ksize)
{
int i;
float *bp, *kp, *endkp;
float sum;
for (i = 0; i < rsize; i++) {
sum = 0.0;
bp = &buffer[i];
kp = &kernel[0];
endkp = &kernel[ksize];
/* Loop unrolling: do 5 multiplications at a time. */
// while (kp + 4 < endkp) {
// sum += (double) bp[0] * (double) kp[0] + (double) bp[1] * (double) kp[1] + (double) bp[2] * (double) kp[2] +
// (double) bp[3] * (double) kp[3] + (double) bp[4] * (double) kp[4];
// bp += 5;
// kp += 5;
// }
// /* Do 2 multiplications at a time on remaining items. */
// while (kp + 1 < endkp) {
// sum += (double) bp[0] * (double) kp[0] + (double) bp[1] * (double) kp[1];
// bp += 2;
// kp += 2;
// }
// /* Finish last one if needed. */
// if (kp < endkp) {
// sum += (double) *bp * (double) *kp;
// }
while (kp < endkp) {
sum += *bp++ * *kp++;
}
buffer[i] = sum;
}
}
/* Convolve image with the 1-D kernel vector along image rows. This
is designed to be as efficient as possible. Pixels outside the
image are set to the value of the closest image pixel.
*/
void ConvHorizontal(vector<float>& image, int width, int height, float *kernel, int ksize)
{
int rows, cols, r, c, i, halfsize;
float buffer[4000];
vector<float> pixels(width*height);
rows = height;
cols = width;
halfsize = ksize / 2;
pixels = image;
assert(cols + ksize < 4000);
for (r = 0; r < rows; r++) {
/* Copy the row into buffer with pixels at ends replicated for
half the mask size. This avoids need to check for ends
within inner loop. */
for (i = 0; i < halfsize; i++)
buffer[i] = pixels[r*cols];
for (i = 0; i < cols; i++)
buffer[halfsize + i] = pixels[r*cols+i];
for (i = 0; i < halfsize; i++)
buffer[halfsize + cols + i] = pixels[r*cols+cols-1];
ConvBufferFast(buffer, kernel, cols, ksize);
for (c = 0; c < cols; c++)
pixels[r*cols+c] = buffer[c];
}
image = pixels;
}
/* Same as ConvHorizontal, but apply to vertical columns of image.
*/
void ConvVertical(vector<float>& image, int width, int height, float *kernel, int ksize)
{
int rows, cols, r, c, i, halfsize;
float buffer[4000];
vector<float> pixels(width*height);
rows = height;
cols = width;
halfsize = ksize / 2;
pixels = image;
assert(rows + ksize < 4000);
for (c = 0; c < cols; c++) {
for (i = 0; i < halfsize; i++)
buffer[i] = pixels[c];
for (i = 0; i < rows; i++)
buffer[halfsize + i] = pixels[i*cols+c];
for (i = 0; i < halfsize; i++)
buffer[halfsize + rows + i] = pixels[(rows - 1)*cols+c];
ConvBufferFast(buffer, kernel, rows, ksize);
for (r = 0; r < rows; r++)
pixels[r*cols+c] = buffer[r];
}
image = pixels;
}
/* 1D Convolve image with a Gaussian of width sigma and store result back
in image. This routine creates the Gaussian kernel, and then applies
it in horizontal (flag_dir=0) OR vertical directions (flag_dir!=0).
*/
void GaussianBlur1D(vector<float>& image, int width, int height, float sigma, int flag_dir)
{
float x, kernel[100], sum = 0.0;
int ksize, i;
/* The Gaussian kernel is truncated at GaussTruncate sigmas from
center. The kernel size should be odd.
*/
ksize = (int)(2.0 * GaussTruncate1 * sigma + 1.0);
ksize = MAX(3, ksize); /* Kernel must be at least 3. */
if (ksize % 2 == 0) /* Make kernel size odd. */
ksize++;
assert(ksize < 100);
/* Fill in kernel values. */
for (i = 0; i <= ksize; i++) {
x = i - ksize / 2;
kernel[i] = exp(- x * x / (2.0 * sigma * sigma));
sum += kernel[i];
}
/* Normalize kernel values to sum to 1.0. */
for (i = 0; i < ksize; i++)
kernel[i] /= sum;
if (flag_dir == 0)
{
ConvHorizontal(image, width, height, kernel, ksize);
}
else
{
ConvVertical(image, width, height, kernel, ksize);
}
}
void compensate_affine_coor1(float *x0, float *y0, int w1, int h1, float t1, float t2, float Rtheta)
{
float x_ori, y_ori;
float x_tmp, y_tmp;
float x1 = *x0;
float y1 = *y0;
Rtheta = Rtheta*PI/180;
if ( Rtheta <= PI/2 )
{
x_ori = 0;
y_ori = w1 * sin(Rtheta) / t1;
}
else
{
x_ori = -w1 * cos(Rtheta) / t2;
y_ori = ( w1 * sin(Rtheta) + h1 * sin(Rtheta-PI/2) ) / t1;
}
float sin_Rtheta = sin(Rtheta);
float cos_Rtheta = cos(Rtheta);
/* project the coordinates of im1 to original image before tilt-rotation transform */
/* Get the coordinates with respect to the 'origin' of the original image before transform */
x1 = x1 - x_ori;
y1 = y1 - y_ori;
/* Invert tilt */
x1 = x1 * t2;
y1 = y1 * t1;
/* Invert rotation (Note that the y direction (vertical) is inverse to the usual concention. Hence Rtheta instead of -Rtheta to inverse the rotation.) */
x_tmp = cos_Rtheta*x1 - sin_Rtheta*y1;
y_tmp = sin_Rtheta*x1 + cos_Rtheta*y1;
x1 = x_tmp;
y1 = y_tmp;
*x0 = x1;
*y0 = y1;
}
/* -------------- MAIN FUNCTION ---------------------- */
int compute_asift_keypoints(vector<float>& image, int width, int height, int num_of_tilts, int verb, vector< vector< keypointslist > >& keys_all, siftPar &siftparameters)
// Compute ASIFT keypoints in the input image.
// Input:
// image: input image
// width, height: width and height of the input image.
// num_of_tilts: number of tilts to simulate.
// verb: 1/0 --> show/don not show verbose messages. (1 for debugging)
// keys_all (output): ASIFT keypoints. It is a 2D matrix with varying rows and columns. Each entry keys_all[tt][rr]
// stores the SIFT keypoints calculated on the image with the simulated tilt index tt and simulated rotation index rr (see the code below). In the coordinates of the keypoints,
// the affine distortions have been compensated.
// siftparameters: SIFT parameters.
//
// Output: the number of keypoints
{
vector<float> image_t, image_tmp1, image_tmp;
float t_min, t_k;
int num_tilt, tt, num_rot_t2, rr;
int fproj_o;
float fproj_p, fproj_bg;
char fproj_i;
float *fproj_x4, *fproj_y4;
// float frot_b=0;
float frot_b=128;
char *frot_k;
int counter_sim=0, num_sim;
int flag_dir = 1;
float BorderFact=6*sqrt(2.);
int num_keys_total=0;
fproj_o = 3;
fproj_p = 0;
fproj_i = 0;
fproj_bg = 0;
fproj_x4 = 0;
fproj_y4 = 0;
frot_k = 0;
num_rot_t2 = 10;
t_min = 1;
t_k = sqrt(2.);
num_tilt = num_of_tilts;
if ( num_tilt < 1)
{
printf("Number of tilts num_tilt should be equal or larger than 1. \n");
exit(-1);
}
image_tmp1 = image;
/* Calculate the number of simulations, and initialize keys_all */
keys_all = std::vector< vector< keypointslist > >(num_tilt);
for (tt = 1; tt <= num_tilt; tt++)
{
float t = t_min * pow(t_k, tt-1);
if ( t == 1 )
{
counter_sim ++;
keys_all[tt-1] = std::vector< keypointslist >(1);
}
else
{
int num_rot1 = round(num_rot_t2*t/2);
if ( num_rot1%2 == 1 )
{
num_rot1 = num_rot1 + 1;
}
num_rot1 = num_rot1 / 2;
counter_sim += num_rot1;
keys_all[tt-1] = std::vector< keypointslist >(num_rot1);
}
}
num_sim = counter_sim;
if ( verb )
{
printf("%d affine simulations will be performed. \n", num_sim);
}
counter_sim = 0;
/* Affine simulation (rotation+tilt simulation) */
// Loop on tilts.
#ifdef _OPENMP
omp_set_nested(1);
#endif
#pragma omp parallel for private(tt)
for (tt = 1; tt <= num_tilt; tt++)
{
float t = t_min * pow(t_k, tt-1);
float t1 = 1;
float t2 = 1/t;
// If tilt t = 1, do not simulate rotation.
if ( t == 1 )
{
// copy the image from vector to array as compute_sift_keypoints uses only array.
float *image_tmp1_float = new float[width*height];
for (int cc = 0; cc < width*height; cc++)
image_tmp1_float[cc] = image_tmp1[cc];
compute_sift_keypoints(image_tmp1_float,keys_all[tt-1][0],width,height,siftparameters);
delete[] image_tmp1_float;
}
else
{
// The number of rotations to simulate under the current tilt.
int num_rot1 = round(num_rot_t2*t/2);
if ( num_rot1%2 == 1 )
{
num_rot1 = num_rot1 + 1;
}
num_rot1 = num_rot1 / 2;
float delta_theta = PI/num_rot1;
// Loop on rotations.
#pragma omp parallel for private(rr)
for ( int rr = 1; rr <= num_rot1; rr++ )
{
float theta = delta_theta * (rr-1);
theta = theta * 180 / PI;
vector<float> image_t;
int width_r, height_r;
// simulate a rotation: rotate the image with an angle theta. (the outside of the rotated image are padded with the value frot_b)
frot(image, image_t, width, height, &width_r, &height_r, &theta, &frot_b , frot_k);
/* Tilt */
int width_t = (int) (width_r * t1);
int height_t = (int) (height_r * t2);
int fproj_sx = width_t;
int fproj_sy = height_t;
float fproj_x1 = 0;
float fproj_y1 = 0;
float fproj_x2 = width_t;
float fproj_y2 = 0;
float fproj_x3 = 0;
float fproj_y3 = height_t;
/* Anti-aliasing filtering along vertical direction */
/* sigma_aa = InitSigma_aa * log2(t);*/
float sigma_aa = InitSigma_aa * t / 2;
GaussianBlur1D(image_t,width_r,height_r,sigma_aa,flag_dir);
// simulate a tilt: subsample the image along the vertical axis by a factor of t.
vector<float> image_tmp(width_t*height_t);
fproj (image_t, image_tmp, width_r, height_r, &fproj_sx, &fproj_sy, &fproj_bg, &fproj_o, &fproj_p, &fproj_i , fproj_x1 , fproj_y1 , fproj_x2 , fproj_y2 , fproj_x3 , fproj_y3, fproj_x4, fproj_y4);
vector<float> image_tmp1 = image_tmp;
if ( verb )
{
printf("Rotation theta = %.2f, Tilt t = %.2f. w=%d, h=%d, sigma_aa=%.2f, \n", theta, t, width_t, height_t, sigma_aa);
}
float *image_tmp1_float = new float[width_t*height_t];
for (int cc = 0; cc < width_t*height_t; cc++)
image_tmp1_float[cc] = image_tmp1[cc];
// compute SIFT keypoints on simulated image.
keypointslist keypoints;
keypointslist keypoints_filtered;
compute_sift_keypoints(image_tmp1_float,keypoints,width_t,height_t,siftparameters);
delete[] image_tmp1_float;
/* check if the keypoint is located on the boundary of the parallelogram (i.e., the boundary of the distorted input image). If so, remove it to avoid boundary artifacts. */
if ( keypoints.size() != 0 )
{
for ( int cc = 0; cc < (int) keypoints.size(); cc++ )
{
float x0, y0, x1, y1, x2, y2, x3, y3 ,x4, y4, d1, d2, d3, d4, scale1, theta1, sin_theta1, cos_theta1, BorderTh;
x0 = keypoints[cc].x;
y0 = keypoints[cc].y;
scale1= keypoints[cc].scale;
theta1 = theta * PI / 180;
sin_theta1 = sin(theta1);
cos_theta1 = cos(theta1);
/* the coordinates of the 4 submits of the parallelogram */
if ( theta <= 90 )
{
x1 = height * sin_theta1;
y1 = 0;
y2 = width * sin_theta1;
x3 = width * cos_theta1;
x4 = 0;
y4 = height * cos_theta1;
x2 = x1 + x3;
y3 = y2 + y4;
/* note that the vertical direction goes from top to bottom!!!
The calculation above assumes that the vertical direction goes from the bottom to top. Thus the vertical coordinates need to be reversed!!! */
y1 = y3 - y1;
y2 = y3 - y2;
y4 = y3 - y4;
y3 = 0;
y1 = y1 * t2;
y2 = y2 * t2;
y3 = y3 * t2;
y4 = y4 * t2;
}
else
{
y1 = -height * cos_theta1;
x2 = height * sin_theta1;
x3 = 0;
y3 = width * sin_theta1;
x4 = -width * cos_theta1;
y4 = 0;
x1 = x2 + x4;
y2 = y1 + y3;
/* note that the vertical direction goes from top to bottom!!!
The calculation above assumes that the vertical direction goes from the bottom to top. Thus the vertical coordinates need to be reversed!!! */
y1 = y2 - y1;
y3 = y2 - y3;
y4 = y2 - y4;
y2 = 0;
y1 = y1 * t2;
y2 = y2 * t2;
y3 = y3 * t2;
y4 = y4 * t2;
}
/* the distances from the keypoint to the 4 sides of the parallelogram */
d1 = ABS((x2-x1)*(y1-y0)-(x1-x0)*(y2-y1)) / sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
d2 = ABS((x3-x2)*(y2-y0)-(x2-x0)*(y3-y2)) / sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));
d3 = ABS((x4-x3)*(y3-y0)-(x3-x0)*(y4-y3)) / sqrt((x4-x3)*(x4-x3)+(y4-y3)*(y4-y3));
d4 = ABS((x1-x4)*(y4-y0)-(x4-x0)*(y1-y4)) / sqrt((x1-x4)*(x1-x4)+(y1-y4)*(y1-y4));
BorderTh = BorderFact*scale1;
if (!((d1<BorderTh) || (d2<BorderTh) || (d3<BorderTh) || (d4<BorderTh) ))
{
// Normalize the coordinates of the matched points by compensate the simulate affine transformations
compensate_affine_coor1(&x0, &y0, width, height, 1/t2, t1, theta);
keypoints[cc].x = x0;
keypoints[cc].y = y0;
keypoints_filtered.push_back(keypoints[cc]);
}
}
}
keys_all[tt-1][rr-1] = keypoints_filtered;
}
}
}
{
for (tt = 0; tt < (int) keys_all.size(); tt++)
for (rr = 0; rr < (int) keys_all[tt].size(); rr++)
{
num_keys_total += (int) keys_all[tt][rr].size();
}
printf("%d ASIFT keypoints are detected. \n", num_keys_total);
}
return num_keys_total;
}

View file

@ -0,0 +1,53 @@
// Copyright (c) 2008-2011, Guoshen Yu <yu@cmap.polytechnique.fr>
// Copyright (c) 2008-2011, Jean-Michel Morel <morel@cmla.ens-cachan.fr>
//
// WARNING:
// This file implements an algorithm possibly linked to the patent
//
// Jean-Michel Morel and Guoshen Yu, Method and device for the invariant
// affine recognition recognition of shapes (WO/2009/150361), patent pending.
//
// This file is made available for the exclusive aim of serving as
// scientific tool to verify of the soundness and
// completeness of the algorithm description. Compilation,
// execution and redistribution of this file may violate exclusive
// patents rights in certain countries.
// The situation being different for every country and changing
// over time, it is your responsibility to determine which patent
// rights restrictions apply to you before you compile, use,
// modify, or redistribute this file. A patent lawyer is qualified
// to make this determination.
// If and only if they don't conflict with any patent terms, you
// can benefit from the following license terms attached to this
// file.
//
// This program is provided for scientific and educational only:
// you can use and/or modify it for these purposes, but you are
// not allowed to redistribute this work or derivative works in
// source or executable form. A license must be obtained from the
// patent right holders for any other use.
//
//
//*------------------------ compute_asift_keypoints -------------------------*/
// Compute the ASIFT keypoints on the input image.
//
// Please report bugs and/or send comments to Guoshen Yu yu@cmap.polytechnique.fr
//
// Reference: J.M. Morel and G.Yu, ASIFT: A New Framework for Fully Affine Invariant Image
// Comparison, SIAM Journal on Imaging Sciences, vol. 2, issue 2, pp. 438-469, 2009.
// Reference: ASIFT online demo (You can try ASIFT with your own images online.)
// http://www.ipol.im/pub/algo/my_affine_sift/
/*---------------------------------------------------------------------------*/
#include "library.h"
#include "demo_lib_sift.h"
#include "frot.h"
#include "fproj.h"
#include <vector>
using namespace std;
int compute_asift_keypoints(vector<float>& image, int width, int height, int num_of_tilts, int verb, vector< vector< keypointslist > >& keys_all, siftPar &siftparameters);
void GaussianBlur1D(vector<float>& image, int width, int height, float sigma, int flag_dir);

View file

@ -0,0 +1,791 @@
// Copyright (c) 2008-2011, Guoshen Yu <yu@cmap.polytechnique.fr>
// Copyright (c) 2008-2011, Jean-Michel Morel <morel@cmla.ens-cachan.fr>
//
// WARNING:
// This file implements an algorithm possibly linked to the patent
//
// Jean-Michel Morel and Guoshen Yu, Method and device for the invariant
// affine recognition recognition of shapes (WO/2009/150361), patent pending.
//
// This file is made available for the exclusive aim of serving as
// scientific tool to verify of the soundness and
// completeness of the algorithm description. Compilation,
// execution and redistribution of this file may violate exclusive
// patents rights in certain countries.
// The situation being different for every country and changing
// over time, it is your responsibility to determine which patent
// rights restrictions apply to you before you compile, use,
// modify, or redistribute this file. A patent lawyer is qualified
// to make this determination.
// If and only if they don't conflict with any patent terms, you
// can benefit from the following license terms attached to this
// file.
//
// This program is provided for scientific and educational only:
// you can use and/or modify it for these purposes, but you are
// not allowed to redistribute this work or derivative works in
// source or executable form. A license must be obtained from the
// patent right holders for any other use.
//
//
//*------------------------ compute_asift_matches-- -------------------------*/
// Match the ASIFT keypoints.
//
// Please report bugs and/or send comments to Guoshen Yu yu@cmap.polytechnique.fr
//
// Reference: J.M. Morel and G.Yu, ASIFT: A New Framework for Fully Affine Invariant Image
// Comparison, SIAM Journal on Imaging Sciences, vol. 2, issue 2, pp. 438-469, 2009.
// Reference: ASIFT online demo (You can try ASIFT with your own images online.)
// http://www.ipol.im/pub/algo/my_affine_sift/
/*---------------------------------------------------------------------------*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#ifdef _OPENMP
#include <omp.h>
#endif
#include "compute_asift_matches.h"
#include "libMatch/match.h"
#include "orsa.h"
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
/* Remove the repetitive matches that appear in different simulations and retain only one */
void unique_match1(matchingslist &seg_in, matchingslist &seg_out, vector< vector <float> > &Minfoall_in, vector< vector <float> > &Minfoall_out)
{
int i_in, i_out;
float x1_in, x2_in, y1_in, y2_in, x1_out, x2_out, y1_out, y2_out;
int flag_unique;
float d1, d2;
int Th2 = 2;
seg_out.push_back(seg_in[0]);
Minfoall_out.push_back(Minfoall_in[0]);
/* For other matches */
if ( seg_in.size() > 1 )
{
/* check if a match is unique. if yes, copy */
/* Bug fix by Xiaoyu Sun (Sichuan university) (Dec 13, 2015) */
/* Original version
matchingslist::iterator ptr_in = seg_in.begin();
for ( i_in = 1; i_in < (int) seg_in.size(); i_in++, ptr_in++ )
*/
/* Bug fixed */
matchingslist::iterator ptr_in = seg_in.begin();
ptr_in++;
for ( i_in = 1; i_in < (int) seg_in.size(); i_in++, ptr_in++ )
{
x1_in = ptr_in->first.x;
y1_in = ptr_in->first.y;
x2_in = ptr_in->second.x;
y2_in = ptr_in->second.y;
flag_unique = 1;
matchingslist::iterator ptr_out = seg_out.begin();
for ( i_out = 0; i_out < (int) seg_out.size(); i_out++, ptr_out++ )
{
x1_out = ptr_out->first.x;
y1_out = ptr_out->first.y;
x2_out = ptr_out->second.x;
y2_out = ptr_out->second.y;
d1 = (x1_in - x1_out)*(x1_in - x1_out) + (y1_in - y1_out)*(y1_in - y1_out);
d2 = (x2_in - x2_out)*(x2_in - x2_out) + (y2_in - y2_out)*(y2_in - y2_out);
if ( ( d1 <= Th2) && ( d2 <= Th2) )
{
flag_unique = 0;
continue;
}
}
if ( flag_unique == 1 )
{
seg_out.push_back(seg_in[i_in]);
Minfoall_out.push_back(Minfoall_in[i_in]);
}
}
}
}
/* Remove the ALL one-to-multiple matches. */
void clean_match1(matchingslist &seg_in, matchingslist &seg_out, vector< vector <float> > &Minfoall_in, vector< vector <float> > &Minfoall_out)
{
int i1, i2;
float x1_in, x2_in, y1_in, y2_in, x1_out, x2_out, y1_out, y2_out;
// Guoshen Yu, 2010.09.22, Windows version
// int flag_unique[seg_in.size()];
int tmp_size = seg_in.size();
int *flag_unique = new int[tmp_size];
int sum_flag=0;
float d1, d2;
int Th1 = 1;
int Th2 = 4;
for ( i1 = 0; i1 < (int) seg_in.size(); i1++ )
{
flag_unique[i1] = 1;
}
/* Set the flag of redundant matches to 0. */
matchingslist::iterator ptr_in = seg_in.begin();
for ( i1 = 0; i1 < (int) seg_in.size() - 1; i1++, ptr_in++ )
{
x1_in = ptr_in->first.x;
y1_in = ptr_in->first.y;
x2_in = ptr_in->second.x;
y2_in = ptr_in->second.y;
matchingslist::iterator ptr_out = ptr_in+1;
for ( i2 = i1 + 1; i2 < (int) seg_in.size(); i2++, ptr_out++ )
{
x1_out = ptr_out->first.x;
y1_out = ptr_out->first.y;
x2_out = ptr_out->second.x;
y2_out = ptr_out->second.y;
d1 = (x1_in - x1_out)*(x1_in - x1_out) + (y1_in - y1_out)*(y1_in - y1_out);
d2 = (x2_in - x2_out)*(x2_in - x2_out) + (y2_in - y2_out)*(y2_in - y2_out);
/* If redundant, set flags of both elements to 0.*/
if ( ( ( d1 <= Th1) && ( d2 > Th2) ) || ( ( d1 > Th2) && ( d2 <= Th1) ) )
{
flag_unique[i1] = 0;
flag_unique[i2] = 0;
}
}
}
for ( i1 = 0; i1 < (int) seg_in.size(); i1++ )
{
sum_flag += flag_unique[i1];
}
/* Copy the matches that are not redundant */
if ( sum_flag > 0 )
{
for ( i1 = 0; i1 < (int) seg_in.size(); i1++ )
{
if ( flag_unique[i1] == 1 )
{
seg_out.push_back(seg_in[i1]);
Minfoall_out.push_back(Minfoall_in[i1]);
}
}
}
else
{
printf("Warning: all matches are redundant and are thus removed! This step of match cleaning is short circuited. (Normally this should not happen...)\n");
}
// Guoshen Yu, 2010.09.22, Windows version
delete [] flag_unique;
}
/* Remove the ALL multiple-to-one matches */
void clean_match2(matchingslist &seg_in, matchingslist &seg_out, vector< vector <float> > &Minfoall_in, vector< vector <float> > &Minfoall_out)
{
int i1, i2;
float x1_in, x2_in, y1_in, y2_in, x1_out, x2_out, y1_out, y2_out;
// Guoshen Yu, 2010.09.22, Windows version
// int flag_unique[seg_in.size()];
int tmp_size = seg_in.size();
int *flag_unique = new int[tmp_size];
int sum_flag=0;
float d1, d2;
int Th1 = 1;
int Th2 = 4;
for ( i1 = 0; i1 < (int) seg_in.size(); i1++ )
{
flag_unique[i1] = 1;
}
/* Set the flag of redundant matches to 0. */
matchingslist::iterator ptr_in = seg_in.begin();
for ( i1 = 0; i1 < (int) seg_in.size() - 1; i1++, ptr_in++ )
{
x1_in = ptr_in->first.x;
y1_in = ptr_in->first.y;
x2_in = ptr_in->second.x;
y2_in = ptr_in->second.y;
matchingslist::iterator ptr_out = ptr_in+1;
for ( i2 = i1 + 1; i2 < (int) seg_in.size(); i2++, ptr_out++ )
{
x1_out = ptr_out->first.x;
y1_out = ptr_out->first.y;
x2_out = ptr_out->second.x;
y2_out = ptr_out->second.y;
d1 = (x1_in - x1_out)*(x1_in - x1_out) + (y1_in - y1_out)*(y1_in - y1_out);
d2 = (x2_in - x2_out)*(x2_in - x2_out) + (y2_in - y2_out)*(y2_in - y2_out);
/* If redundant, set flags of both elements to 0.*/
if ( ( d1 > Th2) && ( d2 <= Th1) )
{
flag_unique[i1] = 0;
flag_unique[i2] = 0;
}
}
}
for ( i1 = 0; i1 < (int) seg_in.size(); i1++ )
{
sum_flag += flag_unique[i1];
}
/* Copy the matches that are not redundant */
if ( sum_flag > 0 )
{
for ( i1 = 0; i1 < (int) seg_in.size(); i1++ )
{
if ( flag_unique[i1] == 1 )
{
seg_out.push_back(seg_in[i1]);
Minfoall_out.push_back(Minfoall_in[i1]);
}
}
}
else
{
printf("Warning: all matches are redundant and are thus removed! This step of match cleaning is short circuited. (Normally this should not happen...)\n");
}
// Guoshen Yu, 2010.09.22, Windows version
delete [] flag_unique;
}
// Normalize the coordinates of the matched points by compensating the simulate affine transformations
void compensate_affine_coor(matching &matching1, int w1, int h1, int w2, int h2, float t1, float t2, float Rtheta, float t_im2_1, float t_im2_2, float Rtheta2)
{
float x_ori, y_ori;
float x_ori2, y_ori2, x_tmp, y_tmp;
float x1, y1, x2, y2;
Rtheta = Rtheta*PI/180;
if ( Rtheta <= PI/2 )
{
x_ori = 0;
y_ori = w1 * sin(Rtheta) / t1;
}
else
{
x_ori = -w1 * cos(Rtheta) / t2;
y_ori = ( w1 * sin(Rtheta) + h1 * sin(Rtheta-PI/2) ) / t1;
}
Rtheta2 = Rtheta2*PI/180;
if ( Rtheta2 <= PI/2 )
{
x_ori2 = 0;
y_ori2 = w2 * sin(Rtheta2) / t_im2_1;
}
else
{
x_ori2 = -w2 * cos(Rtheta2) / t_im2_2;
y_ori2 = ( w2 * sin(Rtheta2) + h2 * sin(Rtheta2-PI/2) ) / t_im2_1;
}
float sin_Rtheta = sin(Rtheta);
float cos_Rtheta = cos(Rtheta);
float sin_Rtheta2 = sin(Rtheta2);
float cos_Rtheta2 = cos(Rtheta2);
x1 = matching1.first.x;
y1 = matching1.first.y;
x2 = matching1.second.x;
y2 = matching1.second.y;
/* project the coordinates of im1 to original image before tilt-rotation transform */
/* Get the coordinates with respect to the 'origin' of the original image before transform */
x1 = x1 - x_ori;
y1 = y1 - y_ori;
/* Invert tilt */
x1 = x1 * t2;
y1 = y1 * t1;
/* Invert rotation (Note that the y direction (vertical) is inverse to the usual concention. Hence Rtheta instead of -Rtheta to inverse the rotation.) */
x_tmp = cos_Rtheta*x1 - sin_Rtheta*y1;
y_tmp = sin_Rtheta*x1 + cos_Rtheta*y1;
x1 = x_tmp;
y1 = y_tmp;
/* Coordinate projection on image2 */
/* Get the coordinates with respect to the 'origin' of the original image before transform */
x2 = x2 - x_ori2;
y2 = y2 - y_ori2;
/* Invert tilt */
x2 = x2 * t_im2_2;
y2 = y2 * t_im2_1;
/* Invert rotation (Note that the y direction (vertical) is inverse to the usual concention. Hence Rtheta instead of -Rtheta to inverse the rotation.) */
x_tmp = cos_Rtheta2*x2 - sin_Rtheta2*y2;
y_tmp = sin_Rtheta2*x2 + cos_Rtheta2*y2;
x2 = x_tmp;
y2 = y_tmp;
matching1.first.x = x1;
matching1.first.y = y1;
matching1.second.x = x2;
matching1.second.y = y2;
}
int compute_asift_matches(int num_of_tilts1, int num_of_tilts2, int w1, int h1, int w2, int h2, int verb, vector< vector< keypointslist > >& keys1, vector< vector< keypointslist > >& keys2, matchingslist &matchings, siftPar &siftparameters)
// Match the ASIFT keypoints.
// Input:
// num_of_tilts1, num_of_tilts2: number of tilts that have been simulated on the two images. (They can be different.)
// w1, h1, w2, h2: widht/height of image1/image2.
// verb: 1/0 --> show/don not show verbose messages. (1 for debugging)
// keys1, keys2: ASIFT keypoints of image1/image2. (They should be calculated with compute_asift_keypoints.)
// matchings (output): the coordinates (col1, row1, col2, row2) of all the matching points.
//
// Output: the number of matching points.
{
float t_min, t_k, t;
int num_tilt1, num_tilt2, tt, num_rot_t2, num_rot1, rr;
int cc;
int tt2, rr2, num_rot1_2;
float t_im2;
/* It stores the coordinates of ALL matches points of ALL affine simulations */
vector< vector <float> > Minfoall;
int Tmin = 8;
float nfa_max = -2;
num_rot_t2 = 10;
t_min = 1;
t_k = sqrt(2.);
num_tilt1 = num_of_tilts1;
num_tilt2 = num_of_tilts2;
if ( ( num_tilt1 < 1 ) || ( num_tilt2 < 1 ) )
{
printf("Number of tilts num_tilt should be equal or larger than 1. \n");
exit(-1);
}
/* Initialize the vector structure for the matching points */
std::vector< vector< vector < vector < matchingslist > > > > matchings_vec(num_tilt1);
std::vector< vector< vector< vector< vector< vector <float> > > > > > Minfoall_vec(num_tilt1);
for (tt = 1; tt <= num_tilt1; tt++)
{
t = t_min * pow(t_k, tt-1);
if ( t == 1 )
{
num_rot1 = 1;
}
else
{
num_rot1 = round(num_rot_t2*t/2);
if ( num_rot1%2 == 1 )
{
num_rot1 = num_rot1 + 1;
}
num_rot1 = num_rot1 / 2;
}
matchings_vec[tt-1].resize(num_rot1);
Minfoall_vec[tt-1].resize(num_rot1);
for ( rr = 1; rr <= num_rot1; rr++ )
{
matchings_vec[tt-1][rr-1].resize(num_tilt2);
Minfoall_vec[tt-1][rr-1].resize(num_tilt2);
for (tt2 = 1; tt2 <= num_tilt2; tt2++)
{
t_im2 = t_min * pow(t_k, tt2-1);
if ( t_im2 == 1 )
{
num_rot1_2 = 1;
}
else
{
num_rot1_2 = round(num_rot_t2*t_im2/2);
if ( num_rot1_2%2 == 1 )
{
num_rot1_2 = num_rot1_2 + 1;
}
num_rot1_2 = num_rot1_2 / 2;
}
matchings_vec[tt-1][rr-1][tt2-1].resize(num_rot1_2);
Minfoall_vec[tt-1][rr-1][tt2-1].resize(num_rot1_2);
}
}
}
///*
// * setup the tilt and rotation parameters
// * for all the loops, this vector will hold
// * the following parameters:
// * tt, num_rot1, rr, tt2, num_rot1_2, rr2
// */
//vector<int> tilt_rot;
///* loop on tilts for image 1 */
//for (int tt = 1; tt <= num_tilt1; tt++)
//{
// float t = t_min * pow(t_k, tt-1);
// int num_rot1;
// /* if tilt t = 1, do not simulate rotation. */
// if ( 1 == tt )
// num_rot1 = 1;
// else
// {
// /* number of rotations to simulate */
// num_rot1 = round(num_rot_t2 * t / 2);
// if ( num_rot1%2 == 1 )
// num_rot1 = num_rot1 + 1;
// num_rot1 = num_rot1 / 2;
// }
// /* loop on rotations for image 1 */
// for (int rr = 1; rr <= num_rot1; rr++ )
// {
// /* loop on tilts for image 2 */
// for (int tt2 = 1; tt2 <= num_tilt2; tt2++)
// {
// float t_im2 = t_min * pow(t_k, tt2-1);
// int num_rot1_2;
// if ( tt2 == 1 )
// num_rot1_2 = 1;
// else
// {
// num_rot1_2 = round(num_rot_t2 * t_im2 / 2);
// if ( num_rot1_2%2 == 1 )
// num_rot1_2 = num_rot1_2 + 1;
// num_rot1_2 = num_rot1_2 / 2;
// }
// /* loop on rotations for image 2 */
// for (int rr2 = 1; rr2 <= num_rot1_2; rr2++ )
// {
// tilt_rot.push_back(tt);
// tilt_rot.push_back(num_rot1);
// tilt_rot.push_back(rr);
// tilt_rot.push_back(tt2);
// tilt_rot.push_back(num_rot1_2);
// tilt_rot.push_back(rr2);
// }
// }
// }
//}
/* Calculate the number of simulations */
#ifdef _OPENMP
omp_set_nested(1);
#endif
// loop on tilts for image 1.
#pragma omp parallel for private(tt)
for (int tt = 1; tt <= num_tilt1; tt++)
{
float t = t_min * pow(t_k, tt-1);
/* Attention: the t1, t2 do not follow the same convention as in compute_asift_keypoints */
float t1 = t;
float t2 = 1;
int num_rot1;
// If tilt t = 1, do not simulate rotation.
if ( tt == 1 )
{
num_rot1 = 1;
}
else
{
// The number of rotations to simulate under the current tilt.
num_rot1 = round(num_rot_t2*t/2);
if ( num_rot1%2 == 1 )
{
num_rot1 = num_rot1 + 1;
}
num_rot1 = num_rot1 / 2;
}
float delta_theta = PI/num_rot1;
// Loop on rotations for image 1.
#pragma omp parallel for private(rr)
for ( int rr = 1; rr <= num_rot1; rr++ )
{
float theta = delta_theta * (rr-1);
theta = theta * 180 / PI;
/* Read the keypoints of image 1 */
keypointslist keypoints1 = keys1[tt-1][rr-1];
// loop on tilts for image 2.
#pragma omp parallel for private(tt2)
for (int tt2 = 1; tt2 <= num_tilt2; tt2++)
{
float t_im2 = t_min * pow(t_k, tt2-1);
/* Attention: the t1, t2 do not follow the same convention as in asift_v1.c */
float t_im2_1 = t_im2;
float t_im2_2 = 1;
int num_rot1_2;
if ( tt2 == 1 )
{
num_rot1_2 = 1;
}
else
{
num_rot1_2 = round(num_rot_t2*t_im2/2);
if ( num_rot1_2%2 == 1 )
{
num_rot1_2 = num_rot1_2 + 1;
}
num_rot1_2 = num_rot1_2 / 2;
}
float delta_theta2 = PI/num_rot1_2;
#pragma omp parallel for private(rr2)
// Loop on rotations for image 2.
for ( int rr2 = 1; rr2 <= num_rot1_2; rr2++ )
{
float theta2 = delta_theta2 * (rr2-1);
theta2 = theta2 * 180 / PI;
/* Read the keypoints of image2. */
keypointslist keypoints2 = keys2[tt2-1][rr2-1];
// Match the keypoints of image1 and image2.
matchingslist matchings1;
compute_sift_matches(keypoints1,keypoints2,matchings1,siftparameters);
if ( verb )
{
printf("t1=%.2f, theta1=%.2f, num keys1 = %d, t2=%.2f, theta2=%.2f, num keys2 = %d, num matches=%d\n", t, theta, (int) keypoints1.size(), t_im2, theta2, (int) keypoints2.size(), (int) matchings1.size());
}
/* Store the matches */
if ( matchings1.size() > 0 )
{
matchings_vec[tt-1][rr-1][tt2-1][rr2-1] = matchingslist(matchings1.size());
Minfoall_vec[tt-1][rr-1][tt2-1][rr2-1].resize(matchings1.size());
for ( int cc = 0; cc < (int) matchings1.size(); cc++ )
{
///// In the coordinates the affine transformations have been normalized already in compute_asift_keypoints. So no need to normalize here.
// Normalize the coordinates of the matched points by compensating the simulate affine transformations
// compensate_affine_coor(matchings1[cc], w1, h1, w2, h2, t1, t2, theta, t_im2_1, t_im2_2, theta2);
matchings_vec[tt-1][rr-1][tt2-1][rr2-1][cc] = matchings1[cc];
vector<float> Minfo_1match(6);
Minfo_1match[0] = t1;
Minfo_1match[1] = t2;
Minfo_1match[2] = theta;
Minfo_1match[3] = t_im2_1;
Minfo_1match[4] = t_im2_2;
Minfo_1match[5] = theta2;
Minfoall_vec[tt-1][rr-1][tt2-1][rr2-1][cc] = Minfo_1match;
}
}
}
}
}
}
// Move the matches to a 1D vector
for (tt = 1; tt <= num_tilt1; tt++)
{
t = t_min * pow(t_k, tt-1);
if ( t == 1 )
{
num_rot1 = 1;
}
else
{
num_rot1 = round(num_rot_t2*t/2);
if ( num_rot1%2 == 1 )
{
num_rot1 = num_rot1 + 1;
}
num_rot1 = num_rot1 / 2;
}
for ( rr = 1; rr <= num_rot1; rr++ )
{
for (tt2 = 1; tt2 <= num_tilt2; tt2++)
{
t_im2 = t_min * pow(t_k, tt2-1);
if ( t_im2 == 1 )
{
num_rot1_2 = 1;
}
else
{
num_rot1_2 = round(num_rot_t2*t_im2/2);
if ( num_rot1_2%2 == 1 )
{
num_rot1_2 = num_rot1_2 + 1;
}
num_rot1_2 = num_rot1_2 / 2;
}
for ( rr2 = 1; rr2 <= num_rot1_2; rr2++ )
{
for ( cc=0; cc < (int) matchings_vec[tt-1][rr-1][tt2-1][rr2-1].size(); cc++ )
{
matchings.push_back(matchings_vec[tt-1][rr-1][tt2-1][rr2-1][cc]);
Minfoall.push_back(Minfoall_vec[tt-1][rr-1][tt2-1][rr2-1][cc]);
}
}
}
}
}
if ( verb )
{
printf("The number of matches is %d \n", (int) matchings.size());
}
if ( matchings.size() > 0 )
{
/* Remove the repetitive matches that appear in different simulations and retain only one. */
// Since tilts are simuated on both image 1 and image 2, it is normal to have repetitive matches.
matchingslist matchings_unique;
vector< vector<float> > Minfoall_unique;
unique_match1(matchings, matchings_unique, Minfoall, Minfoall_unique);
matchings = matchings_unique;
Minfoall = Minfoall_unique;
if ( verb )
{
printf("The number of unique matches is %d \n", (int) matchings.size());
}
// There often appear to be some one-to-multiple/multiple-to-one matches (one point in image 1 matches with many points in image 2/vice versa).
// This is an artifact of SIFT on interpolated images, as the interpolation tends to create some auto-similar structures (steps for example).
// These matches need to be removed.
/* Separating the removal of multiple-to-one and one-to-multiple in two steps:
- first remove multiple-to-one
- then remove one-to-multiple
This allows to avoid removing some good matches: multiple-to-one matches is much more frequent than one-to-multiple. Sometimes some of the feature points in image 1 that take part in "multiple-to-one" bad matches have also correct matches in image 2. The modified scheme avoid removing these good matches. */
// Remove to multiple-to-one matches
matchings_unique.clear();
Minfoall_unique.clear();
clean_match2(matchings, matchings_unique, Minfoall, Minfoall_unique);
matchings = matchings_unique;
Minfoall = Minfoall_unique;
// Remove to one-to-multiple matches
matchings_unique.clear();
Minfoall_unique.clear();
clean_match1(matchings, matchings_unique, Minfoall, Minfoall_unique);
matchings = matchings_unique;
Minfoall = Minfoall_unique;
if ( verb )
{
printf("The number of final matches is %d \n", (int) matchings.size());
}
// If enough matches to do epipolar filtering
if ( (int) matchings.size() >= Tmin )
{
//////// Use ORSA to filter out the incorrect matches.
// store the coordinates of the matching points
vector<Match> match_coor;
for ( cc = 0; cc < (int) matchings.size(); cc++ )
{
Match match1_coor;
match1_coor.x1 = matchings[cc].first.x;
match1_coor.y1 = matchings[cc].first.y;
match1_coor.x2 = matchings[cc].second.x;
match1_coor.y2 = matchings[cc].second.y;
match_coor.push_back(match1_coor);
}
std::vector<float> index;
// Guoshen Yu, 2010.09.23
// index.clear();
int t_value_orsa=10000;
int verb_value_orsa=0;
int n_flag_value_orsa=0;
int mode_value_orsa=2;
int stop_value_orsa=0;
// epipolar filtering with the Moisan-Stival ORSA algorithm.
// float nfa = orsa(w1, h1, match_coor, index, t_value_orsa, verb_value_orsa, n_flag_value_orsa, mode_value_orsa, stop_value_orsa);
float nfa = orsa((w1+w2)/2, (h1+h2)/2, match_coor, index, t_value_orsa, verb_value_orsa, n_flag_value_orsa, mode_value_orsa, stop_value_orsa);
// if the matching is significant, register the good matches
if ( nfa < nfa_max )
{
// extract meaningful matches
matchings_unique.clear();
Minfoall_unique.clear();
for ( cc = 0; cc < (int) index.size(); cc++ )
{
matchings_unique.push_back(matchings[(int)index[cc]]);
Minfoall_unique.push_back(Minfoall[(int)index[cc]]);
}
matchings = matchings_unique;
Minfoall = Minfoall_unique;
cout << "The two images match! " << matchings.size() << " matchings are identified. log(nfa)=" << nfa << "." << endl;
}
else
{
matchings.clear();
Minfoall.clear();
cout << "The two images do not match. The matching is not significant: log(nfa)=" << nfa << "." << endl;
}
}
else
{
matchings.clear();
Minfoall.clear();
cout << "The two images do not match. Not enough matches to do epipolar filtering." << endl;
}
}
else
{
cout << "The two images do not match.\n" << endl;
}
return matchings.size();
}

View file

@ -0,0 +1,51 @@
// Copyright (c) 2008-2011, Guoshen Yu <yu@cmap.polytechnique.fr>
// Copyright (c) 2008-2011, Jean-Michel Morel <morel@cmla.ens-cachan.fr>
//
// WARNING:
// This file implements an algorithm possibly linked to the patent
//
// Jean-Michel Morel and Guoshen Yu, Method and device for the invariant
// affine recognition recognition of shapes (WO/2009/150361), patent pending.
//
// This file is made available for the exclusive aim of serving as
// scientific tool to verify of the soundness and
// completeness of the algorithm description. Compilation,
// execution and redistribution of this file may violate exclusive
// patents rights in certain countries.
// The situation being different for every country and changing
// over time, it is your responsibility to determine which patent
// rights restrictions apply to you before you compile, use,
// modify, or redistribute this file. A patent lawyer is qualified
// to make this determination.
// If and only if they don't conflict with any patent terms, you
// can benefit from the following license terms attached to this
// file.
//
// This program is provided for scientific and educational only:
// you can use and/or modify it for these purposes, but you are
// not allowed to redistribute this work or derivative works in
// source or executable form. A license must be obtained from the
// patent right holders for any other use.
//
//
//*------------------------ compute_asift_matches-- -------------------------*/
// Match the ASIFT keypoints.
//
// Please report bugs and/or send comments to Guoshen Yu yu@cmap.polytechnique.fr
//
// Reference: J.M. Morel and G.Yu, ASIFT: A New Framework for Fully Affine Invariant Image
// Comparison, SIAM Journal on Imaging Sciences, vol. 2, issue 2, pp. 438-469, 2009.
// Reference: ASIFT online demo (You can try ASIFT with your own images online.)
// http://www.ipol.im/pub/algo/my_affine_sift/
/*---------------------------------------------------------------------------*/
#include "library.h"
#include "demo_lib_sift.h"
#include "frot.h"
#include "fproj.h"
#include <vector>
using namespace std;
int compute_asift_matches(int num_of_tilts1, int num_of_tilts2, int w1, int h1, int w2, int h2, int verb, vector< vector< keypointslist > >& keys1, vector< vector< keypointslist > >& keys2, matchingslist &matchings, siftPar &siftparameters);

1222
asift_match/src/demo_lib_sift.cpp Executable file

File diff suppressed because it is too large Load diff

298
asift_match/src/demo_lib_sift.h Executable file
View file

@ -0,0 +1,298 @@
// Authors: Unknown. Please, if you are the author of this file, or if you
// know who are the authors of this file, let us know, so we can give the
// adequate credits and/or get the adequate authorizations.
// WARNING:
// This file implements an algorithm possibly linked to the patent
//
// David Lowe "Method and apparatus for identifying scale invariant
// features in an image and use of same for locating an object in an
// image", U.S. Patent 6,711,293.
//
// This file is made available for the exclusive aim of serving as
// scientific tool to verify of the soundness and
// completeness of the algorithm description. Compilation,
// execution and redistribution of this file may violate exclusive
// patents rights in certain countries.
// The situation being different for every country and changing
// over time, it is your responsibility to determine which patent
// rights restrictions apply to you before you compile, use,
// modify, or redistribute this file. A patent lawyer is qualified
// to make this determination.
// If and only if they don't conflict with any patent terms, you
// can benefit from the following license terms attached to this
// file.
//
// This program is provided for scientific and educational only:
// you can use and/or modify it for these purposes, but you are
// not allowed to redistribute this work or derivative works in
// source or executable form. A license must be obtained from the
// patent right holders for any other use.
#ifndef _CLIBSIFT_H_
#define _CLIBSIFT_H_
///////////// Description
/// For each octave:
/// - Divide in par.Scales scales
/// - Convolve and compute differences of convolved scales
/// - Look for a 3x3 multiscale extrema and contraste enough and with no predominant direction (no 1d edge)
/// For each extrema
/// - Compute orientation histogram in neighborhood.
/// - Generate a keypoint for each mode with this orientation
/// For each keypoint
/// - Create vector
///////////// Possible differences with MW
/// Gaussian convolution
#include <stdlib.h>
#include <assert.h>
#include "numerics1.h"
#include "library.h"
#include "filter.h"
#include "domain.h"
#include "splines.h"
#include "flimage.h"
#include <vector>
// BASIC STRUCTURES:
// Keypoints:
#define OriSize 8
#define IndexSize 4
#define VecLength IndexSize * IndexSize * OriSize
/* Keypoint structure:
position: x,y
scale: s
orientation: angle
descriptor: array of gradient orientation histograms in a neighbors */
struct keypoint {
float x,y,
scale,
angle;
float vec[VecLength];
};
/* Keypoint structure:
position: x,y
scale: s
orientation: angle
descriptor: array of gradient orientation histograms in a neighbors */
struct keypoint_char {
float x,y,
scale,
angle;
unsigned char vec[VecLength];
};
/* Keypoint structure:
position: x,y
scale: s
orientation: angle
descriptor: array of gradient orientation histograms in a neighbors */
struct keypoint_short {
float x,y,
scale,
angle;
unsigned short vec[VecLength];
};
/* Keypoint structure:
position: x,y
scale: s
orientation: angle
descriptor: array of gradient orientation histograms in a neighbors */
struct keypoint_int {
float x,y,
scale,
angle;
unsigned int vec[VecLength];
};
/* List of keypoints: just use the standard class vector: */
typedef std::vector<keypoint> keypointslist;
/* List of keypoints: just use the standard class vector: */
typedef std::vector<keypoint_char> keypointslist_char;
typedef std::vector<keypoint_short> keypointslist_short;
typedef std::vector<keypoint_int> keypointslist_int;
/* Matching: just use the standard class pair: */
typedef std::pair<keypoint,keypoint> matching;
/* List of matchings: just use the standard class vector: */
typedef std::vector<matching> matchingslist;
struct siftPar
{
int OctaveMax;
int DoubleImSize;
int order;
/* InitSigma gives the amount of smoothing applied to the image at the
first level of each octave. In effect, this determines the sampling
needed in the image domain relative to amount of smoothing. Good
values determined experimentally are in the range 1.2 to 1.8.
*/
float InitSigma /*= 1.6*/;
/* Peaks in the DOG function must be at least BorderDist samples away
from the image border, at whatever sampling is used for that scale.
Keypoints close to the border (BorderDist < about 15) will have part
of the descriptor landing outside the image, which is approximated by
having the closest image pixel replicated. However, to perform as much
matching as possible close to the edge, use BorderDist of 4.
*/
int BorderDist /*= 5*/;
/* Scales gives the number of discrete smoothing levels within each octave.
For example, Scales = 2 implies dividing octave into 2 intervals, so
smoothing for each scale sample is sqrt(2) more than previous level.
Value of 2 works well, but higher values find somewhat more keypoints.
*/
int Scales /*= 3*/;
/// Decreasing PeakThresh allows more non contrasted keypoints
/* Magnitude of difference-of-Gaussian value at a keypoint must be above
this threshold. This avoids considering points with very low contrast
that are dominated by noise. It is divided by Scales because more
closely spaced scale samples produce smaller DOG values. A value of
0.08 considers only the most stable keypoints, but applications may
wish to use lower values such as 0.02 to find keypoints from low-contast
regions.
*/
//#define PeakThreshInit 255*0.04
//#define PeakThresh PeakThreshInit / Scales
float PeakThresh /*255.0 * 0.04 / 3.0*/;
/// Decreasing EdgeThresh allows more edge points
/* This threshold eliminates responses at edges. A value of 0.08 means
that the ratio of the largest to smallest eigenvalues (principle
curvatures) is below 10. A value of 0.14 means ratio is less than 5.
A value of 0.0 does not eliminate any responses.
Threshold at first octave is different.
*/
float EdgeThresh /*0.06*/;
float EdgeThresh1 /*0.08*/;
/* OriBins gives the number of bins in the histogram (36 gives 10
degree spacing of bins).
*/
int OriBins /*36*/;
/* Size of Gaussian used to select orientations as multiple of scale
of smaller Gaussian in DOG function used to find keypoint.
Best values: 1.0 for UseHistogramOri = FALSE; 1.5 for TRUE.
*/
float OriSigma /*1.5*/;
/// Look for local (3-neighborhood) maximum with valuer larger or equal than OriHistThresh * maxval
/// Setting one returns a single peak
/* All local peaks in the orientation histogram are used to generate
keypoints, as long as the local peak is within OriHistThresh of
the maximum peak. A value of 1.0 only selects a single orientation
at each location.
*/
float OriHistThresh /*0.8*/;
/// Feature vector is normalized to has euclidean norm 1.
/// This threshold avoid the excessive concentration of information on single peaks
/* Index values are thresholded at this value so that regions with
high gradients do not need to match precisely in magnitude.
Best value should be determined experimentally. Value of 1.0
has no effect. Value of 0.2 is significantly better.
*/
float MaxIndexVal /*0.2*/;
/* This constant specifies how large a region is covered by each index
vector bin. It gives the spacing of index samples in terms of
pixels at this scale (which is then multiplied by the scale of a
keypoint). It should be set experimentally to as small a value as
possible to keep features local (good values are in range 3 to 5).
*/
int MagFactor /*3*/;
/* Width of Gaussian weighting window for index vector values. It is
given relative to half-width of index, so value of 1.0 means that
weight has fallen to about half near corners of index patch. A
value of 1.0 works slightly better than large values (which are
equivalent to not using weighting). Value of 0.5 is considerably
worse.
*/
float IndexSigma /*1.0*/;
/* If this is TRUE, then treat gradients with opposite signs as being
the same. In theory, this could create more illumination invariance,
but generally harms performance in practice.
*/
int IgnoreGradSign /*0*/;
float MatchRatio /*0.6*/;
/*
In order to constrain the research zone for matches.
Useful for example when looking only at epipolar lines
*/
float MatchXradius /*= 1000000.0f*/;
float MatchYradius /*= 1000000.0f*/;
int noncorrectlylocalized;
};
//////////////////////////////////////////////////////////
/// SIFT
//////////////////////////////////////////////////////////
void default_sift_parameters(siftPar &par);
void compute_sift_keypoints(float *input, keypointslist& keypoints,int width, int height, siftPar &par);
// MATCHING DETECTION FUNCTION:
void compute_sift_matches( keypointslist& keys1, keypointslist& keys2, matchingslist& matchings, siftPar &par);
#endif // _LIBSIFT_H_

145
asift_match/src/domain.cpp Executable file
View file

@ -0,0 +1,145 @@
// Authors: Unknown. Please, if you are the author of this file, or if you
// know who are the authors of this file, let us know, so we can give the
// adequate credits and/or get the adequate authorizations.
#include "domain.h"
#define DEBUG 0
void apply_zoom(float *input, float *out, float zoom, int order, int width, int height)
{
int nwidth = (int)( zoom * (float) width);
int nheight = (int)( zoom * (float) height);
float *coeffs;
float *ref;
float cx[12],cy[12],ak[13];
// Guoshen Yu, 2010.09.22, Windows versions
vector<float> input_vec, coeffs_vec, ref_vec;
input_vec = vector<float>(width*height);
coeffs_vec = vector<float>(width*height);
ref_vec = vector<float>(width*height);
for (int i = 0; i < width*height; i++)
input_vec[i] = input[i];
if (order!=0 && order!=1 && order!=-3 &&
order!=3 && order!=5 && order!=7 && order!=9 && order!=11)
{
printf("unrecognized interpolation order.\n");
exit(-1);
}
if (order>=3) {
coeffs = new float[width*height];
// Guoshen Yu, 2010.09.21, Windows version
//finvspline(input,order,coeffs,width,height);
finvspline(input_vec,order,coeffs_vec,width,height);
for (int i = 0; i < width*height; i++)
coeffs[i] = coeffs_vec[i];
ref = coeffs;
if (order>3) init_splinen(ak,order);
} else
{
coeffs = NULL;
ref = input;
}
int xi,yi;
float xp,yp;
float res;
int n1,n2;
float bg = 0.0f;
float p=-0.5;
for(int i=0; i < nwidth; i++)
for(int j=0; j < nheight; j++)
{
xp = (float) i / zoom;
yp = (float) j / zoom;
if (order == 0) {
xi = (int)floor((double)xp);
yi = (int)floor((double)yp);
if (xi<0 || xi>=width || yi<0 || yi>=height)
res = bg;
else res = input[yi*width+xi];
} else {
if (xp<0. || xp>=(float)width || yp<0. || yp>=(float)height) res=bg;
else {
xp -= 0.5; yp -= 0.5;
int xi = (int)floor((double)xp);
int yi = (int)floor((double)yp);
float ux = xp-(float)xi;
float uy = yp-(float)yi;
switch (order)
{
case 1: /* first order interpolation (bilinear) */
n2 = 1;
cx[0]=ux; cx[1]=1.-ux;
cy[0]=uy; cy[1]=1.-uy;
break;
case -3: /* third order interpolation (bicubic Keys' function) */
n2 = 2;
keys(cx,ux,p);
keys(cy,uy,p);
break;
case 3: /* spline of order 3 */
n2 = 2;
spline3(cx,ux);
spline3(cy,uy);
break;
default: /* spline of order >3 */
n2 = (1+order)/2;
splinen(cx,ux,ak,order);
splinen(cy,uy,ak,order);
break;
}
res = 0.; n1 = 1-n2;
if (xi+n1>=0 && xi+n2<width && yi+n1>=0 && yi+n2<height) {
int adr = yi*width+xi;
for (int dy=n1;dy<=n2;dy++)
for (int dx=n1;dx<=n2;dx++)
res += cy[n2-dy]*cx[n2-dx]*ref[adr+width*dy+dx];
} else
// Guoshen Yu, 2010.09.21, Windows
for (int i = 0; i < width*height; i++)
ref_vec[i] = ref[i];
for (int dy=n1;dy<=n2;dy++)
for (int dx=n1;dx<=n2;dx++)
// Guoshen Yu, 2010.09.21, Windows
// res += cy[n2-dy]*cx[n2-dx]*v(ref,xi+dx,yi+dy,bg,width,height);
res += cy[n2-dy]*cx[n2-dx]*v(ref_vec,xi+dx,yi+dy,bg,width,height);
}
}
out[j*nwidth+i] = res;
}
}

40
asift_match/src/domain.h Executable file
View file

@ -0,0 +1,40 @@
// Authors: Unknown. Please, if you are the author of this file, or if you
// know who are the authors of this file, let us know, so we can give the
// adequate credits and/or get the adequate authorizations.
#ifndef _DOMAIN_H_
#define _DOMAIN_H_
#include "numerics1.h"
#include "library.h"
#include "splines.h"
/// Compute homography from n points using svd
void compute_planar_homography_n_points(float *x0, float *y0, float *x1, float *y1, int n, float **H);
/// Compute homography using svd + Ransac
void compute_ransac_planar_homography_n_points(float *x0, float *y0, float *x1, float *y1, int n, int niter, float tolerance, float **H);
/// Compute homography by using Lionel Code
void compute_moisan_planar_homography_n_points(float *x0, float *y0, float *x1, float *y1, int n, int niter, float &epsilon, float **H, int &counter, int recursivity);
/// Apply planar homography to image
void compute_planar_homography_bounding_box(int width, int height, float **H, float *x0, float *y0, int *nwidth, int *nheight);
void apply_planar_homography(float *input, int width, int height, float **H, float bg, int order, float *out, float x0, float y0, int nwidth, int nheight);
/// Apply zoom of factor z
void apply_zoom(float *input, float *out, float zoom, int order, int width, int height);
/// Apply general transformation
void apply_general_transformation(float *input, float *transformx, float* transformy, float *out, float bg, int order, int width, int height, int nwidth,int nheight);
#endif

460
asift_match/src/filter.cpp Executable file
View file

@ -0,0 +1,460 @@
// Authors: Unknown. Please, if you are the author of this file, or if you
// know who are the authors of this file, let us know, so we can give the
// adequate credits and/or get the adequate authorizations.
#include "filter.h"
/////////////////////////////////////////////////////////////// Build Gaussian filters
float * directional_gauss_filter(float xsigma, float ysigma, float angle, int *kwidth, int *kheight)
{
int ksize = (int)(2.0 * 2.0 * MAX(xsigma, ysigma) + 1.0);
float *kernel = new float[ksize*ksize];
float xsigma2 = xsigma*xsigma;
float ysigma2 = ysigma*ysigma;
int l2 = ksize/2;
for(int y = -l2; y <= l2; y++)
for(int x = -l2; x <= l2; x++)
{
float a = (float) angle * PI / 180.0f;
float sina = sin(a);
float cosa = cos(a);
float ax = (float) x * cosa + (float) y * sina;
float ay = -(float) x * sina + (float) y * cosa;
kernel[(y+l2) * ksize + x + l2] = exp(-(ax*ax)/(2.0f*xsigma2) - (ay*ay)/(2.0f*ysigma2) );
}
float sum=0.0;
for(int i=0; i < ksize*ksize; i++) sum += kernel[i];
for(int i=0; i < ksize*ksize; i++) kernel[i] /= sum;
*kwidth = ksize;
*kheight = ksize;
return kernel;
}
/* Convolution with a kernel */
/* No padding applied to the image */
void convol(float *u,float *v,int width,int height,float *kernel,int kwidth,int kheight)
{
// float S;
// int K2,L2,m,n,kmin,kmax,lmin,lmax,l,k;
int K2 = kwidth / 2;
int L2 = kheight / 2;
for(int y=0 ; y < height; y++)
for (int x=0 ; x < width; x++) {
float S = 0.0;
// kmax = MIN(kwidth-1,n+K2);
// kmin = MAX(0,1+n+K2-width);
// lmax = MIN(kheight-1,m+L2);
// lmin = MAX(0,1+m+L2-height);
for (int l = -L2; l <= L2; l++)
for (int k = -K2 ; k<= K2; k++)
{
int px=x+k;
int py=y+l;
if (px>=0 && px < width && py>=0 && py<height)
S += u[width*py + px] * kernel[kwidth*(l+L2) + k+K2];
}
v[y*width+x] = (float) S;
}
}
void median(float *u,float *v, float radius, int niter, int width,int height)
{
int iradius = (int)(radius+1.0);
int rsize=(2*iradius+1)*(2*iradius+1);
float * vector = new float[rsize];
float * index = new float[rsize];
for(int n=0; n< niter;n++){
for(int x=0;x<width;x++)
for(int y=0;y<height;y++){
int count=0;
for(int i=-iradius;i<=iradius;i++)
for(int j=-iradius;j<=iradius;j++)
if ((float) (i*i + j*j) <= iradius*iradius){
int x0=x+i;
int y0=y+j;
if (x0>=0 && y0>=0 && x0 < width && y0 < height) {
vector[count] = u[y0*width+x0];
index[count] = count;
count++;
}
}
quick_sort(vector,index,count);
v[y*width+x] = vector[count/2];
}
copy(v,u,width*height);
}
delete[] vector;
delete[] index;
}
void remove_outliers(float *igray,float *ogray,int width, int height)
{
int bloc=1;
int bsize = (2*bloc+1)*(2*bloc+1)-1;
for(int x=bloc;x<width-bloc;x++)
for(int y=bloc;y<height-bloc;y++) {
int l = y*width+x;
int countmax=0;
int countmin=0;
float valueg0 = igray[l];
// float distmin = MAXFLOAT;
float distmin = FLT_MAX; // Guoshen Yu
float green = igray[l];
for(int i=-bloc;i<=bloc;i++)
for(int j=-bloc;j<=bloc;j++)
if ((i!=0 || j!=0)){
int l0 = (y+j)*width+x+i;
int valueg = (int) igray[l0];
if (valueg0>valueg) countmax++;
if (valueg0<valueg) countmin++;
float dist = fabsf(valueg - valueg0);
if (dist < distmin) {distmin=dist;green=valueg;}
}
if (countmin == bsize || countmax == bsize ) ogray[l]=green;
else ogray[l] = igray[l];
}
}
/* Convolution with a separable kernel */
/* boundary condition: 0=zero, 1=symmetry */
void separable_convolution(float *u, float *v, int width, int height,float * xkernel, int xsize,float *ykernel,int ysize,int boundary)
{
int width2 = 2*width;
int height2 = 2*height;
float *tmp = (float *) malloc(width*height*sizeof(float));
/* convolution along x axis */
float sum = 0.0;
int org = xsize / 2;
for (int y=height;y--;)
for (int x=width;x--;) {
sum = 0.0;
for (int i=xsize;i--;) {
int s = x-i+org;
switch(boundary) {
case 0:
if (s>=0 && s<width) sum += xkernel[i]*u[y*width+s];
break;
case 1:
while (s<0) s+=width2;
while (s>=width2) s-=width2;
if (s>=width) s = width2-1-s;
sum += xkernel[i]*u[y*width+s];
break;
}
}
tmp[y*width+x] = sum;
}
/* convolution along y axis */
org = ysize / 2;
for (int y=height;y--;)
for (int x=width;x--;) {
sum=0.0;
for (int i=ysize;i--;) {
int s = y-i+org;
switch(boundary) {
case 0:
if (s>=0 && s<height) sum += ykernel[i]*tmp[s*width+x];
break;
case 1:
while (s<0) s+=height2;
while (s>=height2) s-=height2;
if (s>=height) s = height2-1-s;
sum += ykernel[i]*tmp[s*width+x];
break;
}
}
v[y*width+x] = sum;
}
free(tmp);
}
void gaussian_convolution(float *u, float *v, int width, int height, float sigma)
{
int ksize;
float * kernel;
ksize = (int)(2.0 * 4.0 * sigma + 1.0);
kernel = gauss(1,sigma,&ksize);
int boundary = 1;
copy(u,v,width*height);
horizontal_convolution(v, v, width, height, kernel, ksize, boundary);
vertical_convolution(v, v, width, height, kernel, ksize, boundary);
delete[] kernel; /*memcheck*/
}
void gaussian_convolution(float *u, float *v, int width, int height, float sigma, int ksize)
{
float * kernel;
kernel = gauss(1,sigma,&ksize);
int boundary = 1;
copy(u,v,width*height);
horizontal_convolution(v, v, width, height, kernel, ksize, boundary);
vertical_convolution(v, v, width, height, kernel, ksize, boundary);
}
void fast_separable_convolution(float *u, float *v, int width, int height,float * xkernel, int xsize,float *ykernel,int ysize,int boundary)
{
copy(u,v,width*height);
horizontal_convolution(v, v, width, height, xkernel, xsize, boundary);
vertical_convolution(v, v, width, height, ykernel, ysize, boundary);
}
/* Loop unrolling simply sums 5 multiplications
at a time to allow the compiler to schedule
operations better and avoid loop overhead.
*/
void buffer_convolution(float *buffer,float *kernel,int size,int ksize)
{
for (int i = 0; i < size; i++) {
float sum = 0.0;
float *bp = &buffer[i];
float *kp = &kernel[0];
/* Loop unrolling: do 5 multiplications at a time. */
// int k=0;
for(int k = 0; k < ksize; k++)
sum += *bp++ * *kp++;
// for(;k + 4 < ksize; bp += 5, kp += 5, k += 5)
// sum += bp[0] * kp[0] + bp[1] * kp[1] + bp[2] * kp[2] +
// bp[3] * kp[3] + bp[4] * kp[4];
/* Do multiplications at a time on remaining items. */
// for(; k < ksize; bp++ , kp++, k++) sum += *bp * (*kp);
buffer[i] = sum;
}
}
/* Convolve image with the 1-D kernel vector along image rows. This
is designed to be as efficient as possible.
*/
void horizontal_convolution(float *u, float *v, int width, int height, float *kernel, int ksize, int boundary)
{
int halfsize = ksize / 2;
int buffersize = width + ksize;
float *buffer = new float[buffersize];
for (int r = 0; r < height; r++) {
/// symmetry
int l = r*width;
if (boundary == 1)
for (int i = 0; i < halfsize; i++)
buffer[i] = u[l + halfsize - 1 - i ];
else
for (int i = 0; i < halfsize; i++)
buffer[i] = 0.0;
for (int i = 0; i < width; i++)
buffer[halfsize + i] = u[l + i];
if (boundary == 1)
for (int i = 0; i < halfsize; i++)
buffer[i + width + halfsize] = u[l + width - 1 - i];
else
for (int i = 0; i < halfsize; i++)
buffer[i + width + halfsize] = 0.0;
buffer_convolution(buffer, kernel, width, ksize);
for (int c = 0; c < width; c++)
v[r*width+c] = buffer[c];
}
delete[] buffer; /*memcheck*/
}
void vertical_convolution(float *u, float *v, int width, int height, float *kernel,int ksize, int boundary)
{
int halfsize = ksize / 2;
int buffersize = height + ksize;
float *buffer = new float[buffersize];
for (int c = 0; c < width; c++) {
if (boundary == 1)
for (int i = 0; i < halfsize; i++)
buffer[i] = u[(halfsize-i-1)*width + c];
else
for (int i = 0; i < halfsize; i++)
buffer[i] = 0.0f;
for (int i = 0; i < height; i++)
buffer[halfsize + i] = u[i*width + c];
if (boundary == 1)
for (int i = 0; i < halfsize; i++)
buffer[halfsize + height + i] = u[(height - i - 1)*width+c];
else
for (int i = 0; i < halfsize; i++)
buffer[halfsize + height + i] = 0.0f;
buffer_convolution(buffer, kernel, height, ksize);
for (int r = 0; r < height; r++)
v[r*width+c] = buffer[r];
}
delete[] buffer; /*memcheck*/
}
void heat(float *input, float *out, float step, int niter, float sigma, int width, int height)
{
int i,j,n,ksize,size,im,i1,j1,jm;
float *kernel = NULL, *laplacian = NULL, *convolved = NULL;
size = width*height;
if (sigma > 0.0) kernel = gauss(0,sigma,&ksize);
laplacian = (float *) malloc(size*sizeof(float));
convolved = (float *) malloc(size*sizeof(float));
for(n=0; n < niter; n++)
{
if (sigma > 0.0)
{
separable_convolution(input,convolved,width,height, kernel, ksize,kernel,ksize,1);
for(i=0; i< size; i++) laplacian[i] = convolved[i] - input[i];
} else
{
for (i=0; i < width;i++)
for (j=0; j< height ;j++)
{
if (j==0) jm=1; else jm=j-1;
if (j==height-1) j1=height-2; else j1=j+1;
if (i==0) im=1; else im=i-1;
if (i==width-1) i1=width-2; else i1=i+1;
laplacian[j*width + i] = - 4.0 * input[width*j+i] + input[width*j+im]+ input[width*j+i1]+input[width*jm + i] + input[width*j1 + i];
}
}
for(i=0; i < size; i++) out[i] = input[i] + step * laplacian[i];
copy(out,input,size);
}
free(laplacian);
free(convolved);
if (kernel) free(kernel);
}

38
asift_match/src/filter.h Executable file
View file

@ -0,0 +1,38 @@
// Authors: Unknown. Please, if you are the author of this file, or if you
// know who are the authors of this file, let us know, so we can give the
// adequate credits and/or get the adequate authorizations.
#ifndef _FILTER_H_
#define _FILTER_H_
#include "library.h"
float * directional_gauss_filter(float xsigma, float ysigma, float angle, int *kwidth, int *kheight);
void median(float *u,float *v, float radius, int niter, int width,int height);
void remove_outliers(float *igray,float *ogray,int width, int height);
/// Convolution with a separable kernel, boundary condition: 0=zero, 1=symmetry
void separable_convolution(float *u, float *v, int width, int height, float *xkernel, int xsize, float *ykernel, int ysize,int boundary);
void buffer_convolution(float *buffer,float *kernel,int size,int ksize);
void horizontal_convolution(float *u, float *v, int width, int height, float *kernel, int ksize, int boundary);
void vertical_convolution(float *u, float *v, int width, int height, float *kernel,int ksize, int boundary);
void fast_separable_convolution(float *u, float *v, int width, int height,float * xkernel, int xsize,float *ykernel,int ysize,int boundary);
/// Can be called with u=v
void gaussian_convolution(float *u, float *v, int width, int height, float sigma);
void gaussian_convolution(float *u, float *v, int width, int height, float sigma, int ksize);
void convol(float *u, float *v, int width, int height, float *kernel, int kwidth, int kheight); /// Convolution with a kernel, No padding applied to the image
void heat(float *u, float *v, float step, int niter, float sigma, int width, int height);
#endif // _FILTER_H_

86
asift_match/src/flimage.cpp Executable file
View file

@ -0,0 +1,86 @@
// Authors: Unknown. Please, if you are the author of this file, or if you
// know who are the authors of this file, let us know, so we can give the
// adequate credits and/or get the adequate authorizations.
#include "flimage.h"
//////////////////////////////////////////////// Class flimage
//// Construction
flimage::flimage() : width(0), height(0), p(0)
{
}
flimage::flimage(int w, int h) : width(w), height(h), p(new float[w*h])
{
for (int j=width*height-1; j>=0 ; j--) p[j] = 0.0;
}
flimage::flimage(int w, int h, float v) : width(w), height(h), p(new float[w*h])
{
for (int j=width*height-1; j>=0 ; j--) p[j] = v;
}
flimage::flimage(int w, int h, float* v) : width(w), height(h), p(new float[w*h])
{
for (int j=width*height-1; j>=0 ; j--) p[j] = v[j];
}
void flimage::create(int w, int h)
{
erase();
width = w; height = h;
p = new float[w*h];
for (int j=width*height-1; j>=0 ; j--) p[j] = 0.0;
}
void flimage::create(int w, int h, float* v)
{
erase();
width = w; height = h; p = new float[w*h];
for (int j=width*height-1; j>=0 ; j--) p[j] = v[j];
}
flimage::flimage(const flimage& im) : width(im.width), height(im.height), p(new float[im.width*im.height])
{
for (int j=width*height-1; j>=0 ; j--) p[j] = im.p[j];
}
flimage& flimage::operator= (const flimage& im)
{
if (&im == this) {
return *this;
}
if (width != im.width || height != im.height)
{
erase();
width = im.width; height=im.height; p = new float[width*height];
}
for (int j=width*height-1; j>=0 ; j--) p[j] = im.p[j];
return *this;
}
//// Destruction
void flimage::erase()
{
width = height = 0;
if (p) delete[] p;
p=0;
}
flimage::~flimage()
{
erase();
}

Some files were not shown because too many files have changed in this diff Show more