图像质量评估系统的Matlab GUIDE实现(四)——相关算法

系统的大体流程和介绍在(一)~(三)中大致介绍完了。

该系统采用的方法主要有两种,一种是全参考(RF),另一种是无参考(NF)

贴出的算法代码是用于系统调用的返回值版:

一、全参考(RF)

RF中主要包括了MSE\PSNR\JND\PDM\SSIM\SIExt\QILV\VIF几个算法,在这里就不逐个介绍了。

(1)MSE(Mean Square Error)均方误差

该算法直接比较得到两幅图像 IJ 每一个像素位置对应的绝对差值,最后总平均差值即为 MSE

(2)PSNR(Peak Signal to Noise Ratio)峰值信噪比

可由MSE值计算得到。

function [PSNR, MSE] = mseandpsnr(X, Y)
D = X-Y;
[m n d]=size(D);
MSE = sum(D(:).^2)/(m*n*d);
PSNR = 10*log10(258^2/MSE);

(3)JND(Just Noticeable Difference)最小可觉差/差别感知阈限

这个在网上找到了一个版本的代码,但是无法搬到系统中,搜了半天看到有说这个算法基于mallat,于是就用mallat替代了。

%离散快速正交小波变换——Mallat算法
function [psnr]=mallat(I)
    order = 3; %变换级数为3
    I=rgb2gray(I);
    I=imresize(I,[256,256]);
    wname = 'db2';
    ordata=double(I);
    data=ordata;
    [row,col]=size(data);
    imdata=zeros(size(data,1),size(data,2));
    %分解
    [lo_d,hi_d]=wfilters(wname,'d');
    for i=1:order
        data=decomp(lo_d,hi_d,i,data);
        MIN=min(min(data));
        MAX=max(max(data));
        for j=1:size(data,1)
            for k=1:size(data,2)
                imdata(j,k)=((data(j,k)-MIN)/(MAX-MIN))*255;
            end
        end
        %figure;
        %imshow(uint8(imdata));    
    end

    %计算最后一级分解后能量分布
    energy=zeros(1,4);
    energy=cal_energy(data,order);

    %阈值化处理
    [thr,sorh]=ddencmp('den','wv',ordata);  %获得阈值
    ddata=wthresh(data,sorh,thr);           %阈值化处理
    MIN=min(min(ddata));
    MAX=max(max(ddata));
        for j=1:size(ddata,1)
            for k=1:size(ddata,2)
                imdata(j,k)=((ddata(j,k)-MIN)/(MAX-MIN))*255;
            end
        end
    %figure;    
    %imshow(uint8(imdata));  

    %统计0的个数
    sum=0;
    for i=1:row
        for j=1:col
            if (ddata(i,j)==0)
                sum=sum+1;
            end
        end
    end
    Zero=sum/(row*col);

    %重建
    [lo_r,hi_r]=wfilters(wname,'r');
    redata=zeros(size(data,1),size(data,2));
    data=ddata;
    for i=order:-1:1
        data=reconstrn(lo_r,hi_r,i,data);
        MIN=min(min(data));
        MAX=max(max(data));
        for j=1:size(data,1)
            for k=1:size(data,2)
                redata(j,k)=((data(j,k)-MIN)/(MAX-MIN))*255;
            end
        end
        %figure;
        %imshow(uint8(redata));
    end

    %计算重构后的均值和方差
    [mean,var]=cal_mv(data);

    %峰值信噪比PSNR
    [row,col]=size(data);
    mse=0;
    for i=1:row
        for j=1:col
            mse=mse+(data(i,j)-ordata(i,j))^2;
        end
    end
    mse=mse/(row*col);
    psnr=10*log10(255^2/mse);
end






调用到的其他函数:

cal_mv.m

%求均值、方差
function [mean var]=cal_mv(data)
[row col]=size(data);
sum=0;
for i=1:row
    for j=1:col
        sum=sum+data(i,j);
    end
end
mean = sum/(row*col);
sum=0;
for i=1:row
    for j=1:col
        sum=sum+(data(i,j)-mean)^2;
    end
end
var = sum/(row*col);
        

        

decomp.m 

