K-L变换

附带的读取图像的函数

Brovey变换

function [Out]=Brovey(msi,pan)
[row1,col1,bands1]=size(msi);
[row2,col2]=size(pan);
rowscale=row2/row1;
colscale=col2/col1;
Out=zeros(row2,col2,3);
msi=double(msi);
pan=double(pan);
%对多波段影像进行重采样
ReampleMSI=zeros(row2,col2,bands1);
for i=1:bands1
    ReampleMSI(:,:,i)=BilineInter(msi(:,:,i),row2,col2);
end
%Brovey变换
for k=1:bands1-1
    for i=1:row2
        for j=1:col2
            Out(i,j,k)= pan(i,j)*ReampleMSI(i,j,k)/(ReampleMSI(i,j,1)+ReampleMSI(i,j,2)+ReampleMSI(i,j,3));
        end
    end
end

end


%%
function M=BilineInter(datar,p,q)
%datar为低分辨率,[p,q]为要变换的大小
[m,n,k]=size(datar);
A=zeros(m+2,n+2,k);
%M为上采用的结果矩阵
M=zeros(p,q,k);
for t=1:k
A(2:m+1,2:n+1,t)=datar(:,:,t);%得到各个波段的值
end
%下面就是根据双线性内插法进行插值
for i=1:p
    for j=1:q
        I=ceil(i*m/p);
        J=ceil(j*n/q);
        u=I-i*m/p;
        v=J-j*n/q;
        a=[A(I,J,:),A(I,J+1,:);A(I+1,J,:),A(I+1,J+1,:)];
        w=[(1-u)*(1-v),(1-u)*v;(1-v)*u,u*v];
        M(i,j,:)=sum(sum(a.*w));
    end
end 
end

K-L变换

function Out=KLFusion(msidata,pan)
[~,~,bands]=size(msidata);
[row,col]=size(pan);
msidata1=zeros(row,col,bands);%根据msidata的尺寸声明msidata1的尺寸
for i=1:bands
    msidata1(:,:,i)=BilineInter(msidata(:,:,i),row,col);
end
%进行PCA变换之前先进性双线性内插求得上采用之后的图像
Out=PCA(msidata1,pan);%对多光谱数据做主成分变换
end

function Out=PCA(msidata,pan)
[row,col,bands]=size(msidata);
%先声明一个方差协方差矩阵
Q=zeros(bands,bands);%先声明一个方差协方差矩阵
bandmeans=zeros(1,bands);
msidata=double(msidata);
for i=1:bands
    bandmeans(1,i)=MyMean(msidata(:,:,i));%顺便求得每个波段的平均值以便于后面进行协方差的解算
end

for m=1:bands
    for n=1:bands 
        %外面两层循环就代表协方差矩阵的尺寸
        if m==n
            %m=n就直接计算方差就可以了
            Q(m,n)=Variance(msidata(:,:,m),bandmeans(1,m));
        else
            Q(m,n)=Cov(msidata(:,:,m),msidata(:,:,n),bandmeans(1,m),bandmeans(1,n));
        end
    end
end
%求得方差协方差矩阵之后进行特征矩阵和特诊向量的求解
%求解特征值和特征矩阵
[V,D]=eig(Q);%其中V是特征列向量拼接成为一个矩阵,D中diag为特征值
%将特征值进行排序,然后再进行正变换,将位于第一位置的多光谱但波段影像用全色影像代替
eigenvalues=diag(D);
%将原始的特征向量进行对应的调整,这一步直接在sort函数中与特征值排序同步进行
%将特征值排序之后特征向量必须跟着一起排序
[Transform,MSI]=Sort(eigenvalues,V,msidata);%得到对应的变换矩阵用于逆变换
%先做主成分变换
% MSI=MSI*Trasnform;%row*col*4*4*4===大致认为是row*col*4
% --------------TODO,实际上这种想法是错误的,我的MSI中的每一个波段进行行列变换才可以进行相乘
ReshapeMSI=zeros(row*col,bands);%首先给ReshapeMSI预分配内存为了得到更好的运行速度

