OpenCV Description:
Feature Matcher:
cv::Stitcher::stitch(InputArrayOfArrays images, const std::vector<std::vectorcv::Rect> &rois, OutputArray pano)
Stitcher::Status Stitcher::stitch(InputArrayOfArrays images, const std::vector<std::vector<Rect> > &rois, OutputArray pano)
{
Status status = estimateTransform(images, rois);
if (status != OK)
return status;
return composePanorama(pano);
}
globalDescIdx라는 argument를 사용하고 있는 function들은 다음과 같다.
void DescriptorMatcher::DescriptorCollection::getLocalIdx( int globalDescIdx, int& imgIdx, int& localDescIdx ) const
{
CV_Assert( (globalDescIdx>=0) && (globalDescIdx < size()) );
std::vector<int>::const_iterator img_it = std::upper_bound(startIdxs.begin(), startIdxs.end(), globalDescIdx);
--img_it;
imgIdx = (int)(img_it - startIdxs.begin());
localDescIdx = globalDescIdx - (*img_it);
}
const Mat DescriptorMatcher::DescriptorCollection::getDescriptor( int globalDescIdx ) const
{
CV_Assert( globalDescIdx < size() );
return mergedDescriptors.row( globalDescIdx );
}
cv::Stitcher를 사용하기 위해서는 cv::Stitcher Stitcher::createDefault(bool try_use_gpu) 를 가장 먼저 선언해주어야 한다. 이때 구성되는 FeaturesFinder 및 FeaturesMatcher관련 코드는 다음과 같다.
// FeaturesFinder Related Code !
#ifdef HAVE_OPENCV_XFEATURES2D
stitcher.setFeaturesFinder(makePtr<detail::SurfFeaturesFinder>());
#else
stitcher.setFeaturesFinder(makePtr<detail::OrbFeaturesFinder>());
#endif
// FeaturesMatcher Related Code !
stitcher.setFeaturesMatcher(makePtr<detail::BestOf2NearestMatcher>(try_use_gpu));
CUDA를 사용하고 있지 않으므로 matcher는 다음과 같은 CpuMatcher를 사용하고 있다.
BestOf2NearestMatcher::BestOf2NearestMatcher(bool try_use_gpu, float match_conf, int num_matches_thresh1, int num_matches_thresh2)
{
(void)try_use_gpu;
#ifdef HAVE_OPENCV_CUDAFEATURES2D
if (try_use_gpu && getCudaEnabledDeviceCount() > 0)
{
impl_ = makePtr<GpuMatcher>(match_conf);
}
else
#endif
{
impl_ = makePtr<CpuMatcher>(match_conf);
}
is_thread_safe_ = impl_->isThreadSafe();
num_matches_thresh1_ = num_matches_thresh1;
num_matches_thresh2_ = num_matches_thresh2;
}
CpuMatcher Constructor
class CpuMatcher : public FeaturesMatcher
{
public:
CpuMatcher(float match_conf) : FeaturesMatcher(true), match_conf_(match_conf) {}
void match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info);
private:
float match_conf_;
};
CpuMatcher match
void CpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info)
{
Ptr<cv::DescriptorMatcher> matcher;
Ptr<flann::IndexParams> indexParams = makePtr<flann::KDTreeIndexParams>();
Ptr<flann::SearchParams> searchParams = makePtr<flann::SearchParams>();
if (features2.descriptors.depth() == CV_8U)
{
indexParams->setAlgorithm(cvflann::FLANN_INDEX_LSH);
searchParams->setAlgorithm(cvflann::FLANN_INDEX_LSH);
}
matcher = makePtr<FlannBasedMatcher>(indexParams, searchParams);
std::vector< std::vector<DMatch> > pair_matches;
MatchesSet matches;
// Find 1->2 matches
matcher->knnMatch(features1.descriptors, features2.descriptors, pair_matches, 2);
~~~~
}
ORB로 추출했을 때의 결과
To see img1 keypoints: 29, des: [32 x 29]
To see img2 keypoints: 500, des: [32 x 500]
To see img3 keypoints: 497, des: [32 x 497]
To see des1 and des2 matching: 29
To see des2 and des3 matching: 500
*** 위에서 분석한 함수들을 사용한 결과 **(SURF + knnMatch) *****
To see img1 keypoints: 1, des: [64 x 1]
To see img2 keypoints: 366, des: [64 x 366]
To see img3 keypoints: 212, des: [64 x 212]
To see des1 and des2 matching: 1
To see des2 and des3 matching: 366
[Example Code] -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_core -lopencv_stitching -lopencv_features2d -lopencv_flann -lopencv_xfeatures2d 사용!
cv::Mat des1, des2, des3;
std::vector<cv::KeyPoint> kpt1, kpt2, kpt3;
cv::Ptr<cv::xfeatures2d::SURF> surf = cv::xfeatures2d::SURF::create(300);
surf -> detectAndCompute(left, cv::Mat(), kpt1, des1);
surf -> detectAndCompute(front, cv::Mat(), kpt2, des2);
surf -> detectAndCompute(right, cv::Mat(), kpt3, des3);
/* ------------------Solution Part !!------------------- */
if(kpt1.size() < 2 || kpt2.size() < 2 || kpt3.size() < 2)
return;
/* ----------------------------------------------------- */
cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create(cv::DescriptorMatcher::FLANNBASED);
std::vector<std::vector<cv::DMatch>> matches1, matches2;
matcher -> knnMatch(des1, des2, matches1, 2);
matcher -> knnMatch(des2, des3, matches2, 2);