%分解变换
function data_d=decomp(lo_d,hi_d,order,data)
[row,col]=size(data);
%一维行变换
firowlen=size(lo_d,2);
l=fix(firowlen/2);
%excoldata=wextend('ac','sym',data(1:row/2^(order-1),1:col/2^(order-1)),l);
excoldata=wextend('ac','ppd',data(1:row/2^(order-1),1:col/2^(order-1)),firowlen-1,'r');%往右周期延拓
for i=1:row/2^(order-1);
    for j=1:row/2^order;
        data(i,j)=lo_d*excoldata(i,(2*j-1):(2*j+firowlen-2))';
        data(i,j+row/2^order)=hi_d*excoldata(i,(2*j-1):(2*j+firowlen-2))';
    end
end

%一维列变换
ficollen=size(hi_d,2);
l=fix(ficollen/2);
%exrowdata=wextend('ar','sym',data(1:row/2^(order-1),1:col/2^(order-1)),l);
exrowdata=wextend('ar','ppd',data(1:row/2^(order-1),1:col/2^(order-1)),ficollen-1,'d');%往下周期延拓
for i=1:col/2^(order-1);
    for j=1:col/2^order;
        data(j,i)=lo_d*exrowdata((2*j-1):(2*j+ficollen-2),i);
        data(j+col/2^order,i)=hi_d*exrowdata((2*j-1):(2*j+ficollen-2),i);
    end
end
data_d= data;

reconstrn.m 

%重建
function data_r=reconstrn(lo_r,hi_r,order,data)
[row,col]=size(data);
lo_ro=lo_r(1:2:end);%提取lo_r奇数位上的值
lo_re=lo_r(2:2:end);%提取lo_r偶数位上的值
hi_ro=hi_r(1:2:end);%提取hi_r奇数位上的值
hi_re=hi_r(2:2:end);%提取hi_r偶数位上的值
leno=size(lo_ro,2);
lene=size(lo_re,2);
%列重构
exloodata=wextend('ar','ppd',data(1:row/2^order,1:col/2^(order-1)),(leno-1),'u');%向上周期延拓
exloedata=wextend('ar','ppd',data(1:row/2^order,1:col/2^(order-1)),(lene-1),'u');%向上周期延拓
exhiodata=wextend('ar','ppd',data((row/2^order+1):row/2^(order-1),1:col/2^(order-1)),(leno-1),'u');%向上周期延拓
exhiedata=wextend('ar','ppd',data((row/2^order+1):row/2^(order-1),1:col/2^(order-1)),(lene-1),'u');%向上周期延拓
for i=1:row/2^(order-1);
    for j=1:col/2^(order-1);
        k=fix((i+1)/2);
        if(mod(i,2)==0)
            lodata=lo_ro*exloodata(k:k+leno-1,j);
            hidata=hi_ro*exhiodata(k:k+leno-1,j);
            data(i,j)=lodata+hidata;
        else
            lodata=lo_re*exloedata(k:k+lene-1,j);
            hidata=hi_re*exhiedata(k:k+lene-1,j);
            data(i,j)=lodata+hidata;
        end
    end
end

%行重构
exloodata=wextend('ac','ppd',data(1:row/2^(order-1),1:col/2^order),(leno-1),'l');%向左周期延拓
exloedata=wextend('ac','ppd',data(1:row/2^(order-1),1:col/2^order),(lene-1),'l');%向左周期延拓
exhiodata=wextend('ac','ppd',data(1:row/2^(order-1),(col/2^order+1):col/2^(order-1)),(leno-1),'l');%向左周期延拓
exhiedata=wextend('ac','ppd',data(1:row/2^(order-1),(col/2^order+1):col/2^(order-1)),(lene-1),'l');%向左周期延拓
for i=1:row/2^(order-1);
    for j=1:row/2^(order-1);
        k=fix((j+1)/2);
        if(mod(j,2)==0)
            lodata=lo_ro*exloedata(i,k:k+lene-1)';
            hidata=hi_ro*exhiedata(i,k:k+lene-1)';
            data(i,j)=lodata+hidata;
        else
            lodata=lo_re*exloodata(i,k:k+leno-1)';
            hidata=hi_re*exhiodata(i,k:k+leno-1)';
            data(i,j)=lodata+hidata;
        end
    end
end
data_r=data;

cal_energy.m 