for i=1:bands
    ReshapeMSI(:,i) = reshape(MSI(:,:,i),[row*col,1]);%将每个波段转变为列向量
end
%做主成分变换
PCAPositiveTransform=ReshapeMSI*Transform;%(row2*col2,4)*(4,4)
%对全色影像按照 ReshapeMSI(:,1)进行直方图匹配之后再进行替换
firstComponent=reshape(ReshapeMSI(:,1),[row,col]);%将波段变为正常的二维矩阵
%求得映射之后的图像
panMatch=HistogramMatch(pan,firstComponent);%其中pan为待匹配图像,firstComponent为匹配的参照图像
%将该图像代替第一主成分进行假彩色显示
panMatch=reshape(panMatch,[row*col,1]);%先变换为列向量
%再进行插入
PCAPositiveTransform(:,1)=panMatch;
%PCA反变换------这里面不做替换就可以不进行变换
PCANegativeTransform=PCAPositiveTransform*inv(Transform);
%其实PCA最后的图像融合效果就是一个假彩色融合的效果
Out=zeros(row,col,3);
Out(:,:,1)=reshape(PCANegativeTransform(:,1),[row,col]);%第一主成分(列向量转化为图像矩阵)
Out(:,:,2)=reshape(PCANegativeTransform(:,2),[row,col]);%第二主成分(列向量转化为图像矩阵)
Out(:,:,3)=reshape(PCANegativeTransform(:,3),[row,col]);%第三主成分(列向量转化为图像矩阵)
for i=1:3
    Out(:,:,i)=LineExtension(Out(:,:,i));
end
end

%%
function cov=Cov(Band1,Band2,mean1,mean2)
%计算两个波段的协方差提取成为一个函数,传入均值的目的是防止均值的重复计算降低效率
[row,col]=size(Band1);
sum=0;
for i=1:row
    for j=1:col
        sum=sum+(Band1(i,j)-mean1)*(Band2(i,j)-mean2);
    end
end
cov=sum/row/col;
end

%%
function variance=Variance(Band,mean)
%其实虽然方差只是协方差的一个特殊的例子,但是为了提高效率还是单独提取出来比较好
[row,col]=size(Band);
sum=0;
for i=1:row
    for j=1:col
        sum=sum+(Band(i,j)-mean)^2;%MALTAB还是非常方便的,所有函数都给我们重载好了
    end
end
variance=sum/row/col;
end

%%
function result=MyMean(A)
[row,col] = size(A);
result=0;
for i=1:row
    for j=1:col
        result=result+A(i,j); %这里需要注意的问题最后的数值是否会超过限制??导致结果不准确----但好像又不会
    end
end
result=result/row/col;
end

%%
function [V,MSI]=Sort(eigenvalues,V,MSI)
eigensize=size(eigenvalues);
% temp1=eigenvalues;
%进行排序的时候需要知道每个位置是由什么位置变换过来
for i=1:eigensize(1)-1
    for j=2:eigensize(1)
        k=j-1;
        temp=eigenvalues(j,1);%保存当前的值
        temp1=V(:,j);
        temp2=MSI(:,:,j);
         if temp>eigenvalues(k,1)
            while k>=1&&temp>eigenvalues(k,1)
                eigenvalues(k+1,1)=eigenvalues(k,1);%往后移动
                V(:,k+1)=V(:,k);%将列向量交换
                MSI(:,:,k+1)=MSI(:,:,k);
                k=k-1;
            end
        end
        %找到插入的位置为j+1
         eigenvalues(k+1,1)=temp;
         V(:,k+1)=temp1;
         MSI(:,:,k+1)=temp2;
    end
end
% sortdata=eigenvalues;
% %寻找第一主成分是哪一个波段
% for i=1:eigensize(1)
%     if temp1(i,1)==sortdata(eigensize(1),1)
%         index=i;
%         break;
%     end
% end
end


