我目前正致力于构建可以使用热成像相机匹配从固定点拍摄的红外和非红外图像的软件 .
用例如下:使用红外热像仪和标准相机使用固定点的三脚架拍摄照片 . 拍摄照片后,摄影师想要匹配每个相机的图像 . 在某些情况下,只使用一台摄像机拍摄图像,因为不需要其他图像类型 . 是的,可以使用时间戳匹配图像,但最终用户要求使用计算机视觉匹配图像 .
我查看了StackOverflow上的其他图像匹配帖子 - 他们经常专注于使用直方图匹配和特征检测器 . 直方图匹配不是一个选项,因为我们无法匹配两种图像类型之间的颜色 . 结果,我开发了一个进行特征检测的应用程序 . 除了标准特征检测之外,我还添加了一些逻辑,如果它们不在彼此的某个边界内,则两个关键点无法匹配(查询图像最左侧的关键点与该关键点上的关键点不匹配)候选图像的最右侧) - 此过程发生在下面代码的第3阶段 .
为了让您了解当前的输出,这里有一个有效且无效的匹配-- note the thermographic image is on the left . 我的目标是提高匹配过程的准确性 .
Valid match:
Invalid match:
这是代码:
// for each candidate image specified on the command line, compare it against the query image
Mat img1 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); // loading query image
for(int candidateImage = 0; candidateImage < (argc - 2); candidateImage++) {
Mat img2 = imread(argv[candidateImage + 2], CV_LOAD_IMAGE_GRAYSCALE); // loading candidate image
if(img1.empty() || img2.empty())
{
printf("Can't read one of the images\n");
return -1;
}
// detecting keypoints
SiftFeatureDetector detector;
vector keypoints1, keypoints2;
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
// computing descriptors
SiftDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);
// matching descriptors
BFMatcher matcher(NORM_L1);
vector< vector > matches_stage1;
matcher.knnMatch(descriptors1, descriptors2, matches_stage1, 2);
// use nndr to eliminate weak matches
float nndrRatio = 0.80f;
vector< DMatch > matches_stage2;
for (size_t i = 0; i < matches_stage1.size(); ++i)
{
if (matches_stage1[i].size() < 2)
continue;
const DMatch &m1 = matches_stage1[i][0];
const DMatch &m2 = matches_stage1[i][3];
if(m1.distance <= nndrRatio * m2.distance)
matches_stage2.push_back(m1);
}
// eliminate points which are too far away from each other
vector matches_stage3;
for(int i = 0; i < matches_stage2.size(); i++) {
Point queryPt = keypoints1.at(matches_stage2.at(i).queryIdx).pt;
Point trainPt = keypoints2.at(matches_stage2.at(i).trainIdx).pt;
// determine the lowest number here
int lowestXAxis;
int greaterXAxis;
if(queryPt.x <= trainPt.x) { lowestXAxis = queryPt.x; greaterXAxis = trainPt.x; }
else { lowestXAxis = trainPt.x; greaterXAxis = queryPt.x; }
int lowestYAxis;
int greaterYAxis;
if(queryPt.y <= trainPt.y) { lowestYAxis = queryPt.y; greaterYAxis = trainPt.y; }
else { lowestYAxis = trainPt.y; greaterYAxis = queryPt.y; }
// determine if these points are acceptable
bool acceptable = true;
if( (lowestXAxis + MARGIN) < greaterXAxis) { acceptable = false; }
if( (lowestYAxis + MARGIN) < greaterYAxis) { acceptable = false; }
if(acceptable == false) { continue; }
it's acceptable -- provide details, perform input
matches_stage3.push_back(matches_stage2.at(i));
}
// output how many individual matches were found for this training image
cout << "good matches found for candidate image # " << (candidateImage+1) << " = " << matches_stage3.size() << endl;
我以this sites code为例 . 我遇到的问题是特征检测不可靠,我似乎错过了NNDR比率的目的 . 我理解我在查询图像中为每个点找到K个可能的匹配,并且我有K = 2.但是我不明白示例代码中这部分的用途:
vector< DMatch > matches_stage2;
for (size_t i = 0; i < matches_stage1.size(); ++i)
{
if (matches_stage1[i].size() < 2)
continue;
const DMatch &m1 = matches_stage1[i][0];
const DMatch &m2 = matches_stage1[i][1];
if(m1.distance <= nndrRatio * m2.distance)
matches_stage2.push_back(m1);
}
关于如何进一步改进这一点的任何想法?任何建议将一如既往地受到赞赏 .