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());
112 detector = cv::xfeatures2d::SIFT::create();
114 detector->detect(objectImg, objectKeypoints);
115 printf(
"Object: %d keypoints detected in %d ms\n", (
int)objectKeypoints.size(), time.restart());
116 detector->detect(sceneImg, sceneKeypoints);
117 printf(
"Scene: %d keypoints detected in %d ms\n", (
int)sceneKeypoints.size(), time.restart());
122 cv::Ptr<cv::DescriptorExtractor> extractor;
123 #if CV_MAJOR_VERSION == 2 127 extractor = cv::Ptr<cv::DescriptorExtractor>(
new cv::SIFT());
132 extractor = cv::xfeatures2d::SIFT::create();
134 extractor->compute(objectImg, objectKeypoints, objectDescriptors);
135 printf(
"Object: %d descriptors extracted in %d ms\n", objectDescriptors.rows, time.restart());
136 extractor->compute(sceneImg, sceneKeypoints, sceneDescriptors);
137 printf(
"Scene: %d descriptors extracted in %d ms\n", sceneDescriptors.rows, time.restart());
144 std::vector<std::vector<cv::DMatch> > matches;
146 bool useBFMatcher =
false;
147 if(objectDescriptors.type()==CV_8U)
150 printf(
"Binary descriptors detected...\n");
153 cv::BFMatcher matcher(cv::NORM_HAMMING);
154 matcher.knnMatch(objectDescriptors, sceneDescriptors, matches, k);
159 cv::flann::Index flannIndex(sceneDescriptors, cv::flann::LshIndexParams(12, 20, 2), cvflann::FLANN_DIST_HAMMING);
160 printf(
"Time creating FLANN LSH index = %d ms\n", time.restart());
163 flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() );
169 printf(
"Float descriptors detected...\n");
172 cv::BFMatcher matcher(cv::NORM_L2);
173 matcher.knnMatch(objectDescriptors, sceneDescriptors, matches, k);
178 cv::flann::Index flannIndex(sceneDescriptors, cv::flann::KDTreeIndexParams(), cvflann::FLANN_DIST_EUCLIDEAN);
179 printf(
"Time creating FLANN KDTree index = %d ms\n", time.restart());
182 flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() );
185 printf(
"Time nearest neighbor search = %d ms\n", time.restart());
188 if(dists.type() == CV_32S)
191 dists.convertTo(temp, CV_32F);
204 float nndrRatio = 0.8f;
205 std::vector<cv::Point2f> mpts_1, mpts_2;
206 std::vector<int> indexes_1, indexes_2;
207 std::vector<uchar> outlier_mask;
211 for(
int i=0; i<objectDescriptors.rows; ++i)
215 if(results.at<
int>(i,0) >= 0 && results.at<
int>(i,1) >= 0 &&
216 dists.at<
float>(i,0) <= nndrRatio * dists.at<
float>(i,1))
218 mpts_1.push_back(objectKeypoints.at(i).pt);
219 indexes_1.push_back(i);
221 mpts_2.push_back(sceneKeypoints.at(results.at<
int>(i,0)).pt);
222 indexes_2.push_back(results.at<
int>(i,0));
228 for(
unsigned int i=0; i<matches.size(); ++i)
232 if(matches.at(i).size() == 2 &&
233 matches.at(i).at(0).distance <= nndrRatio * matches.at(i).at(1).distance)
235 mpts_1.push_back(objectKeypoints.at(matches.at(i).at(0).queryIdx).pt);
236 indexes_1.push_back(matches.at(i).at(0).queryIdx);
238 mpts_2.push_back(sceneKeypoints.at(matches.at(i).at(0).trainIdx).pt);
239 indexes_2.push_back(matches.at(i).at(0).trainIdx);
245 unsigned int minInliers = 8;
246 if(mpts_1.size() >= minInliers)
249 cv::Mat H = findHomography(mpts_1,
254 printf(
"Time finding homography = %d ms\n", time.restart());
255 int inliers=0, outliers=0;
256 for(
unsigned int k=0; k<mpts_1.size();++k)
258 if(outlier_mask.at(k))
267 QTransform hTransform(
268 H.at<
double>(0,0), H.at<
double>(1,0), H.at<
double>(2,0),
269 H.at<
double>(0,1), H.at<
double>(1,1), H.at<
double>(2,1),
270 H.at<
double>(0,2), H.at<
double>(1,2), H.at<
double>(2,2));
273 QColor color(Qt::green);
275 color.setAlpha(alpha);
276 for(
unsigned int k=0; k<mpts_1.size();++k)
278 if(outlier_mask.at(k))
285 objWidget.
setKptColor(indexes_1.at(k), QColor(255,0,0,alpha));
286 sceneWidget.
setKptColor(indexes_2.at(k), QColor(255,0,0,alpha));
291 QGraphicsRectItem * rectItem =
new QGraphicsRectItem(objWidget.
pixmap().rect());
292 rectItem->setPen(rectPen);
293 rectItem->setTransform(hTransform);
295 printf(
"Inliers=%d Outliers=%d\n", inliers, outliers);
299 printf(
"Not enough matches (%d) for homography...\n", (
int)mpts_1.size());
304 objWidget.setWindowTitle(
"Object");
305 if(objWidget.
pixmap().width() <= 800)
307 objWidget.setMinimumSize(objWidget.
pixmap().width(), objWidget.
pixmap().height());
311 objWidget.setMinimumSize(800, 600);
316 sceneWidget.setWindowTitle(
"Scene");
317 if(sceneWidget.
pixmap().width() <= 800)
319 sceneWidget.setMinimumSize(sceneWidget.
pixmap().width(), sceneWidget.
pixmap().height());
323 sceneWidget.setMinimumSize(800, 600);
331 printf(
"Closing...\n");
337 printf(
"Images are not valid!\n");
int main(int argc, char *argv[])
FINDOBJECT_EXP QImage cvtCvMat2QImage(const cv::Mat &image, bool isBgr=true)