%计算最后一级分级高低频能量分布
function energy=cal_energy(data,order)
result=zeros(1,4);
[row,col]=size(data);
%求低频C(order)的能量
sum=0;
for i=1:row/2^order;
    for j=1:row/2^order;
        sum=sum+data(i,j)^2;
    end
end
result(1,1)=sum;
%求d(order,1)的能量
sum=0;
for i=(row/2^order+1:row/2^(order-1))
    for j=1:row/2^order;
        sum=sum+data(i,j)^2;
    end
end
result(1,2)=sum;
%求d(order,2)的能量
sum=0;
for i=1:row/2^order;
    for j=(row/2^order+1:row/2^(order-1))
        sum=sum+data(i,j)^2;
    end
end
result(1,3)=sum;
%求d(order,3)的能量
sum=0;
for i=(row/2^order+1:row/2^(order-1))
    for j=(col/2^order+1:col/2^(order-1))
        sum=sum+data(i,j)^2;
    end
end
result(1,4)=sum;
energy=result;
        
        

(4)PDM(Perceptual Distortion Metric)感知失真度量

没找到合适的代码。。。

(5)SSIM(Structural SIMilarity index)结构相似指数

SSIM 算法以图像的亮度(灰度均值)、对比度(灰度方差)、结构(两个图像灰度协方差)作为质量评估的三个因素。加入块形窗口计算局部ssim,同时使用高斯函数避免块效应。

function [mssim, ssim_map] = ssim(img1, img2, K, window, L)

% ========================================================================
% SSIM Index with automatic downsampling, Version 1.0
% Copyright(c) 2009 Zhou Wang
% All Rights Reserved.
%
% ----------------------------------------------------------------------
% Permission to use, copy, or modify this software and its documentation
% for educational and research purposes only and without fee is hereby
% granted, provided that this copyright notice and the original authors'
% names appear on all copies and supporting documentation. This program
% shall not be used, rewritten, or adapted as the basis of a commercial
% software or hardware product without first obtaining permission of the
% authors. The authors make no representations about the suitability of
% this software for any purpose. It is provided "as is" without express
% or implied warranty.
%----------------------------------------------------------------------
%
% This is an implementation of the algorithm for calculating the
% Structural SIMilarity (SSIM) index between two images
%
% Please refer to the following paper and the website with suggested usage
%
% Z. Wang, A. C. Bovik, H. R. Sheikh, and E. P. Simoncelli, "Image
% quality assessment: From error visibility to structural similarity,"
% IEEE Transactios on Image Processing, vol. 13, no. 4, pp. 600-612,
% Apr. 2004.
%
% http://www.ece.uwaterloo.ca/~z70wang/research/ssim/
%
% Note: This program is different from ssim_index.m, where no automatic
% downsampling is performed. (downsampling was done in the above paper
% and was described as suggested usage in the above website.)
%
% Kindly report any suggestions or corrections to zhouwang@ieee.org
%
%----------------------------------------------------------------------
%
%Input : (1) img1: the first image being compared
%        (2) img2: the second image being compared
%        (3) K: constants in the SSIM index formula (see the above
%            reference). defualt value: K = [0.01 0.03]
%        (4) window: local window for statistics (see the above
%            reference). default widnow is Gaussian given by
%            window = fspecial('gaussian', 11, 1.5);
%        (5) L: dynamic range of the images. default: L = 255
%
%Output: (1) mssim: the mean SSIM index value between 2 images.
%            If one of the images being compared is regarded as 
%            perfect quality, then mssim can be considered as the
%            quality measure of the other image.
%            If img1 = img2, then mssim = 1.
%        (2) ssim_map: the SSIM index map of the test image. The map
%            has a smaller size than the input images. The actual size
%            depends on the window size and the downsampling factor.
%
%Basic Usage:
%   Given 2 test images img1 and img2, whose dynamic range is 0-255
%
%   [mssim, ssim_map] = ssim(img1, img2);
%
%Advanced Usage:
%   User defined parameters. For example
%
%   K = [0.05 0.05];
%   window = ones(8);
%   L = 100;
%   [mssim, ssim_map] = ssim(img1, img2, K, window, L);
%
%Visualize the results:
%
%   mssim                        %Gives the mssim value
%   imshow(max(0, ssim_map).^4)  %Shows the SSIM index map
%========================================================================


