3

基于准则匹配的图像对准 - 归去_来兮

 1 year ago
source link: https://www.cnblogs.com/flyup/p/17019719.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

  在图像处理相关的问题中,图像对准是一类典型的问题,也就是要将两幅图严丝合缝地对应起来。通常来讲,两幅图大小不一,一个是模板,一个是母图,也就是要在母图中搜寻定位到与模板图最为接近的区域。
  实现的方式有很多,惯常使用的是基于准则匹配的方法和基于特征匹配的方法。基于准则匹配,就是直接地对图的灰度值矩阵进行计算操作,以特定的准则遍历整个母图,找到与目标图(模板图)最相近的子区域;基于特征匹配,就是先提取出图像特征,再基于特征进行操作。这里对基于准则匹配的图像对准基本方法做简单介绍。

二、匹配准则

  常见的匹配准则有SAD、MAD、SSD、MSD、NCC。前四种是基于两个矩阵的向量差做运算,NCC是计算两个矩阵的相关系数。事实上,矩阵是一个高阶向量(二阶张量),对两个矩阵向量作差,就得到差向量,对差向量做分析运算,便可在一定程度上获得两个矩阵间的差异性信息。
设A=(aij)A=(aij),B=(bij)B=(bij),i=1,2,...,Mi=1,2,...,M,j=1,2,...,Nj=1,2,...,N.则差向量
D=A−B=(aij−bij)D=A−B=(aij−bij)

(1) SAD

  SAD,绝对误差算法(Sum of Absolute Differences),它是差向量D中各元素的绝对值之和,也就是L1范数,是两个向量间的曼哈顿距离。表达式为
SAD=∑i=1M∑j=1N|aij−bij|SAD=∑i=1M∑j=1N|aij−bij|

(2) MAD

  MAD,平均绝对误差算法(Mean Absolute Differences),它是在SAD基础上进一步求平均值。表达式为
MAD=1M×N∑i=1M∑j=1N|aij−bij|MAD=1M×N∑i=1M∑j=1N|aij−bij|

(3) SSD

  SSD,误差平方和算法(Sum of Squared Differences),它是差向量D中各元素的平方和。表达式为
SSD=∑i=1M∑j=1N(aij−bij)2SSD=∑i=1M∑j=1N(aij−bij)2

(4) MSD

  MSD,平均误差平方和算法(Mean Square Differences),它是在SSD的基础上进一步求平均值。表达式为
MSD=1M×N∑i=1M∑j=1N(aij−bij)2MSD=1M×N∑i=1M∑j=1N(aij−bij)2

(5) NCC

  NCC,归一化互相关算法(Normalized Cross Correlation)。若将两个矩阵看做两个随机变量,那么NCC就是两个变量之间的皮尔逊相关系数。同时,它也是两个矩阵向量在各自中心化之后彼此间空间夹角的余弦值。它的表达式为
NCC=∑Mi=1∑Nj=1(aij−E(A))(bij−E(B))∑Mi=1∑Nj=1(aij−E(A))2−−−−−−−−−−−−−−−−−−−−√⋅∑Mi=1∑Nj=1(bij−E(B))2−−−−−−−−−−−−−−−−−−−−√NCC=∑i=1M∑j=1N(aij−E(A))(bij−E(B))∑i=1M∑j=1N(aij−E(A))2⋅∑i=1M∑j=1N(bij−E(B))2
  易知,ncc值的范围为 [−1,1][−1,1],越接近1,两个矩阵越相关;越接近-1,两个矩阵越不相关。


等同于皮尔逊相关系数
  皮尔逊相关系数,用以衡量两个变量间的线性相关性。它的表达式为
Pearson=Cov(X,Y)D(X)−−−−−√⋅D(Y)−−−−−√=E(X−EX)(Y−EY)D(X)−−−−−√⋅D(Y)−−−−−√Pearson=Cov(X,Y)D(X)⋅D(Y)=E(X−EX)(Y−EY)D(X)⋅D(Y)
  将两个矩阵看做两个随机变量代入,有
