I'm trying to match the feature points of a deformed object and the non deformed version of the same object. I know that after the deformation it's applied, I end up with a totally different image, but there are still some feature points in common between the 2 that could be found.
If I don't comment the if (dist < m_InlierThreshold)
condition, I end up with no inlier, most of them being wrong matches.
Could someone tell me what is it that I'm doing wrong?
Here is the output of the feature matching (In this case I limited the number of feature matches for an easier view of the points): MatchingResult
This is the homography matrix that I am using :
7.6285898e-01 -2.9922929e-01 2.2567123e+02
3.3443473e-01 1.0143901e+00 -7.6999973e+01
3.4663091e-04 -1.4364524e-05 1.0000000e+00
Here are the members of the class CImage, of which I'm using the instances with the name m_SourceImage, m_TemplateImage
:
std::string m_ImagePath;
cv::Mat m_Image, m_ImageDescriptors;
std::vector<cv::KeyPoint> m_ImageKeyPoints;
And here are the relevant members of the class that does the feature matching:
CImage m_SourceImage, m_TemplateImage;
float m_InlierThreshold, m_NnMatchRatio;
cv::Mat m_Homography, m_OutputResult;
std::vector<cv::DMatch> m_CorrectImageMatches;
std::vector<std::vector<cv::DMatch> > m_NnMatches;
std::vector<cv::KeyPoint> m_KPMatchedSourceImage, m_KPMatchedTemplateImage, m_InliersSourceImage, m_InliersTemplateImage;
And here we have the functions used for the feature matching and drawing the output:
//-----------------------------------------------------------------------------
void CImageTemplateMatching::AkazeTemplateMatch()
{
AkazeDescriptorsAndKeypointsDetection();
BruteForceMatching();
FindCorrectKeypoints();
CheckMatchesHomographyFit();
MatchOutput();
}
//-----------------------------------------------------------------------------
void CImageTemplateMatching::AkazeDescriptorsAndKeypointsDetection()
{
Ptr<AKAZE> akazeMatch = AKAZE::create();
akazeMatch->detectAndCompute(m_SourceImage.GetImage() , noArray(), m_SourceImage.GetImageKeyPoints(), m_SourceImage.GetImageDescriptors());
akazeMatch->detectAndCompute(m_TemplateImage.GetImage() , noArray(), m_TemplateImage.GetImageKeyPoints(), m_TemplateImage.GetImageDescriptors());
}
//-----------------------------------------------------------------------------
void CImageTemplateMatching::BruteForceMatching()
{
if (m_SourceImage.GetImageDescriptorsRows() > 0 && m_TemplateImage.GetImageDescriptorsRows() > 0)
{
BFMatcher templateMatcher(NORM_HAMMING);
templateMatcher.knnMatch(m_SourceImage.GetImageDescriptors(), m_TemplateImage.GetImageDescriptors(), m_NnMatches, 4);
}
}
//-----------------------------------------------------------------------------
void CImageTemplateMatching::FindCorrectKeypoints()
{
for (size_t i = 0; i < m_NnMatches.size(); i++) {
DMatch firstKPMatched = m_NnMatches[i][0];
float distSourceImage = m_NnMatches[i][0].distance;
float distTemplateImage = m_NnMatches[i][1].distance;
if (distSourceImage < m_NnMatchRatio * distTemplateImage ) {
m_KPMatchedSourceImage.push_back(m_SourceImage.GetImageKeyPoint(firstKPMatched.queryIdx%m_SourceImage.GetImageKeyPointsSize()));
m_KPMatchedTemplateImage.push_back(m_TemplateImage.GetImageKeyPoint(firstKPMatched.queryIdx%m_TemplateImage.GetImageKeyPointsSize()));
}
}
}
//-----------------------------------------------------------------------------
void CImageTemplateMatching::CheckMatchesHomographyFit()
{
unsigned kpSize = max(m_KPMatchedSourceImage.size(), m_KPMatchedTemplateImage.size());
for (int i = 0; i < kpSize; i++)
{
Mat columnCheck = Mat::ones(3, 1, CV_64F);
columnCheck.at<double>(0) = m_KPMatchedSourceImage[i].pt.x;
columnCheck.at<double>(1) = m_KPMatchedSourceImage[i].pt.y;
columnCheck = columnCheck * m_Homography;
columnCheck /= columnCheck.at<double>(2);
float dist = sqrt(pow(columnCheck.at<double>(0) - m_KPMatchedTemlpateImage[i].pt.x, 2) +
pow(columnCheck.at<double>(1) - m_KPMatchedTemplateImage[i].pt.y, 2));
if (dist < m_InlierThreshold) {
int new_i = m_InliersSourceImage.size();
m_InliersSourceImage.push_back(m_KPMatchedSourceImage[i]);
if (i < m_KPMatchedTemplateImage.size())
m_InliersTemplateImage.push_back(m_KPMatchedTemplateImage[i]);
m_CorrectImageMatches.push_back(DMatch(new_i, new_i, 0));
}
}
}
//-----------------------------------------------------------------------------
void CImageTemplateMatching::MatchOutput()
{
drawMatches(m_SourceImage.GetImage(), m_InliersSourceImage, m_TemplateImage.GetImage(), m_InliersTemplateImage, m_CorrectImageMatches, m_OutputResult);
imwrite(m_OutputPath.data(), m_OutputResult);
}
//-----------------------------------------------------------------------------