API文档:
http://docs.ros.org/hydro/api/siftgpu/html/SiftGPU_8h.html
visualsfm
https://github.com/mrquincle/visualsfm/blob/master/SiftGPU/src/ServerSiftGPU/server.cpp
可视化显示:
https://github.com/district10/sfmViewer
sudo apt-get install build-essential libgl1-mesa-dev
sudo apt-get install freeglut3-dev
sudo apt-get install libglew-dev libsdl2-dev libsdl2-image-dev libglm-dev libfreetype6-dev
sudo apt-get install libglu1-mesa-dev freeglut3-dev
写在前面的话,关于示例有两种
一种是SiftGPU *sift = *********;
原版示例就是这样,https://github.com/pitzer/SiftGPU/blob/master/src/TestWin/SimpleSIFT.cpp
一种是 SiftGPU sift;
高翔的示例是这样 SLAM拾萃(3):siftGPU
cmake_minimum_required(VERSION 2.8.3) project(test_siftgpu) # OpenCV依赖 find_package( OpenCV REQUIRED ) # OpenGL find_package(OpenGL REQUIRED) # GLUT find_package(GLUT REQUIRED) # Glew find_package(GLEW REQUIRED) # SiftGPU:手动设置其头文件与库文件所在位置 include_directories("/home/spple/CLionProjects/SIFT-GPU/src/SiftGPU/" ${OpenGL_INCLUDE_DIR}) set(SIFTGPU_LIBS "/home/spple/CLionProjects/SIFT-GPU/cmake-build-debug/src/SiftGPU/libsiftgpu.so") add_executable( testSIFTGPU main.cpp ) target_link_libraries( testSIFTGPU ${OpenCV_LIBS} ${SIFTGPU_LIBS} ${GLEW_LIBRARIES} ${GLUT_LIBRARIES} ${OPENGL_LIBRARIES} )
参考文章:
https://www.cnblogs.com/RichardYao/p/9907860.html
SiftGPU在Ubuntu和Windows下的编译与使用
https://www.cnblogs.com/wangguchangqing/p/10132052.html
SLAM拾萃(3):siftGPU
https://www.cnblogs.com/gaoxiang12/p/5149067.html
https://github.com/pitzer/SiftGPU/pull/3/commits/831aa0d3fda201afd94d930bf3850c7cba5e499e
https://blog.csdn.net/qq_27550989/article/details/73614758
还有别人直接处理好的Ubuntu版本:
https://github.com/QianshengGu/SiftGPU_Linux
或者修改:
第一处:
SiftGPU/src/SiftGPU/SiftGPU.h文件,在上头加入一个
#include
第二处:
SiftGPU/src/SiftGPU/CMakeLists.txt
删除find_package(Glew)
添加find_package(GLEW)
第三处:
src/SiftGPU/LiteWindow.h:
virtual ~LiteWindow() { if(glut_id > 0) glutDestroyWindow(glut_id); }
修改为
virtual ~LiteWindow()
{
if(glut_id > 0)
{
int argc = 0;
char** argv;
glutInit(&argc, argv);
glutDestroyWindow(glut_id);
}
}
关于第三处这个问题,其实是一个内存释放问题,你用上面的也可以通过,
如果你想知道怎么不用上面的改,请看一下我之前的博客:
SiftGPU一些细节整理
https://blog.csdn.net/baidu_40840693/article/details/84503083
通过这种改法,不用改 virtual ~LiteWindow() { if(glut_id > 0) glutDestroyWindow(glut_id); }
我个人觉得关于内存释放的改法才是问题的解决办法所在
main.cpp
关于SLAM拾萃(3):siftGPU这个例子,有点问题
彩图的话一些地方需要改:
sift.RunSIFT(width, height, img.data, GL_BGR, GL_UNSIGNED_BYTE);
具体看我之前的博客:
https://blog.csdn.net/baidu_40840693/article/details/84503083
// SiftGPU模块
#include
//标准C++
#include
#include
// OpenCV图像
#include
#include
// boost库中计时函数
#include
// OpenGL
#include
using namespace std;
int main( int argc, char** argv)
{
//声明SiftGPU并初始化
SiftGPU sift;
char* myargv[4] ={ "-fo", "-1", "-v", "1"};
sift.ParseParam(4, myargv);
//检查硬件是否支持SiftGPU
int support = sift.CreateContextGL();
if ( support != SiftGPU::SIFTGPU_FULL_SUPPORTED )
{
cerr<<"SiftGPU is not supported!"<cmake_minimum_required(VERSION 2.8.3)
project(test_siftgpu)
# OpenCV依赖
find_package( OpenCV REQUIRED )
# OpenGL
find_package(OpenGL REQUIRED)
# GLUT
find_package(GLUT REQUIRED)
# Glew
find_package(Glew REQUIRED)
# SiftGPU:手动设置其头文件与库文件所在位置
include_directories("/home/xiang/Downloads/SiftGPU/src/SiftGPU/" ${OpenGL_INCLUDE_DIR})
set(SIFTGPU_LIBS "/home/xiang/Downloads/SiftGPU/bin/libsiftgpu.so")
add_executable( testSIFTGPU main.cpp )
target_link_libraries( testSIFTGPU
${OpenCV_LIBS}
${SIFTGPU_LIBS}
${GLEW_LIBRARIES} ${GLUT_LIBRARIES} ${OPENGL_LIBRARIES}
)
还遇到过一个:
CMake Error at src/TestWin/CMakeLists.txt:3 (find_package):
By not providing "FindGlEW.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "GlEW", but
CMake did not find one.
Could not find a package configuration file provided by "GlEW" with any of
the following names:
GlEWConfig.cmake
glew-config.cmake
Add the installation prefix of "GlEW" to CMAKE_PREFIX_PATH or set
"GlEW_DIR" to a directory containing one of the above files. If "GlEW"
provides a separate development package or SDK, be sure it has been
installed.
参考:
https://www.cnblogs.com/gaoxiang12/p/5149067.html
因为我使用的是clion,去找的时候发现有:
/home/spple/clion-2018.2.5/bin/cmake/linux/share/cmake-3.12/Modules/FindGLEW.cmake
但是还是报错。定睛一看,。。。。好吧他是GlEW,加个软链接吧
ln -s FindGLEW.cmake FindGlEW.cmake,
或者修改:
SIFT-GPU/src/TestWin/CMakeLists.txt下的
find_package(GLEW REQUIRED)
新错误:
/home/spple/CLionProjects/SIFT-GPU/src/TestWin/SimpleSIFT.cpp:88:对‘dlopen’未定义的引用
/home/spple/CLionProjects/SIFT-GPU/src/TestWin/SimpleSIFT.cpp:102:对‘dlsym’未定义的引用
/home/spple/CLionProjects/SIFT-GPU/src/TestWin/SimpleSIFT.cpp:103:对‘dlsym’未定义的引用
/home/spple/CLionProjects/SIFT-GPU/src/TestWin/SimpleSIFT.cpp:286:对‘dlclose’未定义的引用
https://blog.csdn.net/qq_22122811/article/details/52738134
https://www.cnblogs.com/Rainlee007/p/6930386.html
https://bbs.csdn.net/topics/392137961
SIFT-GPU/src/TestWin/CMakeLists.txt:
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
find_package(GLEW REQUIRED)
include_directories( ${GLEW_INCLUDE_DIRS} )
ADD_EXECUTABLE(SimpleSIFT SimpleSIFT.cpp)
TARGET_LINK_LIBRARIES(SimpleSIFT siftgpu)
TARGET_LINK_LIBRARIES(SimpleSIFT dl)
#ADD_EXECUTABLE(TestWinGlut TestWinGlut.cpp BasicTestWin.cpp )
#TARGET_LINK_LIBRARIES(TestWinGlut siftgpu)
set(CMAKE_VERBOSE_MAKEFILE ON)
编译成功,但是还有一种问题,
就是程序没反应,
原来代码中是:
SIFT-GPU/src/TestWin/SimpleSIFT.cpp
#ifdef _WIN32
#ifdef _DEBUG
HMODULE hsiftgpu = LoadLibrary("siftgpu_d.dll");
#else
HMODULE hsiftgpu = LoadLibrary("siftgpu.dll");
#endif
#else
void * hsiftgpu = dlopen("libsiftgpu.so", RTLD_LAZY);
#endif
但是我没找到 libsiftgpu.so,我编译出来的是:libsiftgpu.a
静态库动态库问题,我们改一下;
SIFT-GPU/src/SiftGPU/CMakeLists.txt
#siftgpu STATIC
#siftgpu SHARED
ADD_LIBRARY(siftgpu SHARED FrameBufferObject.cpp GlobalUtil.cpp GLTexImage.cpp ProgramGLSL.cpp
ProgramGPU.cpp ShaderMan.cpp SiftGPU.cpp SiftPyramid.cpp PyramidGL.cpp SiftMatch.cpp)
好了,此时就有了 libsiftgpu.so
在代码中给一个绝对路径就可以了:
SIFT-GPU/src/TestWin/SimpleSIFT.cpp
#ifdef _WIN32
#ifdef _DEBUG
HMODULE hsiftgpu = LoadLibrary("siftgpu_d.dll");
#else
HMODULE hsiftgpu = LoadLibrary("siftgpu.dll");
#endif
#else
void * hsiftgpu = dlopen("/home/spple/CLionProjects/SIFT-GPU/cmake-build-debug/src/SiftGPU/libsiftgpu.so", RTLD_LAZY);
#endif
成功运行了,至于这个新错误,我们前面遇到过:
彩图的话一些地方需要改:
sift.RunSIFT(width, height, img.data, GL_BGR, GL_UNSIGNED_BYTE);
具体看我之前的博客:
https://blog.csdn.net/baidu_40840693/article/details/84503083
或者直接用绝对路径载入,程序内部会将彩图转灰度
if(sift->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED) return 0; if(sift->RunSIFT("/home/spple/CLionProjects/SIFT-GPU/data/800-1.jpg")) { //Call SaveSIFT to save result to file, the format is the same as Lowe's //sift->SaveSIFT("../data/800./-1.sift"); //Note that saving ASCII format is slow //get feature count num1 = sift->GetFeatureNum(); //allocate memory keys1.resize(num1); descriptors1.resize(128*num1); //reading back feature vectors is faster than writing files //if you dont need keys or descriptors, just put NULLs here sift->GetFeatureVector(&keys1[0], &descriptors1[0]); //this can be used to write your own sift file. } //You can have at most one OpenGL-based SiftGPU (per process). //Normally, you should just create one, and reuse on all images. if(sift->RunSIFT("/home/spple/CLionProjects/SIFT-GPU/data/640-1.jpg")) { num2 = sift->GetFeatureNum(); keys2.resize(num2); descriptors2.resize(128*num2); sift->GetFeatureVector(&keys2[0], &descriptors2[0]); }
修改SIFT-GPU/src/TestWin/CMakeLists.txt::
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
find_package(GLEW REQUIRED)
# OpenCV依赖
find_package( OpenCV REQUIRED )
include_directories( ${GLEW_INCLUDE_DIRS} )
include_directories( ${OpenGL_INCLUDE_DIR} )
ADD_EXECUTABLE(SimpleSIFT SimpleSIFT.cpp)
TARGET_LINK_LIBRARIES(SimpleSIFT siftgpu)
TARGET_LINK_LIBRARIES(SimpleSIFT dl)
target_link_libraries(SimpleSIFT
${OpenCV_LIBS}
)
#ADD_EXECUTABLE(TestWinGlut TestWinGlut.cpp BasicTestWin.cpp )
#TARGET_LINK_LIBRARIES(TestWinGlut siftgpu)
set(CMAKE_VERBOSE_MAKEFILE ON)
SIFT-GPU/src/TestWin/SimpleSIFT.cpp:88:对‘dlopen’未定义的引用
SIFT-GPU/src/TestWin/SimpleSIFT.cpp:102:对‘dlsym’未定义的引用
SIFT-GPU/src/TestWin/SimpleSIFT.cpp:103:对‘dlsym’未定义的引用
SIFT-GPU/src/TestWin/SimpleSIFT.cpp:286:对‘dlclose’未定义的引用TARGET_LINK_LIBRARIES(SimpleSIFT dl)
在:SIFT-GPU/src/TestWin/SimpleSIFT.cpp
下添加头文件和修改代码:
#include
#include
#include
#include
cv::Mat img1 = cv::imread("/home/spple/CLionProjects/SIFT-GPU/data/800-1.jpg", 1);
cv::Mat grayImg1;
cv::cvtColor(img1, grayImg1, CV_BGR2GRAY);
int width1 = grayImg1.cols;
int height1 = grayImg1.rows;
if(sift->RunSIFT(width1, height1, img1.data, GL_BGR, GL_UNSIGNED_BYTE))
{
//Call SaveSIFT to save result to file, the format is the same as Lowe's
//sift->SaveSIFT("../data/800-1.sift"); //Note that saving ASCII format is slow
//get feature count
num1 = sift->GetFeatureNum();
//allocate memory
keys1.resize(num1); descriptors1.resize(128*num1);
//reading back feature vectors is faster than writing files
//if you dont need keys or descriptors, just put NULLs here
sift->GetFeatureVector(&keys1[0], &descriptors1[0]);
//this can be used to write your own sift file.
}
//You can have at most one OpenGL-based SiftGPU (per process).
//Normally, you should just create one, and reuse on all images.
cv::Mat img2 = cv::imread("/home/spple/CLionProjects/SIFT-GPU/data/640-1.jpg", 1);
cv::Mat grayImg2;
cv::cvtColor(img2, grayImg2, CV_BGR2GRAY);
int width2 = grayImg2.cols;
int height2 = grayImg2.rows;
if( sift->RunSIFT(width2, height2, img2.data, GL_BGR, GL_UNSIGNED_BYTE))
{
num2 = sift->GetFeatureNum();
keys2.resize(num2); descriptors2.resize(128*num2);
sift->GetFeatureVector(&keys2[0], &descriptors2[0]);
}
或者安装好devil
然后:
修改:
SIFT-GPU/src/SiftGPU/CMakeLists.txt
find_package(DevIL)
#FALSE 为开启DEVIL
SET(SIFTGPU_DISABLE_DEVIL FALSE)
makefile文件默认是开启devil的,但是CMAKELIST不是,我们开启后,很多地方就会使用devil去载入图像
最后可以改一下:修改SIFT-GPU/src/TestWin/CMakeLists.txt::
project(SimpleSIFT)
project(TestWinGlut)
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
find_package(GLEW REQUIRED)
# OpenCV依赖
find_package( OpenCV REQUIRED )
include_directories( ${GLEW_INCLUDE_DIRS} )
include_directories( ${OpenGL_INCLUDE_DIR} )
ADD_EXECUTABLE(SimpleSIFT SimpleSIFT.cpp)
TARGET_LINK_LIBRARIES(SimpleSIFT siftgpu)
TARGET_LINK_LIBRARIES(SimpleSIFT dl)
target_link_libraries(SimpleSIFT
${OpenCV_LIBS}
)
ADD_EXECUTABLE(TestWinGlut TestWinGlut.cpp BasicTestWin.cpp )
TARGET_LINK_LIBRARIES(TestWinGlut siftgpu)
set(CMAKE_VERBOSE_MAKEFILE ON)
关于TestWinGlut运行没反应是因为需要参数:
./TestWinGlut -i /home/spple/CLionProjects/SIFT-GPU/data/1600.jpg
./TestWinGlut -il ../data/list640.txt
./TestWinGlut -il ../data/listx.txt
./TestWinGlut -i ../doc/evaluation/box.pgm -o ../doc/evaluation/box.siftgpu -w 3 -fo -1 -loweo -exit
还有一种方式是:
https://www.cnblogs.com/wangguchangqing/p/10132052.html
通过本身的makefile去编译,我这边出现了和博客一样的问题:
src/SiftGPU/GLTexImage.cpp:47:23: fatal error: IL/il.h: 没有那个文件或目录
#include "IL/il.h"
^
compilation terminated.
makefile:140: recipe for target 'build/GLTexImage.o' failed
make: *** [build/GLTexImage.o] Error 1
在执行make 编译,如果遇到fatal error: IL/il.h: No such file or directory,使用下面的命令安装dev image library.
sudo apt-get install libdevil-dev
下列软件包有未满足的依赖关系:
libdevil-dev : 依赖: liblcms2-dev 但是它将不会被安装
E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。
sudo apt-get install liblcms2-dev
下列软件包有未满足的依赖关系:
liblcms2-dev : 依赖: liblcms2-2 (= 2.6-3ubuntu2) 但是 2.6-3ubuntu2.1 正要被安装
E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。
sudo apt-get install liblcms2-2
spple@spple:~/CLionProjects/SIFT-GPU$ sudo apt-get install liblcms2-2
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
liblcms2-2 已经是最新版 (2.6-3ubuntu2.1)。
下列软件包是自动安装的并且现在不需要了:
我已经安装了一个不正确的依赖,所以这条路必须重新编译一个devil
然后地址加载makefile的文件上
使用vcpkg吧,等等突然找到了解决方法
找到了解决方式:
sudo apt install liblcms2-2=2.6-3ubuntu2
sudo apt-get install liblcms2-dev
sudo apt-get install libdevil-dev
这一块使用make 不要-j4
make clean
make
生成的bin目录下的文件运行:
./SimpleSIFT
[SiftGPU Language]: GLSL
[GPU VENDOR]: Intel Open Source Technology Center
TEXTURE: 16384
Image size : 800x600
Image loaded : /home/spple/CLionProjects/SIFT-GPU/data/800-1.jpg
#Features: 3359
#Features MO: 3927
[RUN SIFT]: 0.118
Image size : 640x480
Image loaded : /home/spple/CLionProjects/SIFT-GPU/data/640-1.jpg
#Features: 2377
#Features MO: 2784
[RUN SIFT]: 0.047
[SiftMatchGPU]: GLSL
2276 sift matches were found;
如果使用cuda,那么找到SimpleSIFT.cpp
修改为:
//char * argv[] = {"-fo", "-1", "-v", "1"};//
char * argv[] = {"-fo", "-1", "-v", "1", "-cuda", "0"};
使用makefile重新编译,使用:
spple@spple:~/CLionProjects/SIFT-GPU/bin$ ./SimpleSIFT
NOTE: changing maximum texture dimension to 32768
[SiftGPU Language]: CUDA
Image size : 800x600
Image loaded : /home/spple/CLionProjects/SIFT-GPU/data/800-1.jpg
#Features: 3348
#Features MO: 3911
[RUN SIFT]: 0.09
Image size : 640x480
Image loaded : /home/spple/CLionProjects/SIFT-GPU/data/640-1.jpg
#Features: 2372
#Features MO: 2767
[RUN SIFT]: 0.029
NOTE: changing maximum texture dimension to 32768
[SiftMatchGPU]: CUDA
2247 sift matches were found;
暂时只有windows 还有Ubuntu的makefile可以开启使用cuda,
如果是Ubuntu的CmakeList.txt
SIFT-GPU/src/SiftGPU/CMakeLists.txt
SET(SIFTGPU_ENABLE_CUDA FALSE)
并没有用,还是会显示
---------------------------------------------------------------------------
CUDA not supported in this binary! To enable it, please use SiftGPU_CUDA_Enable
solution for VS2005+ or set siftgpu_enable_cuda to 1 in makefile
----------------------------------------------------------------------------
./TestWinGlut -il /home/spple/CLionProjects/SIFT-GPU/data/list640.txt
[SiftGPU Language]: GLSL
[GPU VENDOR]: Intel Open Source Technology Center
TEXTURE: 16384
[Load Programs]: begin ...
Filter: sigma = 1.51987, size = 13x13
Filter: sigma = 1.22627, size = 11x11
Filter: sigma = 1.54501, size = 13x13
Filter: sigma = 1.94659, size = 17x17
Filter: sigma = 2.45255, size = 21x21
Filter: sigma = 3.09002, size = 25x25
[Load Programs]: 0.394
[Load Input Image]: begin ...
Image size : 640x480
Image loaded : 640-1.jpg
[Load Input Image]: 0.006
[Initialize Pyramid]: begin ...
[Allocate Pyramid]: 640x480
[Allocate Pyramid]: 40MB
[Initialize Pyramid]: 0.006
[Build Pyramid]: begin ...
#0 0.004 0.001 0 0 0 0 | 0.006
#1 0.001 0 0 0 0 0 | 0.001
#2 0 0 0.001 0 0 0 | 0.001
#3 0 0 0 0 0 0 | 0
#4 0.001 0 0 0 0 0 | 0.001
[Build Pyramid]: 0.009
[Detect Keypoints]: begin ...
#0 0.003 0 0 | 0.003
#1 0 0 0 | 0
#2 0.001 0 0 | 0.001
#3 0.001 0 0 | 0.001
#4 0 0 0 | 0
0.004
0.005
[Detect Keypoints]: 0.009
[Get Feature List]: begin ...
#0: 210 137 83 | 430 : (0.002)
#1: 72 40 19 | 131 : (0.001)
#2: 18 10 13 | 41 : (0)
#3: 3 5 2 | 10 : (0.001)
#4: 1 3 0 | 4 : (0)
#Features: 616
[Get Feature List]: 0.005
[Feature Orientations]: begin ...
[Feature Orientations]: 0.003
[MultiO Feature List]: begin ...
#Features MO: 726
[MultiO Feature List]: 0.001
[Download Keypoints]: begin ...
[Download Keypoints]: 0
[Get Descriptor]: begin ...
[Get Descriptor]: 0.005
[Gen. Display VBO]: begin ...
[Gen. Display VBO]: 0.001
[RUN SIFT]: 0.046
./speed -i /home/spple/CLionProjects/SIFT-GPU/data/1600.jpg -fo -1
Initialize and warm up...
Loading image: 73ms, Tex initialization: 66ms
Start 2x30 repetitions...
++++++++++++++++++++++++++++++
##############################
****************************************
[Feature Count]: 10998
[Average Time]: 113.133ms
[Average Speed]: 8.83913hz
[Build Pyramid]: 22.5667ms
[Detection]: 33.9ms
[Feature List]: 8.4ms
[Orientation]: 7.43333ms
[MO Feature List]: 1.36667ms
[Download Keys]: 0ms
[Descriptor]: 39.6ms
****************************************
./MultiThreadSIFT :
修改:
SIFT-GPU/src/TestWin/MultiThreadSIFT.cpp
int main() { //NOTE that SiftGPU must be compiled with CUDA for this demo MultiThreadDemo thread1(0, "/home/spple/CLionProjects/SIFT-GPU/data/640-1.jpg"); MultiThreadDemo thread2(1, "/home/spple/CLionProjects/SIFT-GPU/data/800-1.jpg"); ...... }
运行时候出错:
CUDA not supported in this binary! To enable it, please use SiftGPU_CUDA_Enable
solution for VS2005+ or set siftgpu_enable_cuda to 1 in makefile修改 makefile
https://blog.csdn.net/yrc19950911/article/details/83785908
https://blog.csdn.net/hehehetanchaow/article/details/90378010
ifneq ($(simple_find_cuda), ) siftgpu_enable_cuda = 1 else siftgpu_enable_cuda = 0 endif ........ siftgpu_cuda_options = -arch sm_61
关于GPU算力:
https://www.cnblogs.com/ahuo/p/6904820.html
但是我这里只有一个GPU,0,1代表GPU的驱动号
MultiThreadDemo thread1(0, "/home/spple/CLionProjects/SIFT-GPU/data/640-1.jpg"); MultiThreadDemo thread2(1, "/home/spple/CLionProjects/SIFT-GPU/data/800-1.jpg");
GPU-SIFT封装:
https://www.cnblogs.com/wangguchangqing/p/10132052.html
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
class GpuFeatureDetector{
enum InitStatus{
INIT_OK,
INIT_IS_NOT_SUPPORT,
INIT_VERIFY_FAILED
};
public:
GpuFeatureDetector() = default;
~GpuFeatureDetector() {
if(m_siftGpuDetector) delete m_siftGpuDetector;
if(m_siftGpuMatcher) delete m_siftGpuMatcher;
}
InitStatus create(){
m_siftGpuDetector = new SiftGPU();
char* myargv[4] = {"-fo","-1","-v","1"};
m_siftGpuDetector->ParseParam(4,myargv);
// Set edge threshold, dog threshold
if(m_siftGpuDetector->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED){
cerr << "SiftGPU is not supported!" << endl;
return InitStatus::INIT_IS_NOT_SUPPORT;
}
m_siftGpuMatcher = new SiftMatchGPU();
m_siftGpuMatcher->VerifyContextGL();
m_maxMatch = 4096;
return INIT_OK;
}
void detectAndCompute(const Mat &img,Mat &descriptors,vector &kpts){
assert(img.channels() == 3); // RGB
m_siftGpuDetector->RunSIFT(img.cols,img.rows,img.data,GL_RGB,GL_UNSIGNED_BYTE);
auto num1 = m_siftGpuDetector->GetFeatureNum();
vector des(128 * num1);
vector keypoints(num1);
m_siftGpuDetector->GetFeatureVector(&keypoints[0],&des[0]);
// Trans to Mat
Mat m(des);
descriptors = m.reshape(1,num1).clone();
for(const SiftGPU::SiftKeypoint &kp : keypoints){
KeyPoint t(kp.x,kp.y,kp.s,kp.o);
kpts.push_back(t);
}
}
void transToRootSift(const cv::Mat &siftFeature,cv::Mat &rootSiftFeature){
for(int i = 0; i < siftFeature.rows; i ++){
// Conver to float type
Mat f;
siftFeature.row(i).convertTo(f,CV_32FC1);
normalize(f,f,1,0,NORM_L1); // l1 normalize
sqrt(f,f); // sqrt-root root-sift
rootSiftFeature.push_back(f);
}
}
int gpuMatch(const Mat &des1,const Mat &des2){
m_siftGpuMatcher->SetDescriptors(0,des1.rows,des1.data);
m_siftGpuMatcher->SetDescriptors(1,des2.rows,des2.data);
int (*match_buf)[2] = new int[m_maxMatch][2];
auto matchNum = m_siftGpuMatcher->GetSiftMatch(m_maxMatch,match_buf);
delete[] match_buf;
return matchNum;
}
int gpuMatch(const Mat &des1,const Mat &des2,vector& matches){
m_siftGpuMatcher->SetDescriptors(0,des1.rows,(float*)des1.data);
m_siftGpuMatcher->SetDescriptors(1,des2.rows,(float*)des2.data);
int (*match_buf)[2] = new int[m_maxMatch][2];
auto matchNum = m_siftGpuMatcher->GetSiftMatch(m_maxMatch,match_buf);
for(int i = 0 ;i < matchNum; i ++) {
DMatch dm(match_buf[i][0],match_buf[i][1],0);
matches.push_back(dm);
}
delete[] match_buf;
return matchNum;
}
private:
SiftGPU *m_siftGpuDetector;
SiftMatchGPU *m_siftGpuMatcher;
int m_maxMatch;
};
int main()
{
/////////////////////////////////////////////////////////////////////
///
/// Opencv extract sift
///
///////////////////////////////////////////////////////////////////
// Read image
auto detector = cv::xfeatures2d::SIFT::create();
Mat des;
vector kpts;
string file1 = "/home/liqiang/Documents/shared/8.jpg";
auto t = getTickCount();
auto img = imread(file1);
detector->detectAndCompute(img,noArray(),kpts,des);
auto end = static_cast(getTickCount() - t) / getTickFrequency();
cout << "OpenCV get sift consume:" << end << endl;
cout << "count:" << kpts.size() << endl;
////////////////////////////////////////////////////////////////
///
/// SiftGPU extract sift
///
///////////////////////////////////////////////////////////////
// Declare sift and initlize
SiftGPU sift;
char* myargv[4] = {"-fo","-1","-v","0"};
//char* myargv[5] = { "-m", "-s", "-unpa", "1"};
//char* myargv[4] = {"-fo", "-1", "-cuda", "0"};
sift.ParseParam(4,myargv);
// Check hardware is support siftGPU
int support = sift.CreateContextGL();
if(support != SiftGPU::SIFTGPU_FULL_SUPPORTED){
cerr << "SiftGPU is not supported!" << endl;
return 2;
}
auto img1 = imread("/home/liqiang/Documents/shared/3.jpg");
auto img2 = imread("/home/liqiang/Documents/shared/4.jpg");
auto img3 = imread("/home/liqiang/Documents/shared/5.jpg");
auto img4 = imread("/home/liqiang/Documents/shared/6.jpg");
auto img5 = imread("/home/liqiang/Documents/shared/7.jpg");
auto f = [&sift](Mat &img,vector &des,vector &kpts){
auto t = getTickCount();
sift.RunSIFT(img.cols,img.rows,img.data,GL_RGB,GL_UNSIGNED_BYTE);
auto num1 = sift.GetFeatureNum();
des.resize(128 * num1);
kpts.resize(num1);
sift.GetFeatureVector(&kpts[0],&des[0]);
cout << "=======================================" << endl;
cout << "width x height : " << img.cols << "x" << img.rows << endl;
cout << "Features count:" << num1 << endl;
cout << "Extract features,consume:" << static_cast(getTickCount() - t) / getTickFrequency() << endl;
};
vector des1,des2,des3,des4,des5;
vector kpts1,kpts2,kpts3,kpts4,kpts5;
f(img1,des1,kpts1);
f(img2,des2,kpts2);
f(img3,des3,kpts3);
f(img4,des4,kpts4);
f(img5,des5,kpts5);
SiftMatchGPU matcher;
matcher.VerifyContextGL();
matcher.SetDescriptors(0,kpts1.size(),&des1[0]);
matcher.SetDescriptors(1,kpts2.size(),&des2[0]);
int (*match_buf)[2] = new int[kpts1.size()][2];
t = getTickCount();
int num_match = matcher.GetSiftMatch(kpts1.size(), match_buf);
cout << "====================================" << endl;
cout << "Match keypoints count:" << num_match << endl;
end = static_cast(getTickCount() - t) / getTickFrequency();
cout << "Match,consume:" << end << endl;
////////////////////////////////////////////////////////////////////
///
/// Test class GpuFeatureDetector
///
///////////////////////////////////////////////////////////////////
GpuFeatureDetector fp;
fp.create();
Mat des11,des22;
vector kpts11,kpts22;
fp.detectAndCompute(img1,des11,kpts11);
fp.detectAndCompute(img2,des22,kpts22);
vector matches;
t = getTickCount();
auto matcheNum = fp.gpuMatch(des11,des22,matches);
cout << "gpu matche:" << static_cast(getTickCount() - t) / getTickFrequency() << endl;
cout << "gpu match count:" << matcheNum << endl;
Mat matchImg;
drawMatches(img1,kpts11,img2,kpts22,matches,matchImg);
imshow("gpu matches",matchImg);
//////////////////////////////////////////////////////////////////////
///
/// OpenCV extract sift and match
///
////////////////////////////////////////////////////////////////////
Mat des111,des222;
vector kpts111,kpts222;
detector->detectAndCompute(img1,noArray(),kpts111,des111);
detector->detectAndCompute(img2,noArray(),kpts222,des222);
auto ov_matcher = DescriptorMatcher::create("FlannBased");
const float minRatio = 0.8;
const int k = 2;
vector> knnMatches;
vector betterMatches;
t = getTickCount();
ov_matcher->knnMatch(des111, des222, knnMatches, k);
for (size_t i = 0; i < knnMatches.size(); i++) {
const DMatch &bestMatch = knnMatches[i][0];
const DMatch &betterMatch = knnMatches[i][1];
float distanceRatio = bestMatch.distance / betterMatch.distance;
if (distanceRatio < minRatio)
betterMatches.push_back(bestMatch);
}
cout << "Opencv Match:" << static_cast(getTickCount() - t) / getTickFrequency() << endl;
Mat ovMatchImg;
drawMatches(img1,kpts111,img2,kpts222,betterMatches,ovMatchImg);
imshow("opencv matches",ovMatchImg);
waitKey();
return 0;
}