Pearson=1M×N∑Mi=1∑Nj=1(aij−E(A))(bij−E(B))∑Mi=1∑Nj=1(aij−E(A))2M×N−−−−−−−−−−−−−−−√⋅∑Mi=1∑Nj=1(bij−E(B))2M×N−−−−−−−−−−−−−−−√=∑Mi=1∑Nj=1(aij−E(A))(bij−E(B))∑Mi=1∑Nj=1(aij−E(A))2−−−−−−−−−−−−−−−−−−−−√∑Mi=1∑Nj=1(bij−E(B))2−−−−−−−−−−−−−−−−−−−−√=NCCPearson=1M×N∑i=1M∑j=1N(aij−E(A))(bij−E(B))∑i=1M∑j=1N(aij−E(A))2M×N⋅∑i=1M∑j=1N(bij−E(B))2M×N=∑i=1M∑j=1N(aij−E(A))(bij−E(B))∑i=1M∑j=1N(aij−E(A))2∑i=1M∑j=1N(bij−E(B))2=NCC

等同于余弦距离
  余弦距离即空间向量夹角的余弦值,通常用以衡量两个向量间的差异度。它的表达式为
cosθ=<X,Y>|X|⋅|Y|cosθ=<X,Y>|X|⋅|Y|
  将两个矩阵向量去中心化后代入,有
cosθ=<A−E(A),B−E(B)>|A−E(A)|⋅|B−E(B)|=∑Mi=1∑Nj=1(aij−E(A))(bij−E(B))∑Mi=1∑Nj=1(aij−E(A))2−−−−−−−−−−−−−−−−−−−−√∑Mi=1∑Nj=1(bij−E(B))2−−−−−−−−−−−−−−−−−−−−√=NCCcosθ=<A−E(A),B−E(B)>|A−E(A)|⋅|B−E(B)|=∑i=1M∑j=1N(aij−E(A))(bij−E(B))∑i=1M∑j=1N(aij−E(A))2∑i=1M∑j=1N(bij−E(B))2=NCC

三、matlab实现

(1) SAD

clear all;
close all; clc;

%1.读取图片
img_A_dir = '.\data\lena.bmp';  %待寻母图
img_A_raw = imread(img_A_dir);
[r1,c1,d1] = size(img_A_raw);
if d1==3 %灰度化
    img_A = rgb2gray(img_A_raw);
else
    img_A = img_A_raw;
end

img_B_dir = '.\data\refer.bmp';  %模板图
img_B_raw = imread(img_B_dir);
[r2,c2,d2] = size(img_B_raw);
if d2==3
    img_B = rgb2gray(img_B_raw);
else
    img_B = img_B_raw;
end

%2.计算SAD矩阵
msad = zeros(r1-r2,c1-c2);

for i = 1:r1-r2
    for j = 1:c1-c2
        temp = img_A(i:i+r2-1,j:j+c2-1);        
        msad(i,j) = msad(i,j) + sum(sum(abs(temp - img_B)));    
    end
end

%3.定位匹配位置
min_sad = min(min(msad));
[x,y] = find(msad == min_sad);
x = x(1); %定位到的第一个位置
y = y(1);

%4.保存结果图
getImg = img_A_raw(x:x+r2-1,y:y+c2-1,1:3);
imwrite(getImg,'.\output\SAD_match.bmp');

fprintf('\n Done. \n');
在这里插入代码片
2197714-20230102114126546-159723503.jpg

(2) MAD

clear all;
close all; clc;

%1.读取图片
img_A_dir = '.\data\lena.bmp';  %待寻母图
img_A_raw = imread(img_A_dir);
[r1,c1,d1] = size(img_A_raw);
if d1==3 %灰度化
    img_A = rgb2gray(img_A_raw);
else
    img_A = img_A_raw;
end

img_B_dir = '.\data\refer.bmp';  %模板图
img_B_raw = imread(img_B_dir);
[r2,c2,d2] = size(img_B_raw);
if d2==3
    img_B = rgb2gray(img_B_raw);
else
    img_B = img_B_raw;
end

%2.计算MAD矩阵
mmad = zeros(r1-r2,c1-c2);

for i = 1:r1-r2
    for j = 1:c1-c2
        temp = img_A(i:i+r2-1,j:j+c2-1);        
        mmad(i,j) = mmad(i,j) + sum(sum(abs(temp - img_B)))/(r2*c2);    
    end
end

%3.定位匹配位置
min_mad = min(min(mmad));
[x,y] = find(mmad == min_mad);
x = x(1); %定位到的第一个位置
y = y(1);

%4.保存结果图
getImg = img_A_raw(x:x+r2-1,y:y+c2-1,1:3);
imwrite(getImg,'.\output\MAD_match.bmp');

fprintf('\n Done. \n');
2197714-20230102114210429-1054958068.jpg

(3) SSD

clear all;
close all; clc;