%%
%双线性内插
function M=BilineInter(datar,p,q)
%datar为低分辨率,[p,q]为要变换的大小
[m,n,k]=size(datar);
A=zeros(m+2,n+2,k);
%M为上采用的结果矩阵
M=zeros(p,q,k);
for t=1:k
A(2:m+1,2:n+1,t)=datar(:,:,t);%得到各个波段的值
end
%下面就是根据双线性内插法进行插值
for i=1:p
    for j=1:q
        I=ceil(i*m/p);
        J=ceil(j*n/q);
        u=I-i*m/p;
        v=J-j*n/q;
        a=[A(I,J,:),A(I,J+1,:);A(I+1,J,:),A(I+1,J+1,:)];
        w=[(1-u)*(1-v),(1-u)*v;(1-v)*u,u*v];
        M(i,j,:)=sum(sum(a.*w));
    end
end 
end

%%
function src1=HistogramMatch(src1,src2) %两个相同尺寸的矩阵进行匹配
%灰度图像的直方图匹配
%第一步先将uint16的转化为uint8的图像便于在计算机处理0-255
%对src1和src2先在0-255上拉伸再进行直方图匹配
src1=LineExtension(src1);
src2=LineExtension(src2);
grayscale=256;
dist1=zeros(grayscale,1);
dist2=zeros(grayscale,1);
dist1(:,1)=AP(src1(:,:),grayscale);
dist2(:,1)=AP(src2(:,:),grayscale);%计算累计概率
%第二步进行灰度值重分配
%这里我假设src2是参考影像,目的是把src1指定到src2上
src1(:,:)=RuleDN(dist1(:,1),dist2(:,1),src1(:,:));
%第三步进行匹配图像的显示

end

%计算每个灰度级的累计概率
function cumulative=AP(src,grayscale)
[row,col]= size(src);
%就C++而言尽量避免uint与其他的数进行操作,所以我选择直接转化为double再进行操作
A=double(src);
dist=zeros(grayscale,1);%由于我暂时不知道如何读取图片的位图,所以暂时默认是256
for i=1:row
    for j=1:col
        index=round(A(i,j))+1;
        try 
            dist(index,1)=dist(index,1)+1;%这个是浙大数据结构中讲过的一个知识点
        catch 
            warning('Problem using function!');
        end
    end
end
%累计完频率之后进行概率计算,但是实际上考虑到效率和后续直方图的匹配根本用不到概率,所以我选择直接返回dist
%但是实际上上一句话也很矛盾,转变为double之后就是double,但是还是可以减少不必要的算数操作
%下一步计算每个灰度级出现的概率
dist=dist/(row*col);
%计算累计的概率,在MATLAB中很奇怪的一件事就是任何变量都不需要提前进行声明就可以使用
cumulative(1,1)=dist(1,1);
for i=2:grayscale
    cumulative(i,1)=cumulative(i-1,1)+dist(i,1);
end
end

function src1=RuleDN(cum1,cum2,src1) %cum为单波段的累计概率,src1为对应波段的概率
[row,col]=size(cum1);
src1_size=size(src1);%取得该单波段的尺寸
Map=zeros(row,col);%先进行一个for循环求得对应的映射矩阵
for i=1:row
    %对于1-256的DN值建立一一的映射关系
    mapDN=-1;
    minDis=100000;
    for j=1:row
        if abs(cum1(i,1)-cum2(j,1))<minDis
            minDis=abs(cum1(i,1)-cum2(j,1));
            mapDN=j-1;%真实的DN值为0-255,但是下标是1-256
        end
    end
    Map(i,1)=mapDN;%表示DN值为i的映射为mapDN值
end
%上面建立好对应的映射关系之后就进行DN值的总体映射
for i=1:src1_size(1)
    for j=1:src1_size(2)
        index=src1(i,j);
        %index为真实的DN值,在映射表中寻找对应的映射值进行映射
        src1(i,j)=Map(index+1,1);
    end
end
%上面就做好了直方图的匹配了
end





HSI融合变换

function HSIFusion(msi,pan)
%第一步,先进行msi的去极化线性拉伸
%只对前面三个波段进行线性拉伸
[row,col]=size(pan);
RGB=zeros(row,col,3);
for i=1:3
    temp=BilineInter(msi(:,:,i),row,col);
    RGB(:,:,i)=LineExtension(temp);