if (nargin < 2 | nargin > 5)
   ssim_index = -Inf;
   ssim_map = -Inf;
   return;
end

if (size(img1) ~= size(img2))
   ssim_index = -Inf;
   ssim_map = -Inf;
   return;
end

[M N] = size(img1);

if (nargin == 2)
   if ((M < 11) | (N < 11))
	   ssim_index = -Inf;
	   ssim_map = -Inf;
      return
   end
   window = fspecial('gaussian', 11, 1.5);	%
   K(1) = 0.01;					% default settings
   K(2) = 0.03;					%
   L = 255;                                     %
end

if (nargin == 3)
   if ((M < 11) | (N < 11))
	   ssim_index = -Inf;
	   ssim_map = -Inf;
      return
   end
   window = fspecial('gaussian', 11, 1.5);
   L = 255;
   if (length(K) == 2)
      if (K(1) < 0 | K(2) < 0)
		   ssim_index = -Inf;
   		ssim_map = -Inf;
	   	return;
      end
   else
	   ssim_index = -Inf;
   	ssim_map = -Inf;
	   return;
   end
end

if (nargin == 4)
   [H W] = size(window);
   if ((H*W) < 4 | (H > M) | (W > N))
	   ssim_index = -Inf;
	   ssim_map = -Inf;
      return
   end
   L = 255;
   if (length(K) == 2)
      if (K(1) < 0 | K(2) < 0)
		   ssim_index = -Inf;
   		ssim_map = -Inf;
	   	return;
      end
   else
	   ssim_index = -Inf;
   	ssim_map = -Inf;
	   return;
   end
end

if (nargin == 5)
   [H W] = size(window);
   if ((H*W) < 4 | (H > M) | (W > N))
	   ssim_index = -Inf;
	   ssim_map = -Inf;
      return
   end
   if (length(K) == 2)
      if (K(1) < 0 | K(2) < 0)
		   ssim_index = -Inf;
   		ssim_map = -Inf;
	   	return;
      end
   else
	   ssim_index = -Inf;
   	ssim_map = -Inf;
	   return;
   end
end


img1 = double(img1);
img2 = double(img2);

% automatic downsampling
f = max(1,round(min(M,N)/256));
%downsampling by f
%use a simple low-pass filter 
if(f>1)
    lpf = ones(f,f);
    lpf = lpf/sum(lpf(:));
    img1 = imfilter(img1,lpf,'symmetric','same');
    img2 = imfilter(img2,lpf,'symmetric','same');

    img1 = img1(1:f:end,1:f:end);
    img2 = img2(1:f:end,1:f:end);
end

C1 = (K(1)*L)^2;
C2 = (K(2)*L)^2;
window = window/sum(sum(window));

mu1 = filter2(window, img1, 'valid');
mu2   = filter2(window, img2, 'valid');
mu1_sq = mu1.*mu1;
mu2_sq = mu2.*mu2;
mu1_mu2 = mu1.*mu2;
sigma1_sq = filter2(window, img1.*img1, 'valid') - mu1_sq;
sigma2_sq = filter2(window, img2.*img2, 'valid') - mu2_sq;
sigma12 = filter2(window, img1.*img2, 'valid') - mu1_mu2;

if (C1 > 0 & C2 > 0)
   ssim_map = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))./((mu1_sq + mu2_sq + C1).*(sigma1_sq + sigma2_sq + C2));
else
   numerator1 = 2*mu1_mu2 + C1;
   numerator2 = 2*sigma12 + C2;
	denominator1 = mu1_sq + mu2_sq + C1;
   denominator2 = sigma1_sq + sigma2_sq + C2;
   ssim_map = ones(size(mu1));
   index = (denominator1.*denominator2 > 0);
   ssim_map(index) = (numerator1(index).*numerator2(index))./(denominator1(index).*denominator2(index));
   index = (denominator1 ~= 0) & (denominator2 == 0);
   ssim_map(index) = numerator1(index)./denominator1(index);
end

mssim = mean2(ssim_map);

return

(6)SIExt(Structural Information Extraction)结构信息提取

https://blog.csdn.net/qq_36614557/article/details/86763655

