close all
i1 = imread('10031.bmp');
image1 = i1(:,:,1);
i2 = imread('10036.bmp');
image2 = i2(:,:,1);
i3 = imread('10041.bmp');
image3 = i3(:,:,1);
%image1 = imread('D:\matlab\work\10037.bmp');
%image2 = imread('D:\matlab\work\10041.bmp');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%显示要匹配的两幅相邻图像
%figure(1);
%imshow(image1);
%figure(2);
%imshow(image2);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
height = size(image1,1);%基准图像高
width = size(image1,2);%基准图像宽
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%取匹配模板
Pdy = 10;%匹配块在y方向上的偏移量
newHeight = (double(uint8(height/10))*10-Pdy);
newWidth = (newHeight/10);
Pdx = double(uint8((width-newWidth)/2));%匹配块在x方向上的偏移量
RoiSorce = zeros(newHeight,newWidth);%新匹配块数组
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%取匹配块并赋初值
for j=(Pdy/2+1):newHeight+(Pdy/2)
for i=1:newWidth
RoiSorce((j-Pdy/2),i) = image1(j,(Pdx+i));
end
end
%figure(3),
%imshow(uint8(RoiSorce));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%SSDvector = zeros(1,(width-newWidth));
%粗匹配 未考虑旋转
minSSD = 10000;
sumSSD = 0;
RecordI = 0;%记录X位移量
RecordJ = 0;%记录Y位移量
%改成二重循环
%K = 1;
q=0;%控制是否进行粗匹配算法,因为算法运行时间长,图像不改变不需要重新计算
while q==1
for z=1:(height-newHeight)
for k=1:(width-newWidth)
sumSSD = 0;
for j=1:newHeight
for i=1:newWidth
temp1 = double(image2(z-1+j,k-1+i));
temp2 = double(RoiSorce(j,i));
temp = temp1-temp2;
m = temp*temp;
sumSSD = sumSSD+m;
end
end
sumSSD = sumSSD/(height*width);
if sumSSD<minSSD
minSSD = sumSSD;
RecordI = k;
RecordJ = z;
end
%SSDvector(K) = sumSSD;
%K=K+1;
end
end
q=0;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%显示粗匹配的区域 未考虑旋转
%for j=1:newHeight
%for i=1:newWidth
%RoiTar(j,i) = image2(RecordJ+j,RecordI+i);
%end
%end
%figure(4),
%imshow(uint8(RoiTar));
%figure(5)
%plot(SSDvector);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%考虑旋转分量
%test US new 31&36
RecordI = 159;
RecordJ = 4;
minSSD = 59.0408;
%end of test
Ox = double(uint8(newWidth/2));%匹配块中心点x坐标
Oy = newHeight/2;%匹配块中心点y坐标
RecordT = 0;%记录角度偏移量
%考虑旋转角度不大于正负2.50度
for t=-2.50:0.1:2.50%由右向左旋转
tg = tan(t/180*pi);
sumSSD = 0;
for j=1:newHeight
xR = (Oy-j)*tg;
if xR<0
xR = double(uint16(-xR));
xR = -xR-1;
else
xR = double(uint16(xR));
end
for i=1:newWidth
temp1 = double(image2(RecordJ+j,RecordI+i+xR));
temp2 = double(RoiSorce(j,i));
temp = temp1-temp2;
m = temp*temp;
sumSSD = sumSSD+m;
end
end
sumSSD = sumSSD/(height*width);
if sumSSD<minSSD
minSSD = sumSSD;
RecordT = t;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%精细匹配算法
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
w=0;%判断是否调用精细匹配
dx = Pdx-RecordI;
dy = (Pdy/2+1)-RecordJ;
%刚体变换仿射矩阵参数
m = [cos(RecordT/180*pi);sin(RecordT/180*pi);-dx;-sin(RecordT/180*pi);cos(RecordT/180*pi);-dy];
while w==1
mm = zeros(6,1);
mmm = zeros(6,1);
A = zeros(6,6);
AA = zeros(6,6);
deta = eye(size(A));
em = zeros(6,1);
bb = zeros(6,1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
jj = height-2;%防止越界
ii = width-2;%防止越界
l = 0.001;%l不变化时优选值
e1 = 0;
e2 = 0;
q=0;%迭代次数
p=0;%迭代次数
while q==0
e1 = 0;
p=0;
for j=(Pdy/2+1):newHeight+(Pdy/2)
for i=(Pdx+1):(Pdx+newWidth)
%计算匹配点x1,y1 双线性插值
x1 = m(1)*i+m(2)*j+m(3);%有可能越界,怎么处理?
y1 = m(4)*i+m(5)*j+m(6);%有可能越界,怎么处理?
if x1<1
x1 = 1;
end
if x1>=width
x1 = ii;
end
if y1<1
y1 = 1;
end
if y1>=height
y1 = jj;
end
x11 = uint8(x1);%x1取整
y11 = uint8(y1);%y1取整
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%做双线性插值
x111 = double(x11);
y111 = double(y11);
b = x1-x111;
a = y1-y111;
t1 = a*double(image2(uint16(y111),uint16(x111+1)))+(1-a)*double(image2(uint16(y111+1),uint16(x111+1)));
t2 = a*double(image2(uint16(y111+1),uint16(x111)))+(1-a)*double(image2(uint16(y111),uint16(x111)));
Iold = double(image1(uint16(j),uint16(i)));
Inew = b*t1+(1-b)*t2;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%求灰度插值,梯度值Gx,Gy
e = Inew-Iold;
e1 = e*e+e1;%最小平方差函数E
x22 = uint16(x1+1);%x1取整
y22 = uint16(y1+1);%y1取整
x222 = double(x22);
y222 = double(y11);
%%%%%%%%%%%%%%%%%%
%做双线性插值
t1 = a*double(image2(uint16(y222),uint16(x222+1)))+(1-a)*double(image2(uint16(y222+1),uint16(x222+1)));
t2 = a*double(image2(uint16(y222+1),uint16(x222)))+(1-a)*double(image2(uint16(y222),uint16(x222)));
Inew = b*t1+(1-b)*t2;
Gx = e-Inew;
x222 = double(x11);
y222 = double(y22);
t1 = a*double(image2(uint16(y222),uint16(x222+1)))+(1-a)*double(image2(uint16(y222+1),uint16(x222+1)));
t2 = a*double(image2(uint16(y222+1),uint16(x222)))+(1-a)*double(image2(uint16(y222),uint16(x222)));
Inew = b*t1+(1-b)*t2;
Gy = e-Inew;
%%%%%%%%%%%%%%%%%%
%求e对仿射系数的偏导数
em(1) = Gx*x1;
em(2) = Gx*y1;
em(3) = Gx;
em(4) = Gy*x1;
em(5) = Gy*y1;
em(6) = Gy;
%求Hessian矩阵
for jj=1:6
for ii=1:6
A(jj,ii) = em(jj)*em(ii)+A(jj,ii);
end
end
%求加权梯度向量
for ii=1:6
bb(ii) = -e*em(ii)-bb(ii);
end
end
end
while p==0
%求改进后的Hessian矩阵
AA = (1+deta*l)*A;
%求m增量
mm = deta/AA*bb;
if abs(e1-e2)<0.00001
p=1;
q=1;
else
e2 = 0;
mmm = m+mm;
for j=(Pdy/2+1):newHeight+(Pdy/2)
for i=(Pdx+1):(Pdx+newWidth)
%计算匹配点x1,y1 双线性插值
x1 = mmm(1)*i+mmm(2)*j+mmm(3);%有可能越界,怎么处理?
y1 = mmm(4)*i+mmm(5)*j+mmm(6);%有可能越界,怎么处理?
if x1<1
x1 = 1;
end
if x1>=width
x1 = ii;
end
if y1<1
y1 = 1;
end
if y1>=height
y1 = jj;
end
x11 = uint16(x1);%x1取整
y11 = uint16(y1);%y1取整
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%做双线性插值
x111 = double(x11);
y111 = double(y11);
b = x1-x111;
a = y1-y111;
t1 = a*double(image2(uint16(y111),uint16(x111+1)))+(1-a)*double(image2(uint16(y111+1),uint16(x111+1)));
t2 = a*double(image2(uint16(y111+1),uint16(x111)))+(1-a)*double(image2(uint16(y111),uint16(x111)));
Iold = double(image1(uint16(j),uint16(i)));
Inew = b*t1+(1-b)*t2;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
e = Inew-Iold;
e2 = e*e+e2;%最小平方差函数E
end
end
if (e1-e2)>0
m=mmm;
l = l/10;
p=1;
q=0;
else
l = l*10;
p=0;
end
end
end
end
w=0;
%AM = m
%BM = [cos(RecordT/180*pi);sin(RecordT/180*pi);-dx;-sin(RecordT/180*pi);cos(RecordT/180*pi);-dy]
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%显示匹配的区域 考虑刚体变换模型 全图像显示
M1 = [cos(RecordT/180*pi),sin(RecordT/180*pi),-dx;-sin(RecordT/180*pi),cos(RecordT/180*pi),-dy;0,0,1];
T = eye(size(M1));
T = T/M1;%T是M1的逆矩阵
%根据精细匹配的结果进行拼接
OffsetY = 100;
OffsetX = 50;
%将第一幅图像放在(OffsetY,OffsetX)位置处
newRoiTar = zeros(2*height,2*width);
for j=1:height
for i=1:width
newRoiTar(j+OffsetY,i+OffsetX) = image1(j,i);
end
end
d = 0.0;
for j=1:height
for i=1:width
C = [i;j;1];
C = T*C;
xNew = C(1);%将图像2上的x坐标映射到图像1上
yNew = C(2);%将图像2上的y坐标映射到图像1上
k = yNew+OffsetY;
wid = width-T(1,3);
if xNew>=1 && yNew>=1 && yNew<=height && xNew<=width
d = i/wid;
a = double(image1(uint16(yNew),uint16(xNew)));
b = double(image2(j,i));
if a==0
d = 1.00;
elseif b==0
d = 0.00;
end
temp = (1-d)*a+d*b;
newRoiTar(uint16(k),uint16(xNew+OffsetX)) = temp;
else
d = 1.00;
newRoiTar(uint16(k),uint16(xNew+OffsetX)) = d*double(image2(j,i));
end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%拼接第三幅图像
RecordI = 162;
RecordJ = 4;
RecordT = 0;
dx = Pdx-RecordI;
dy = (Pdy/2+1)-RecordJ;
M2 = [cos(RecordT/180*pi),sin(RecordT/180*pi),-dx;-sin(RecordT/180*pi),cos(RecordT/180*pi),-dy;0,0,1];
T = eye(size(M2*M1));
T = T/(M2*M1);%T是M1的逆矩阵
d = 0.0;
for j=1:height
for i=1:width
C = [i;j;1];
C = T*C;
xNew = C(1);%将图像3上的x坐标映射到图像1上
yNew = C(2);%将图像3上的y坐标映射到图像1上
k = yNew+OffsetY;
wid = width-T(1,3);
if xNew>=1 && yNew>=1 && yNew<=height && xNew<=width
d = i/wid;
a = double(image1(uint16(yNew),uint16(xNew)));
b = double(image3(j,i));
if a==0
d = 1.00;
temp = (1-d)*a+d*b;
elseif b==0
d = 0.00;
temp = (1-d)*a+d*b;
else
temp = (1-d)*a+d*b;
end
newRoiTar(uint16(k),uint16(xNew+OffsetX)) = temp;
else
%可能存在非空点,应增加判断
d = 1.00;
%if newRoiTar(uint16(k),uint16(xNew+OffsetX))==0
newRoiTar(uint16(k),uint16(xNew+OffsetX)) = d*double(image3(j,i));
%else
%newRoiTar(uint16(k),uint16(xNew+OffsetX)) = (newRoiTar(uint16(k),uint16(xNew+OffsetX))+d*double(image3(j,i)))/2;
%end
end
end
end
figure(7),
imshow(uint8(newRoiTar));
figure(8),
imshow(uint8(newRoiTar));
colorbar
%增加颜色显示
colormap(copper)
%rgbplot(hot)%显示颜色变化曲线
%colormapeditor%编辑颜色
%G=hot;
%hsv 色彩饱和值(以红色开始和结束)
%hot 从黑到红到黄到白
%cool 青蓝和洋红的色度
%pink 粉红的彩色度
%gray 线性灰度
%bone 带一点蓝色的灰度
%jet hsv的一种变形(以蓝色开始和结束)
%copper 线性铜色度 好的
%prim 三棱镜。交替为红色、橘黄色、黄色、绿色和天蓝色 ?????
%flag 交替为红色、白色、蓝色和黑色
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%