end
%拉伸到0-255之后就可以进行HSI变换
HSI=RGB2HSI(RGB);
%将I成分使用全色影像进行替换
%但是替换之前需要转换到0-255
pan=LineExtension(pan);
HSI(:,:,3)=pan;
%替换之后进行HSI反变换
Out=HSI2RGB(HSI);
imshow(uint8(Out));
end

%下面是用于第三步和第六步的HSI<=>RGB的变换函数
%%
function Dist=RGB2HSI(M)
[row,col,bands]=size(M);
Dist=zeros(size(M));
M=double(M);
for i=1:row
    for j=1:col
        R=M(i,j,1);
        G=M(i,j,2);
        B=M(i,j,3);
        Numerator=0.5*(2*R-G-B);
        Denominator=sqrt((R-G)^2+(R-B)*(G-B));
        if R== G && G ==B
            theta = 0;
        else
            theta=acos(Numerator/Denominator);
        end
        %由于是HSI变换,所以H是1,S是2,I是3
        Dist(i,j,3)=(R+G+B)/3;
        Dist(i,j,2)=1-3/(R+G+B)*min([R G B]);
        if G<B
            Dist(i,j,1)=360-theta;
        else
            Dist(i,j,1)=theta;
        end
    end
end
end

%%
function Image=HSI2RGB(HSI)
[lines,samples] = size(HSI(:,:,1));
Image = zeros(lines,samples,3);
for i = 1:lines
    for j = 1:samples                        
        if HSI(i,j,1)>=0 && HSI(i,j,1)<120
            Image(i,j,3) = HSI(i,j,3)*(1-HSI(i,j,2));
            Image(i,j,1) = HSI(i,j,3)*(1+HSI(i,j,2)*cos(pi*HSI(i,j,1)/180)/cos(pi*(60-HSI(i,j,1))/180));
            Image(i,j,2) = 3*HSI(i,j,3)- Image(i,j,1)-Image(i,j,3);            
        end
    
        if HSI(i,j,1)>=120 && HSI(i,j,1)<240
            Image(i,j,1) = HSI(i,j,3)*(1-HSI(i,j,2));
            Image(i,j,2) = HSI(i,j,3)*(1+HSI(i,j,2)*cos(pi*(HSI(i,j,1)-120)/180)/cos(pi*(180-HSI(i,j,1))/180));
            Image(i,j,3) = 3*HSI(i,j,3)- Image(i,j,1)- Image(i,j,2);          
        end
        
        if HSI(i,j,1)>=240 && HSI(i,j,1)<360
            Image(i,j,2) = HSI(i,j,3)*(1-HSI(i,j,2));
            Image(i,j,3) = HSI(i,j,3)*(1+HSI(i,j,2)*cos(pi*(HSI(i,j,1)-240)/180)/cos(pi*(360-HSI(i,j,1))/180));          
            Image(i,j,1) = 3*HSI(i,j,3)- Image(i,j,2)- Image(i,j,3);
        end
    end
end
end

%%
%下面这个函数用于使用双线性内插法进行上采样
function M=BilineInter(datar,p,q)
%datar为低分辨率,[p,q]为要变换的大小
[m,n,k]=size(datar);
A=zeros(m+2,n+2,k);
%M为上采用的结果矩阵
M=zeros(p,q,k);
for t=1:k
A(2:m+1,2:n+1,t)=datar(:,:,t);%得到各个波段的值
end
%下面就是根据双线性内插法进行插值
for i=1:p
    for j=1:q
        I=ceil(i*m/p);
        J=ceil(j*n/q);
        u=I-i*m/p;
        v=J-j*n/q;
        a=[A(I,J,:),A(I,J+1,:);A(I+1,J,:),A(I+1,J+1,:)];
        w=[(1-u)*(1-v),(1-u)*v;(1-v)*u,u*v];
        M(i,j,:)=sum(sum(a.*w));
    end
end 
end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值