vs2015使用SiftGPU
环境:win10、vs2015、x64
编译过程参考:
- http://www.cnblogs.com/wangguchangqing/p/10132052.html
- https://www.cnblogs.com/gaoxiang12/p/5149067.html
需要的第三方库:
- Glew
- DevIL-Windows-SDK-1.8.0
使用:
- 项目属性设置include路径到SiftGPU目录下
- 项目属性设置库路径到编译生成的SIFTGPU.lib路径下
- 将动态库SiftGPU.dll、DevIL.dll、glew32.dll拷贝到工程目录
测试代码(需配置OpenCV,这里不介绍配置过程):
SiftGPU.h
#ifndef _SIFTGPU_H
#define _SIFTGPU_H
#include <Windows.h>
#include <gl\GL.h>
#include <opencv2\opencv.hpp>
#include <SiftGPU\SiftGPU.h>
using namespace std;
using namespace cv;
enum InitStatus {
INIT_OK,
INIT_IS_NOT_SUPPORT,
INIT_VERIFY_FAILED
};
class GpuFeatureDetector {
private:
SiftGPU *m_siftGpuDetector;
SiftMatchGPU *m_siftGpuMatcher;
//m_maxMatch是进行匹配时,最多的匹配点的个数,默认为4096
int m_maxMatch;
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<KeyPoint> &kpts) {
clock_t startTimeDetector = clock();
//必须是RGB图像
assert(img.channels() == 3);
m_siftGpuDetector->RunSIFT(img.cols, img.rows, img.data, GL_RGB, GL_UNSIGNED_BYTE);
auto num1 = m_siftGpuDetector->GetFeatureNum();
vector<float> des(128 * num1);
vector<SiftGPU::SiftKeypoint> 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);
}
clock_t endTimeDetector = clock();
cout << "cost time by feature detected: "
<< static_cast<double>(endTimeDetector - startTimeDetector) / CLOCKS_PER_SEC
<< endl;
}
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, vector<DMatch>& matches) {
clock_t startTimeMatch = clock();
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;
clock_t endTimeMatch = clock();
cout << "cost time by match: "
<< static_cast<double>(endTimeMatch - startTimeMatch) / CLOCKS_PER_SEC
<< endl;
return matchNum;
}
};
#endif // !_SIFTGPU_H
main.cpp
#include "SiftGPU.h"
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
using namespace cv;
int main(int argc, char **argv) {
char imageDir[] = "..\\解帧";
GpuFeatureDetector fp;
InitStatus initState = fp.create();
if (initState != InitStatus::INIT_OK)
{
exit(0);
}
Mat image1, image2, des1, des2;
vector<KeyPoint> kp1, kp2;
vector<DMatch> matches;
for (int i = 0; i < 200; i++) {
for (int j = i + 1; j < 200; j++) {
char imgPath1[256];
sprintf(imgPath1, "%s\\%04d.jpg", imageDir, i);
image1 = imread(imgPath1, IMREAD_UNCHANGED);
char imgPath2[256];
sprintf(imgPath2, "%s\\%04d.jpg", imageDir, j);
image2 = imread(imgPath2, IMREAD_UNCHANGED);
kp1.clear();
kp2.clear();
matches.clear();
fp.detectAndCompute(image1, des1, kp1);
fp.detectAndCompute(image2, des2, kp2);
fp.gpuMatch(des1, des2, matches);
Mat matchImg;
drawMatches(image1, kp1, image2, kp2, matches, matchImg);
imshow("matchImg", matchImg);
waitKey(10);
}
}
}
运行结果如下:
如果自己不想进行编译的话,可以直接下载我编译好的库。