%1.读取图片
img_A_dir = '.\data\lena.bmp';  %待寻母图
img_A_raw = imread(img_A_dir);
[r1,c1,d1] = size(img_A_raw);
if d1==3 %灰度化
    img_A = rgb2gray(img_A_raw);
else
    img_A = img_A_raw;
end

img_B_dir = '.\data\refer.bmp';  %模板图
img_B_raw = imread(img_B_dir);
[r2,c2,d2] = size(img_B_raw);
if d2==3
    img_B = rgb2gray(img_B_raw);
else
    img_B = img_B_raw;
end

%2.计算SSD矩阵
mssd = zeros(r1-r2,c1-c2);

for i = 1:r1-r2
    for j = 1:c1-c2
        temp = img_A(i:i+r2-1,j:j+c2-1);        
        mssd(i,j) = mssd(i,j) + sum(sum((temp - img_B).^2));    
    end
end

%3.定位匹配位置
min_ssd = min(min(mssd));
[x,y] = find(mssd == min_ssd);
x = x(1); %定位到的第一个位置
y = y(1);

%4.保存结果图
getImg = img_A_raw(x:x+r2-1,y:y+c2-1,1:3);
imwrite(getImg,'.\output\SSD_match.bmp');

fprintf('\n Done. \n');

2197714-20230102114246397-262898.jpg

(4) MSD

clear all;
close all; clc;

%1.读取图片
img_A_dir = '.\data\lena.bmp';  %待寻母图
img_A_raw = imread(img_A_dir);
[r1,c1,d1] = size(img_A_raw);
if d1==3 %灰度化
    img_A = rgb2gray(img_A_raw);
else
    img_A = img_A_raw;
end

img_B_dir = '.\data\refer.bmp';  %模板图
img_B_raw = imread(img_B_dir);
[r2,c2,d2] = size(img_B_raw);
if d2==3
    img_B = rgb2gray(img_B_raw);
else
    img_B = img_B_raw;
end

%2.计算MSD矩阵
mmsd = zeros(r1-r2,c1-c2);

for i = 1:r1-r2
    for j = 1:c1-c2
        temp = img_A(i:i+r2-1,j:j+c2-1);        
        mmsd(i,j) = mmsd(i,j) + sum(sum((temp - img_B).^2))/(r2*c2);    
    end
end

%3.定位匹配位置
min_msd = min(min(mmsd));
[x,y] = find(mmsd == min_msd);
x = x(1); %定位到的第一个位置
y = y(1);

%4.保存结果图
getImg = img_A_raw(x:x+r2-1,y:y+c2-1,1:3);
imwrite(getImg,'.\output\MSD_match.bmp');

fprintf('\n Done. \n');
2197714-20230102114315695-287475858.jpg

(5) NCC

clear all;
close all; clc;

%1.读取图片
img_A_dir = '.\data\lena.bmp';  %待寻母图
img_A_raw = imread(img_A_dir);
[r1,c1,d1] = size(img_A_raw);
if d1==3 %灰度化
    img_A = rgb2gray(img_A_raw);
else
    img_A = img_A_raw;
end

img_B_dir = '.\data\refer.bmp';  %模板图
img_B_raw = imread(img_B_dir);
[r2,c2,d2] = size(img_B_raw);
if d2==3
    img_B = rgb2gray(img_B_raw);
else
    img_B = img_B_raw;
end

%2.计算NCC矩阵
mNCC = zeros(r1-r2,c1-c2);

for i = 1:r1-r2
    for j = 1:c1-c2
        
        temp = img_A(i:i+r2-1,j:j+c2-1);   
        
        mean_temp = mean(temp(:)); %temp均值
        mean_B = mean(img_B(:));  %img_B均值      
        
        inp = sum(sum((temp - mean_temp).*(img_B - mean_B))); %两向量内积        
        mod1 = sqrt(sum(sum((temp - mean_temp).^2))); %模长1
        mod2 = sqrt(sum(sum((img_B - mean_B).^2))); %模长2        
        ncc = inp / (mod1*mod2);       
        
        mNCC(i,j) = mNCC(i,j) + ncc;                             
    end
end


%3.定位匹配位置
max_ncc = max(max(mNCC)); %最大ncc值
[x,y] = find(mNCC == max_ncc);
x = x(1); %定位到的第一个位置
y = y(1);

%4.保存结果图
getImg = img_A_raw(x:x+r2-1,y:y+c2-1,1:3);
imwrite(getImg,'.\output\NCC_match.bmp');

fprintf('\n Done. \n');
2197714-20230102114404930-583541757.jpg

End.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK