传入参数:des1, des2, distRatio(红外图像的特征描述符,可见光图像的描述符,比值阈值)
输出:correctIndex1, correctIndex2, zoom(正确匹配点在第一个图像中的索引correctIndex1
、正确匹配点在第二个图像中的索引correctIndex2
,以及一个代表缩放因子的zoom
值。)
function [correctIndex1, correctIndex2, zoom] = cp_match(des1, des2, distRatio)
%%
zoomvote = zeros(3,size(des2,3));
match1 = zeros(size(des1,1),size(des2,3));
match2 = zeros(size(des2,2),size(des2,3));
% For each descriptor in the first image, select its match to second image.
for i = 1 : size(des1,1)
for j = 1:size(des2,3)
des2t = des2(:,:,j);
dotprods = des1(i,:) * des2t; % Computes vector of dot products
[vals1,indx1] = sort(acos(dotprods)); % Take inverse cosine and sort results
% Check if nearest neighbor has angle less than distRatio times 2nd.
zoomvote(1,j) = 10; % > 2*pi is OK
if vals1(1) < distRatio * vals1(2)
zoomvote(1,j) = vals1(1);
match1(i,j) = indx1(1); % store the matches of each zoom time
end
end
% zoomvote
[mintheta,ind] = min(zoomvote(1,:));
if mintheta ~= 10
zoomvote(2,ind) = zoomvote(2,ind)+1;
end
end
disp(zoomvote(2,:));
% [~,zoom] = max(zoomvote(2,:));
% determine zoom scope
% des2zoom = des2(:,:,zoom)';
% match = match(:,zoom);
%%
des1t = des1';
for j = 1:size(des2,3)
des2zoom = des2(:,:,j)';
for i = 1 : size(des2zoom,1)
dotprods = des2zoom(i,:) * des1t;
[vals1,indx1] = sort(acos(dotprods));
if vals1(1) < distRatio * vals1(2)
match2(i,j) = indx1(1);
end
end
end
%% bilateral match
zoomvote(3,:) = size(des1,1) * ones(1,size(des2,3)); %assume all of match1 are correct
for j = 1:size(des2,3)
for i = 1 : size(des1,1)
if match1(i,j)>0
if match2(match1(i,j),j)~=i
match1(i,j)=0;
zoomvote(3,j) = zoomvote(3,j) - 1;
end
else
zoomvote(3,j) = zoomvote(3,j) - 1;
end
end
end
disp(zoomvote(3,:));
[maxvote, zoom] = max(zoomvote(3,:));
%% obtain match index
correctIndex1 = [];
correctIndex2 = [];
for i = 1 : size(des1,1)
if match1(i,zoom)>0
correctIndex1 = [correctIndex1;i];
correctIndex2 = [correctIndex2;match1(i,zoom)];
end
end
上面这段函数主要分为四部分:
第一部分:For each descriptor in the first image, select its match to second image.
zoomvote = zeros(3,size(des2,3));
match1 = zeros(size(des1,1),size(des2,3));
match2 = zeros(size(des2,2),size(des2,3));
% For each descriptor in the first image, select its match to second image.
for i = 1 : size(des1,1)
for j = 1:size(des2,3)
des2t = des2(:,:,j);
dotprods = des1(i,:) * des2t; % Computes vector of dot products
[vals1,indx1] = sort(acos(dotprods)); % Take inverse cosine and sort results
% Check if nearest neighbor has angle less than distRatio times 2nd.
zoomvote(1,j) = 10; % > 2*pi is OK
if vals1(1) < distRatio * vals1(2)
zoomvote(1,j) = vals1(1);
match1(i,j) = indx1(1); % store the matches of each zoom time
end
end
% zoomvote
[mintheta,ind] = min(zoomvote(1,:));
if mintheta ~= 10
zoomvote(2,ind) = zoomvote(2,ind)+1;
end
end
disp(zoomvote(2,:));
首先,定义了三个变量:zoomvote
、match1
和match2
。zoomvote
是一个3xsize(des2,3)的矩阵,其中每一列存储了相应特征点的最小角度度数、匹配次数和匹配对应的缩放因子。match1
和match2
分别是大小为(size(des1,1), size(des2,3))和(size(des2,2), size(des2,3))的矩阵,用于存储每个描述符在第一个图像和第二个图像中的最佳匹配索引。
接下来,双层循环遍历第一个图像中的所有描述符以及第二个图像中的所有描述符。在每个循环迭代中,将当前描述符附加到第二个图像中的特征描述符des2t
中。然后,计算当前描述符与des2t
中所有描述符的点积,并得到一个点积向量dotprods
。为什么要进行点积呢,点积的含义是什么,因为在图像处理或者文本匹配中,向量的点击表示的是两个向量之间的相似度,用于对特征点匹配时的相似度检测。将点击之后的值按大小排序,并计算最小和第二小值之间的比率。如果最小值小于一个设定的阈值distRatio
乘以第二小值,则将该描述符在两个图像中的索引存储在match1
矩阵中,同时将匹配次数加1,说明des1‘中的点与此时des2中的点具有相似度。
最后,输出zoomvote(2,:)
,即得到每个缩放因子对应的匹配点数量;而zoomvote(3,:)
则记录了所有可能的匹配对数。在这里,还没有选择具有最大匹配次数的缩放因子,需要在后续的代码中进行选择。
总结:这段代码主要是对zoomvote进行操作,zoomvote(1,1)与zoomvote(1,2)在每次迭代中保存符合缩放阈值的数,zoomvote(1,1)存放原始大小的值,zoomvote(1,2)存放扩大一倍的值,zoomvote(2,1)存放符合条件的原始图像特征描述符的个数,zoomvote(2,2)存放符合条件的扩大一倍的特征描述符的个数。
match1一共有两列:
第一列表示des1(红外图像经过cp_descriptor返回的特征描述符返回的特征描述符)与des2(:,:,1)(可见光图像经过cp_descriptor返回的特征描述符,即原图像的特征描述符)经过判断之后是否符合相似阈值,相似则将此点的索引存入match1的第一列的相应位置中。
第二列是des1与des2(:,:,2)(原图像2倍的特征描述符)进行相似度匹配。
第二部分:
des1t = des1';
for j = 1:size(des2,3)
des2zoom = des2(:,:,j)';
for i = 1 : size(des2zoom,1)
dotprods = des2zoom(i,:) * des1t;
[vals1,indx1] = sort(acos(dotprods));
if vals1(1) < distRatio * vals1(2)
match2(i,j) = indx1(1);
end
end
end
与第一部分代码进行对调,使用des2(:,:,:)与des1进行匹配,并对相似度进行判断,之后存入match2中,具体做法与第一部分一样。
第三部分:
这里少说了一部分(倒数两行)
zoomvote(3,:)中保存的是双边匹配中符合要求的点的个数,其中zoomvote(3,1)是des1与des2(:,:,1)匹配的结果,zoomvote(3,2)是des1与des2(:,:,2)匹配的结果,具体的变量含义见上文红字。最后在zoomvote(3,:)中选出最多的匹配点个数与在哪一列的索引。(具体就是匹配了两组坐标进行选择哪一个更合适)。
%% bilateral match
zoomvote(3,:) = size(des1,1) * ones(1,size(des2,3)); %assume all of match1 are correct
for j = 1:size(des2,3)
for i = 1 : size(des1,1)
if match1(i,j)>0
if match2(match1(i,j),j)~=i
match1(i,j)=0;
zoomvote(3,j) = zoomvote(3,j) - 1;
end
else
zoomvote(3,j) = zoomvote(3,j) - 1;
end
end
end
disp(zoomvote(3,:));
[maxvote, zoom] = max(zoomvote(3,:));
zoomvote(3,:)= size(des1,1)
开始进行双边匹配,size(des2,3)作为外循环,size(des1,1)作为内循环。
举例说明:
j=1,i=13
if match1(13,1)> 0
match2(match(13,1),1)~= 13
match1(13,1)=0
去除zoomvote(3,1)中的一个向量。
else
去除zoomvote(3,1)中的一个向量。
match1的值 match2的值
如上图所示,此时这里就表示为所匹配成功的一组特征描述符。
如果不出现上图所示的类型(match2(match1(i,j),j)== i)的判断情况,即为错误的匹配点,则一律删除。
第四部分:
%% obtain match index
correctIndex1 = [];
correctIndex2 = [];
for i = 1 : size(des1,1)
if match1(i,zoom)>0
correctIndex1 = [correctIndex1;i];
correctIndex2 = [correctIndex2;match1(i,zoom)];
end
end
初始化两个数组,用于保存第三部分选择出的具有高相似度的匹配点数,来匹配key和value