31 #include <QtCore/QTime> 32 #include <QtCore/QTimer> 33 #include <QApplication> 34 #include <QGraphicsRectItem> 39 #include <opencv2/core/core.hpp> 40 #include <opencv2/highgui/highgui.hpp> 41 #include <opencv2/features2d/features2d.hpp> 42 #include <opencv2/calib3d/calib3d.hpp> 44 #include <opencv2/opencv_modules.hpp> 46 #ifdef HAVE_OPENCV_NONFREE 47 #if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >=4 48 #include <opencv2/nonfree/gpu.hpp> 49 #include <opencv2/nonfree/features2d.hpp> 52 #ifdef HAVE_OPENCV_XFEATURES2D 53 #include <opencv2/xfeatures2d.hpp> 54 #include <opencv2/xfeatures2d/cuda.hpp> 68 printf(
" ./example object.png scene.png\n");
72 int main(
int argc,
char * argv[])
81 QApplication
app(argc, argv);
85 cv::Mat objectImg = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
86 cv::Mat sceneImg = cv::imread(argv[2], cv::IMREAD_GRAYSCALE);
88 if(!objectImg.empty() && !sceneImg.empty())
90 printf(
"Loading images: %d ms\n", time.restart());
91 std::vector<cv::KeyPoint> objectKeypoints;
92 std::vector<cv::KeyPoint> sceneKeypoints;
93 cv::Mat objectDescriptors;
94 cv::Mat sceneDescriptors;
99 cv::Ptr<cv::FeatureDetector> detector;
101 #if CV_MAJOR_VERSION == 2 107 detector = cv::Ptr<cv::FeatureDetector>(
new cv::SIFT());
111 #elif CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION < 3) 112 detector = cv::xfeatures2d::SIFT::create();
114 detector = cv::SIFT::create();
116 detector->detect(objectImg, objectKeypoints);
117 printf(
"Object: %d keypoints detected in %d ms\n", (
int)objectKeypoints.size(), time.restart());
118 detector->detect(sceneImg, sceneKeypoints);
119 printf(
"Scene: %d keypoints detected in %d ms\n", (
int)sceneKeypoints.size(), time.restart());
124 cv::Ptr<cv::DescriptorExtractor> extractor;
125 #if CV_MAJOR_VERSION == 2 129 extractor = cv::Ptr<cv::DescriptorExtractor>(
new cv::SIFT());
133 #elif CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION < 3) 134 extractor = cv::xfeatures2d::SIFT::create();
136 extractor = cv::SIFT::create();
138 extractor->compute(objectImg, objectKeypoints, objectDescriptors);
139 printf(
"Object: %d descriptors extracted in %d ms\n", objectDescriptors.rows, time.restart());
140 extractor->compute(sceneImg, sceneKeypoints, sceneDescriptors);
141 printf(
"Scene: %d descriptors extracted in %d ms\n", sceneDescriptors.rows, time.restart());
148 std::vector<std::vector<cv::DMatch> > matches;
150 bool useBFMatcher =
false;
151 if(objectDescriptors.type()==CV_8U)
154 printf(
"Binary descriptors detected...\n");
157 cv::BFMatcher matcher(cv::NORM_HAMMING);
158 matcher.knnMatch(objectDescriptors, sceneDescriptors, matches, k);
163 cv::flann::Index flannIndex(sceneDescriptors, cv::flann::LshIndexParams(12, 20, 2), cvflann::FLANN_DIST_HAMMING);
164 printf(
"Time creating FLANN LSH index = %d ms\n", time.restart());
167 flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() );
173 printf(
"Float descriptors detected...\n");
176 cv::BFMatcher matcher(cv::NORM_L2);
177 matcher.knnMatch(objectDescriptors, sceneDescriptors, matches, k);
182 cv::flann::Index flannIndex(sceneDescriptors, cv::flann::KDTreeIndexParams(), cvflann::FLANN_DIST_EUCLIDEAN);
183 printf(
"Time creating FLANN KDTree index = %d ms\n", time.restart());
186 flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() );
189 printf(
"Time nearest neighbor search = %d ms\n", time.restart());
192 if(dists.type() == CV_32S)
195 dists.convertTo(temp, CV_32F);
208 float nndrRatio = 0.8f;
209 std::vector<cv::Point2f> mpts_1, mpts_2;
210 std::vector<int> indexes_1, indexes_2;
211 std::vector<uchar> outlier_mask;
215 for(
int i=0; i<objectDescriptors.rows; ++i)
219 if(results.at<
int>(i,0) >= 0 && results.at<
int>(i,1) >= 0 &&
220 dists.at<
float>(i,0) <= nndrRatio * dists.at<
float>(i,1))
222 mpts_1.push_back(objectKeypoints.at(i).pt);
223 indexes_1.push_back(i);
225 mpts_2.push_back(sceneKeypoints.at(results.at<
int>(i,0)).pt);
226 indexes_2.push_back(results.at<
int>(i,0));
232 for(
unsigned int i=0; i<matches.size(); ++i)
236 if(matches.at(i).size() == 2 &&
237 matches.at(i).at(0).distance <= nndrRatio * matches.at(i).at(1).distance)
239 mpts_1.push_back(objectKeypoints.at(matches.at(i).at(0).queryIdx).pt);
240 indexes_1.push_back(matches.at(i).at(0).queryIdx);
242 mpts_2.push_back(sceneKeypoints.at(matches.at(i).at(0).trainIdx).pt);
243 indexes_2.push_back(matches.at(i).at(0).trainIdx);
249 unsigned int minInliers = 8;
250 if(mpts_1.size() >= minInliers)
253 cv::Mat H = findHomography(mpts_1,
258 printf(
"Time finding homography = %d ms\n", time.restart());
259 int inliers=0, outliers=0;
260 for(
unsigned int k=0; k<mpts_1.size();++k)
262 if(outlier_mask.at(k))
271 QTransform hTransform(
272 H.at<
double>(0,0), H.at<
double>(1,0), H.at<
double>(2,0),
273 H.at<
double>(0,1), H.at<
double>(1,1), H.at<
double>(2,1),
274 H.at<
double>(0,2), H.at<
double>(1,2), H.at<
double>(2,2));
277 QColor color(Qt::green);
279 color.setAlpha(alpha);
280 for(
unsigned int k=0; k<mpts_1.size();++k)
282 if(outlier_mask.at(k))
289 objWidget.
setKptColor(indexes_1.at(k), QColor(255,0,0,alpha));
290 sceneWidget.
setKptColor(indexes_2.at(k), QColor(255,0,0,alpha));
295 QGraphicsRectItem * rectItem =
new QGraphicsRectItem(objWidget.
pixmap().rect());
296 rectItem->setPen(rectPen);
297 rectItem->setTransform(hTransform);
299 printf(
"Inliers=%d Outliers=%d\n", inliers, outliers);
303 printf(
"Not enough matches (%d) for homography...\n", (
int)mpts_1.size());
308 objWidget.setWindowTitle(
"Object");
309 if(objWidget.
pixmap().width() <= 800)
311 objWidget.setMinimumSize(objWidget.
pixmap().width(), objWidget.
pixmap().height());
315 objWidget.setMinimumSize(800, 600);
320 sceneWidget.setWindowTitle(
"Scene");
321 if(sceneWidget.
pixmap().width() <= 800)
323 sceneWidget.setMinimumSize(sceneWidget.
pixmap().width(), sceneWidget.
pixmap().height());
327 sceneWidget.setMinimumSize(800, 600);
335 printf(
"Closing...\n");
341 printf(
"Images are not valid!\n");
int main(int argc, char *argv[])
FINDOBJECT_EXP QImage cvtCvMat2QImage(const cv::Mat &image, bool isBgr=true)