原文出處:http://blog.csdn.net/chentravelling/article/details/59540828
0.前言
將基於低版本OpenCV(比如2.3.1)的程序,在vs2015+opencv3.0的環境下編譯會報錯:
“未聲明的標識符:SiftFeatureDetector ”
“未聲明的標識符BruteForceMatcher”
查閱才知,sift、surf等等已經被移到opencv_contrib模塊,如果需要在高版本opencv中使用到opencv_contrib模塊,則需要自己進行編譯。其編譯和配置流程,在github.com:opencv/opencv_contrib的README裏寫了:
那麼現在開始自行編譯和配置吧。根據本文內容,成功率應該是99.99%,中途可能會遇到很多問題,我也會再總結一篇。
通過不懈努力,最終成果如下:
一.準備:系統環境和工具
1)系統:win 10 64位
2)opencv:3.0.0
3)opencv_contrib:3.0.0
4)visual studio:2015
5)CMake:3.8.0
1.安裝CMake3.8.0
根據使用的操作系統選擇相應的版本進行下載和安裝即可(點擊下載):
2.下載opencv3.0.0
3.安裝opencv3.0.0
將opencv安裝到指定目錄,比如:H:\opencv
4.下載opencv_contrib3.0.0
附加模塊opencv_contrib最好下載與opencv爲同一版本的。
5.解壓opencv_contrib 3.0.0
將下載好的附加模塊 opencv_contrib-3.0.0.zip 解壓到指定位置,比如:C:\Users\september\Desktop\opencv_contrib-3.0.0
解壓後,opencv_contrib-3.0.0的結構目錄如下:
二.編譯
1.打開cmake
2.輸入opencv源文件路徑
在where is the source code輸入opencv地址/sources地址, 比如:H:/opencv/sources
3.輸入保存編譯結果的路徑
在where to build the libraries輸入保存編譯結果的地址, 比如:H:/opencv/mybuild
比如下圖:
4.第一次編譯
(1)點擊configure,選擇本機的編譯器,最後四位數字才代表vs的版本,比如圖中的2015,代表的是visual studio 2015。
(2)點擊finish,開始第一次編譯。
如果編譯器的版本選錯,第一次編譯時會出錯:
no cmake_c_compiler could be found.
no cmake_cxx_compiler could be found.
第一次編譯完成後會顯示編譯opencv所需要的參數,如圖:
5.第二次編譯
(1)在參數列表中,將Name爲OPENCV_EXTRA_MODULES_PATH的Value設置爲opencv_contrib-3.0.0的路徑/modules,例如:C:/Users/september/Desktop/opencv_contrib-3.0.0/modules
可以在search欄中搜索OPENCV_EXTRA_MODULES_PATH變量,如下圖。
(2)點擊configure,直到configure done。
重點:configure done後,一定要檢查一下參數列表,如果參數列表還有紅色標記的條目,就再嘗試幾次configure,直到所有條目都是白色爲止。
可能錯誤1:unknown cmake command "ocv_define_module"之類的,即存在未知的命令。
原因:可能是opencv版本和opencv_contrib版本不一致,換成一致的就行(本人遇到這個問題的時候,是這樣解決的)
可能錯誤2:在ICV: Downloading ippicv_windows_20141027.zip...時報錯
CMake Error at 3rdparty/ippicv/downloader.cmake:97 (message):
Call Stack (most recent call first):
3rdparty/ippicv/downloader.cmake:108 (_icv_downloader)cmake/OpenCVFindIPP.cmake:212 (include)cmake/OpenCVFindLibsPerf.cmake:12 (include)
CMakeLists.txt:454 (include)
解決:手動下載ippicv_windows_20141027.zip,保存在opencv/sources/3rdparty/ippicv/downloads/windows-b59f865d1ba16e8c84124e19d78eec57
(3)點擊generate,直到generate done
generate done後,會在where to build the binaries中設置的目錄中生成編譯結果。
(4)【該步驟是個人建議】檢查一下附加模版是否成功編譯並加入到opencv中。如果附加模塊opencv_contrib並未成功編譯到opencv中,那後面再忙活都是白乾。因爲後面的步驟都比較費時,而且最終到了使用SIFT的時候纔會發現附加模塊增加失敗,而且難以鎖定原因,必須返回來逐步檢查。所以個人建議不要跳過這一步,很簡單。
如下圖,進入where to build the binaries中設置的目錄,然後進入modules,查看一下是否有xfeatures2d這類的文件。這類文件是屬於附加模版opencv_contrib的,如果沒有,請檢查一下CMake中參數列表裏,OPENCV_EXTRA_MODULES_PATH的Value是否爲opencv_contrib-3.0.0的路徑/modules,如果不是,請重新設置OPENCV_EXTRA_MODULES_PATH的Value爲opencv_contrib-3.0.0的路徑/modules,然後重新configure、generate。如果附加模塊opencv_contrib並未成功編譯到opencv中,那後面就夠忙活的了,後面更費時,而且最終會配置失敗,還難以想到
三.生成庫文件
1.打開OpenCV.sln
方式1:在CMake界面點擊open project
方式2:進入where to build the binaries中設置的路徑下找到OpenCV.sln,並點擊即可,此時本機的vs會打開OpenCV項目方案。
2.生成.dll和.lib文件
OpenCV.sln項目加載完後(項目個數應該在130~140左右),右鍵點擊CMakeTargets,然後選擇生成。這步完成後,在where to build the binaries中設置的路徑下會多一個install文件,其中就是我們需要的配置文件了。
四.配置
接下來的配置,就和以往配置opencv的流程一樣,只是現在是使用自己編譯的包含了附加模塊的opencv。
1.系統環境變量
在計算機-環境變量-path中增加:where to build the binaries中設置的路徑\install\x86\vc14\bin
2.配置新建的工程
(1)VC++目錄-包含目錄:
<where to build the binaries中設置的路徑>\install\include
<where to build the binaries中設置的路徑>\install\include\opencv
<where to build the binaries中設置的路徑>\install\include\opencv2
- 1
- 2
- 3
- 1
- 2
- 3
如下圖:
(2)VC++目錄-庫目錄:
<where to build the binaries中設置的路徑>\install\x86\vc14\lib
<where to build the binaries中設置的路徑>\install\x86\vc14\staticlib
- 1
- 2
- 1
- 2
如下圖:
(3)鏈接器-輸入-附加依賴項:
可能因爲不同的人編譯時添加的附加模塊不一樣而造成最終的.lib不一樣,所以附加依賴項裏添加的.lib文件都需要出現在:< where to build the binaries中設置的路徑>\install\x86\vc14\lib中,否則在編譯程序的時候會出現XXX.lib加載失敗、丟失、找不到之類的錯誤,因爲這個.lib根本不存在,但是可能被添加在附加依賴項裏了。比如我的:
opencv_bgsegm300d.lib
opencv_calib3d300d.lib
opencv_ccalib300d.lib
opencv_core300d.lib
opencv_datasets300d.lib
opencv_face300d.lib
opencv_features2d300d.lib
opencv_flann300d.lib
opencv_hal300d.lib
opencv_highgui300d.lib
opencv_imgcodecs300d.lib
opencv_imgproc300d.lib
opencv_line_descriptor300d.lib
opencv_ml300d.lib
opencv_objdetect300d.lib
opencv_optflow300d.lib
opencv_photo300d.lib
opencv_reg300d.lib
opencv_rgbd300d.lib
opencv_saliency300d.lib
opencv_shape300d.lib
opencv_stitching300d.lib
opencv_superres300d.lib
opencv_surface_matching300d.lib
opencv_text300d.lib
opencv_tracking300d.lib
opencv_ts300d.lib
opencv_video300d.lib
opencv_videoio300d.lib
opencv_videostab300d.lib
opencv_xfeatures2d300d.lib
opencv_ximgproc300d.lib
opencv_xobjdetect300d.lib
opencv_xphoto300d.lib
五.測試
前面的四大部分完成了opencv和opencv_contrib的編譯和配置,也完成了項目的配置,現在就是檢驗的時候了。
1.添加源碼
在項目源文件中新建main.cpp:
#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\xfeatures2d.hpp>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
int main()
{
Mat firstImage = imread("26.jpg");
Mat secondImage = imread("27.jpg");
if (firstImage.empty() || secondImage.empty())
{
cout << "error" << endl;
return 0;
}
//resize(firstImage,firstImage,Size(800,1000),0,0,1);
//resize(secondImage,secondImage,Size(800,1000),0,0,1);
////////////////////////////////////////////////////////////////////////////////
//第一步:獲取SIFT特徵
////////////////////////////////////////////////////////////////////////////////
//difine a sift detector
Ptr<SIFT> sift = SIFT::create();
//sift->detect();
//SiftFeatureDetector siftDetector;
//store key points
vector<KeyPoint> firstKeypoint, secondKeypoint;
//detect image with SIFT,get key points
sift->detect(firstImage, firstKeypoint);
sift->detect(secondImage, secondKeypoint);
Mat firstOutImage, secondOutImage;
//draw key points at the out image and show to the user
drawKeypoints(firstImage, firstKeypoint, firstOutImage, Scalar(255, 0, 0));
drawKeypoints(secondImage, secondKeypoint, secondOutImage, Scalar(0, 255, 0));
imshow("first", firstOutImage);
imshow("second", secondOutImage);
Mat firstDescriptor, secondDescriptor;
sift->compute(firstImage,firstKeypoint,firstDescriptor);
sift->compute(secondImage,secondKeypoint,secondDescriptor);
Ptr<DescriptorMatcher > matcher = DescriptorMatcher::create("BruteForce");
Mat masks;
vector<DMatch> matches;
matcher->match(firstDescriptor, secondDescriptor, matches, masks);
////////////////////////////////////////////////////////////////////////////////
//第二步:RANSAC方法剔除outliner
////////////////////////////////////////////////////////////////////////////////
Mat matcheImage;
//將vector轉化成Mat
Mat firstKeypointMat(matches.size(), 2, CV_32F), secondKeypointMat(matches.size(), 2, CV_32F);
for (int i = 0; i<matches.size(); i++)
{
firstKeypointMat.at<float>(i, 0) = firstKeypoint[matches[i].queryIdx].pt.x;
firstKeypointMat.at<float>(i, 1) = firstKeypoint[matches[i].queryIdx].pt.y;
secondKeypointMat.at<float>(i, 0) = secondKeypoint[matches[i].trainIdx].pt.x;
secondKeypointMat.at<float>(i, 1) = secondKeypoint[matches[i].trainIdx].pt.y;
}
//Calculate the fundamental Mat;
vector<uchar> ransacStatus;
Mat fundamentalMat = findFundamentalMat(firstKeypointMat, secondKeypointMat, ransacStatus, FM_RANSAC);
cout << fundamentalMat << endl;
//Calculate the number of outliner points;
int outlinerCount = 0;
for (int i = 0; i<matches.size(); i++)
{
if (ransacStatus[i] == 0)
{
outlinerCount++;
}
}
//Calculate inliner points;
vector<Point2f> firstInliner;
vector<Point2f> secondInliner;
vector<DMatch> inlinerMatches;
int inlinerCount = matches.size() - outlinerCount;
firstInliner.resize(inlinerCount);
secondInliner.resize(inlinerCount);
inlinerMatches.resize(inlinerCount);
int index = 0;
for (int i = 0; i<matches.size(); i++)
{
if (ransacStatus[i] != 0)
{
firstInliner[index].x = firstKeypointMat.at<float>(i, 0);
firstInliner[index].y = firstKeypointMat.at<float>(i, 1);
secondInliner[index].x = secondKeypointMat.at<float>(i, 0);
secondInliner[index].y = secondKeypointMat.at<float>(i, 1);
inlinerMatches[index].queryIdx = index;
inlinerMatches[index].trainIdx = index;
index++;
}
}
vector<KeyPoint> inlinerFirstKeypoint(inlinerCount);
vector<KeyPoint> inlinerSecondKeypoint(inlinerCount);
KeyPoint::convert(firstInliner, inlinerFirstKeypoint);
KeyPoint::convert(secondInliner, inlinerSecondKeypoint);
//cout<<fundamentalMat<<endl;
//select 50 keypoints
//matches.erase(matches.begin()+50,matches.end());
//inlinerMatches.erase(inlinerMatches.begin()+50,inlinerMatches.end());
drawMatches(firstImage, inlinerFirstKeypoint, secondImage, inlinerSecondKeypoint, inlinerMatches, matcheImage);
imshow("ransacMatches", matcheImage);
drawMatches(firstImage, firstKeypoint, secondImage, secondKeypoint, matches, matcheImage);
imshow("matches", matcheImage);
waitKey(0);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
2.運行
到此,windows 10 + vs2015+ opencv3.0.0 的環境下,使用opencv_contrib附加模塊就完美解決了,SIFT、SURF也能正常使用了。整個編譯、配置過程,會遇到各種各樣的問題,總之,堅持不懈吧~誰讓opencv不是咱自己寫的呢~