(7)QILV(Quality of Image assessment based on Local Value)基于局部对比度的图像质量评估

https://blog.csdn.net/qq_36614557/article/details/86764086

(8)PCQI(patch-based contrast quality index)基于小片的对比度质量评估

function [mpcqi, pcqi_map]= PCQI(img1, img2, window, L)
img1=double(rgb2gray(img1));
img2=double(rgb2gray(img2));
%========================================================================
%PCQI Index, Version 1.0, Sep. 2015
%
%This is an implementation of the algorithm for calculating the patch-based contrast 
%quality index (PCQI) between two images. Please refer to the following paper:
%
%S. Wang, K. Ma, H. Yeganeh, Z. Wang and W. Lin, A Patch-Structure Representation 
%Method for Quality Assessment of Contrast Changed Images, IEEE Signal Processing
%Letter, 2015. 
%
%Kindly report any suggestions or corrections to sqwang1986@gmail.com
%
%----------------------------------------------------------------------
%
%Input : (1) img1: the first image being compared
%        (2) img2: the second image being compared
%        (4) window: local window for statistics (see the above
%            reference). default widnow is Gaussian given by
%            window = fspecial('gaussian', 11, 1.5);
%        (5) L: dynamic range of the images. default: L = 256
%
%Output: (1) mpcqi   : the mean PCQI index value between 2 images.
%        (2) pcqi_map: the PCQI map of the test image. 
%Default Usage:
%   Given 2 test images img1 and img2, whose dynamic range is 0-255
%   [mpcqi pcqi_map] = PCQI(img1, img2);
%
%Advanced Usage:
%   User defined parameters. For example 
%   window = ones(8);
%   L = 100;
%   [mpcqi pcqi_map] = PCQI(img1, img2, window, L);
%========================================================================

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if (nargin < 2 || nargin > 4)
   mpcqi = -Inf;
   pcqi_map = -Inf;
   return;
end

if (size(img1) ~= size(img2))
   mpcqi = -Inf;
   pcqi_map = -Inf;
   return;
end

[M N] = size(img1);

if (nargin == 2)
   if ((M < 11) || (N < 11))
	   mpcqi    = -Inf;
	   pcqi_map = -Inf;
      return
   end
   window = fspecial('gaussian', 11, 1.5);	%
   L = 256;                                 %
end

if (nargin == 3)
   [H W] = size(window);
   if ((H*W) < 4 || (H > M) || (W > N))
	   mpcqi = -Inf;
	   pcqi_map = -Inf;
      return
   end
   L = 255;
end

if (nargin == 4)
   [H W] = size(window);
   if ((H*W) < 4 || (H > M) || (W > N))
	   mpcqi = -Inf;
	   pcqi_map = -Inf;
      return
   end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
window = window/sum(sum(window));
   
mu1    = filter2(window, img1, 'valid');
mu2    = filter2(window, img2, 'valid');
mu1_sq = mu1.*mu1;
mu2_sq = mu2.*mu2;
mu1_mu2 = mu1.*mu2;
sigma1_sq = filter2(window, img1.*img1, 'valid') - mu1_sq;
sigma2_sq = filter2(window, img2.*img2, 'valid') - mu2_sq;
sigma12   = filter2(window, img1.*img2, 'valid') - mu1_mu2;

      
sigma1_sq = max(0, sigma1_sq);
sigma2_sq = max(0, sigma2_sq);
 
C=3;

pcqi_map  =   (4/pi) *atan((sigma12 + C )./(sigma1_sq + C ));
pcqi_map  =   pcqi_map .*((sigma12 + C)    ./(sqrt(sigma1_sq).*sqrt(sigma2_sq) + C));
pcqi_map  =   pcqi_map .*exp(-abs(mu1-mu2)/L);

mpcqi     = mean2(pcqi_map);

return

     

(9)VIF(Visual Information Fidelity)视觉信息保真度

代码有点多,不列了,最后会统一放在一个包里的。

二、无参考(NF)

NF一共用了BRISQUE、CNR_NSS、UCIQE、UIQM四种。

 

三、自己瞎提出的算法

最后自己提出了一个基于多特征的全参考算法:

其中包括颜色特征、纹理特征、平滑度、一致性、清晰度、饱和度、熵、特征点、兴趣点等。

(1)颜色特征使用颜色矩表示(miu,signa,s分别为在R/G/B层的一阶矩、二阶矩、三阶矩):

颜色矩计算:

function colormom=getcolormom(I)
    I_r=I(:,:,1);
    I_g=I(:,:,2);
    I_b=I(:,:,3);
    colormom=zeros(1,9);
    colormom(1)=mean(mean(I_r));
    colormom(2)=sqrt(mean(mean((I_r-colormom(1)).^2)));
    colormom(3)=(mean(mean(((I_r-colormom(1))/colormom(2)).^3)))^(1/3);
    colormom(4)=mean(mean(I_g));
    colormom(5)=sqrt(mean(mean((I_g-colormom(4)).^2)));
    colormom(6)=(mean(mean(((I_g-colormom(4))/colormom(5)).^3)))^(1/3);
    colormom(7)=mean(mean(I_b));
    colormom(8)=sqrt(mean(mean((I_b-colormom(7)).^2)));
    colormom(9)=(mean(mean(((I_b-colormom(7))/colormom(8)).^3)))^(1/3);
end

两个图像颜色矩的比较:(归一化后使用mse)

function fd=cal_colormom(I1,I2)%0 最好 1最差
    w=zeros(1,9);
    colormom1=getcolormom(I1);
    colormom2=getcolormom(I2);
    fd=0;
    for i=1:9
        w(i)=max(colormom1(i),colormom2(i));
        fd=fd+abs(colormom1(i)-colormom2(i))/(9*w(i));
    end
    disp('Difference in Color Moment:');
    disp(fd);    
end

(2)纹理特征由Laws纹理能量和灰度共生矩阵表示:

灰度共生矩阵计算使用系统函数graycomatrix,并通过下式计算分数:

%% gray co-matrix
function fd=cal_gcm(I1,I2)
    gcm1=graycomatrix(rgb2gray(I1));
    gcm1=normalization2(gcm1);
    gcm2=graycomatrix(rgb2gray(I2));
    gcm2=normalization2(gcm2);
    fd=MSE(gcm1,gcm2);
end

 其中,normalization2为对二阶矩阵归一化的自定义函数:

function matrix=normalization2(matrix) %归一化到0~1
maxi=max(max(matrix));
mini=min(min(matrix));
for i=1:size(matrix,1)
    for j=1:size(matrix,2)
        matrix(i,j)=(matrix(i,j)-mini)/(maxi-mini);
    end
end
end

Laws:

Laws计算:

function Laws=getLaws(i,j)%第i和第j个
    L=[1,4,6,4,1];
    E=[-1,-2,0,2,1];
    S=[-1,0,2,0,1];
    R=[1,-4,6,-4,1];
    W=[-1,2,0,-2,1];
    matrix=[L;E;S;R;W];
    Laws=matrix(i,:)'*matrix(j,:);
end

两个图像Laws的比较:(每个算子卷积后图像归一化后的mse)

function fd=cal_Laws(I1,I2)
    fd=0;
    for i=1:5
        for j=1:5
        Laws=getLaws(i,j);
        I1_conv=conv2(rgb2gray(I1),Laws);
        I1_conv=normalization2(I1_conv);
        I2_conv=conv2(rgb2gray(I2),Laws);
        I2_conv=normalization2(I2_conv);
        fd=fd+MSE(I1_conv,I2_conv);
        end
    end
    fd=fd/25;
    disp('Difference in all-kinds Laws Conv:');
    disp(fd);    
end

(3)清晰度Definition、平滑度Smoothness、一致性Uniformity、饱和度Saturation、熵Entropy:

分别计算如下:

%% definition
function difinition=getDifinition(I)
    difinition=0;
    I=rgb2gray(I);
    [m,n]=size(I);
    for i=1:m-1
        for j=1:n-1
            difinition=difinition+double(abs(I(i,j)-I(i+1,j))*abs(I(i,j)-I(i,j+1)));
        end
    end
end
%% smoothness
function smoothness=getSmoothness(I)
    I=rgb2gray(I);
    m=mean(mean(I));
    var=sqrt(mean(mean((I-m).^2)));
    smoothness=1-1/(1+var/255);
end
%% uniformity
function uniformity=getUniformity(I)
    [p,~]=imhist(I);
    p=p/sum(p);%每个灰度值的概率
    uniformity=sum(p.^2);
end
%% saturation 
function saturation=getSaturation(I)
    saturation=0;
    I_gray=rgb2gray(I);
    [m,n,d]=size(I);
    for i=1:m
        for j=1:n
            for k=1:d
                saturation=saturation+double(abs(I(i,j,k)-I_gray(i,j)));
            end
        end
    end
end
%% entropy
function entropy=getEntropy(I)
    [p,~]=imhist(I);
    p=p/sum(p);%每个灰度值的概率
    entropy=0;
    for i=1:256
        if p(i)~=0
            entropy=entropy+p(i)*log(p(i))/log(2);
        end
    end
    entropy=-entropy;
end

 两个图像各个属性的分数综合:(两者之差除以两者最大)

%% Property
function fd=cal_property(I1,I2)
    difinition1=getDifinition(I1);
    smoothness1=getSmoothness(I1);
    uniformity1=getUniformity(I1);
    saturation1=getSaturation(I1);
    entropy1=getEntropy(I1);
    difinition2=getDifinition(I2);
    smoothness2=getSmoothness(I2);
    uniformity2=getUniformity(I2);
    saturation2=getSaturation(I2);
    entropy2=getEntropy(I2);
    property1={difinition1,smoothness1,uniformity1,saturation1,entropy1};
    property2={difinition2,smoothness2,uniformity2,saturation2,entropy2};
    disp('the Property of I1 in Difinition,Smoothness,Uniformity,Saturation and Entropy is as:');
    disp(property1);
    disp('the Property of I2 in Difinition,Smoothness,Uniformity,Saturation and Entropy is as:');
    disp(property2);
    fd=cell(5,1);
    for i=1:5
        fd{i}=abs(property2{i}-property1{i})/max(property2{i},property1{i});
    end
    disp('the Difference in Difinition,Smoothness,Uniformity,Saturation and Entropy is:');
    disp(fd);
end

(4)特征点、兴趣点

特征点获取:使用sift,比较慢,获得该图像的特征点坐标和特征向量。

兴趣点获取:使用最简单的moravec检测器:

function MO=getMoravec(I)
    I=rgb2gray(I);
    [m,n,~]=size(I);
    MO=zeros(m,n);
    for i=2:m-1
        for j=2:n-1
            for k=i-1:i+1
                for l=j-1:j+1
                    MO(i,j)=MO(i,j)+0.125*double(abs(I(k,l)-I(i,j)));
                end
            end
        end
    end
    MO=normalization2(MO);
end

 两个图像特征点比较(1-匹配到的点数乘2除以两个图像所有特征点数相加)

%% sift
function fd=cal_sift(I1,I2)
    addpath('sift2')
    scale=1;
    [M,N]=size(I1);
    I1_s=imresize(I1,[M/scale,N/scale]);
    I2_s=imresize(I2,[M/scale,N/scale]);
    [des1,~] = getFeatures(I1_s);
    [des2,~] = getFeatures(I2_s);
    matched = match(des1,des2);
    [mx,my]=size(matched);
    count=0;
    for i=1:my
        if matched(i)~=0 
            count=count+1;
        end
    end
    fd=1-2*count/(size(des1,1)+size(des2,1));
    disp('Features matched:');
    disp(fd);   
end

两个图像兴趣点比较:(手动写的匹配算法,计算和sift类似)

%% Moravec
function fd=cal_Moravec(I1,I2)
    MO1=getMoravec(I1);
    I1_gray=rgb2gray(I1);
    MO2=getMoravec(I2);
    I2_gray=rgb2gray(I2);
    thresold_MO=0.2;
    thresold_ditance=3;
    MO1_mask=MO1>thresold_MO;
    MO2_mask=MO2>thresold_MO;
    num1=sum(sum(MO1_mask==1));
    num2=sum(sum(MO2_mask==1));
    [M,N]=size(MO1_mask);
    % range for all pixels that  I1 and I2's mask is 1 ,
    % and distance of gray image is less than thresold
    num_matched=0;
    for i=1:M
        for j=1:N 
            if MO1_mask(i,j)==1 && MO2_mask(i,j)==1 && abs(I1_gray(i,j)-I2_gray(i,j))<=thresold_ditance
                num_matched=num_matched+1;
            end
        end
    end
    fd=1-2*num_matched/(num1+num2); 
    disp('Interest matched in global threshold 0.2:');
    disp(fd);
end

(5)哈希值:

将图像调整为8*8大小,将大于(等于)均值的点置1,小于置0,然后将只有10的矩阵展开成一维。

function [string]=gethash(I)
    I=imresize(I,[8,8]);
    [m,n,d]=size(I);
    I=I/4;
    m3=zeros(1,3);
    if d==3
        for i=1:d
            m3(i)=mean(mean(I(:,:,d)));
        end
    else
        m=mean(mean(I));
    end
    string=zeros(1,64*d);
    if d==1
        for i=1:8
            for j=1:8
                if I(i,j)>=m
                    string(8*(i-1)+j)=1;
                else
                    string(8*(i-1)+j)=0;
                end
            end
        end
    else
        for deep=1:3
            for i=1:8
                for j=1:8
                    if I(i,j,deep)>=m3(deep)
                         string(64*(deep-1)+8*(i-1)+j)=1;
                    else
                         string(64*(deep-1)+8*(i-1)+j)=0;
                    end
                end
            end
        end
    end
end

计算两个图像的哈希值差:(二维时候中间的权值大,两边最小,判断每个一维的哈希,如果不相等那么就累加对应的mask)

%% hash    
function fd=cal_hash(I1,I2)
    string1=gethash(I1);
    string2=gethash(I2);
    [m,n]=size(string1);
    length=m*n;
    mask=zeros(8,8);
    fd=0;
    for i=1:8
        for j=1:8
            if i<=2 || i>=7 || j<=2 || j>=7
                mask(i,j)=0.2;
            elseif i<=3 || i>=6 || j<=3 || j>=6
                    mask(i,j)=0.4;
                else 
                    mask(i,j)=1;
            end
        end
    end
    mask=reshape(mask,[1,64]);     
    index=0;
    for i=1:length
        index=index+1;
        if index>=65
            index=index-64;
        end
        if string1(i)~=string2(i)
            fd=fd+mask(index);
        end
    end
    disp('Hash Value:');
    disp(fd);
end

svd奇异值分解:

使用系统函数svd。分解得到奇异值,加权计算两个图像对应奇异值的差。

%% svd
function fd=cal_SVD(I1,I2)
    [M,N,~]=size(I1);
    [U1,S1,V1]=svd(double(rgb2gray(I1)));
    [U2,S2,V2]=svd(double(rgb2gray(I2)));%奇异值分解后求每个奇异值不同的加权值
    fd=0;
    for i=1:min(M,N)
        fd=fd+abs(S1(i,i)-S2(i,i))*(S1(i,i)+S2(i,i))/(sum(sum(S1))+sum(sum(S2)));
    end
    fd=fd/(max(sum(sum(S1)),sum(sum(S1))));
    disp('Singular Value Using SVD:');
    disp(fd);    
end

最后总得分:w为权值(没时间通过神经网络去计算了,就瞎编的权值)

function fd_out=FD(I1,I2)
    fd1=cal_hash(I1,I2);
    fd2=cal_SVD(I1,I2);
    fd3=cal_colormom(I1,I2);
    fd4=cal_gcm(I1,I2);
    fd5=cal_Laws(I1,I2);
    fd6=cal_property(I1,I2);
    fd7=cal_sift(I1,I2);
    fd8=cal_Moravec(I1,I2);
    fd={fd1,fd2,fd3,fd4,fd5,fd6{1},fd6{2},fd6{3},fd6{4},fd6{5},fd7,fd8};
    w=[0.0121,0.0263,0.1003,0.1127,0.036,0.057,0.052,0.063,0.089,0.022,0.2556,0.1440];
    fd_out=0;
    for i=1:12
        fd_out=w(i)*fd{i}+fd_out;
    end
    fd_out=1-fd_out;
end

以上所有代码:

链接:https://pan.baidu.com/s/19Tqvq1OQSF40uQSJ3OSR-A 
提取码:4abi 
复制这段内容后打开百度网盘手机App,操作更方便哦

  • 11
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值