import numpy as np
import tensorflow as tf
import cv2
import math
def lowpassfilter(sze,cutoff,n):
if cutoff<0 or cutoff>0.5:
print('cutoff frequency must be between 0 and 0.5')
return
if type(n)!=int or n<1:
print('n must be an integer >= 1')
return
if type(sze)==int:
rows=sze
cols=sze
else:
rows=sze[0]
cols=sze[1]
if cols%2>0:
xrange=np.arange(-(cols-1)/2,(cols-1)/2+1)/(cols-1)
else:
xrange=np.arange(-cols/2,cols/2)/cols
if rows%2>0:
yrange=np.arange(-(rows-1)/2,(rows-1)/2+1)/(rows-1)
else:
yrange=np.arange(-rows/2,rows/2)/rows
x,y=np.meshgrid(xrange,yrange)
radius=(x**2+y**2)**0.5
f=tf.signal.ifftshift(1.0/(1.0+(radius/cutoff)**(2*n)))
return f.numpy()
def phasecong2(im):
nscale= 4
norient= 4
minWaveLength= 6
mult= 2
sigmaOnf= 0.55
dThetaOnSigma= 1.2
k= 2.0
epsilon= .0001
thetaSigma = math.pi/norient/dThetaOnSigma
rows,cols=np.shape(im)
imagefft=tf.signal.fft2d(im).numpy()
EO=[[None for i in range(nscale)] for j in range(norient)]
estMeanE2n=np.zeros((norient,))
ifftFilterArray=[None for x in range(nscale)]
if cols%2>0:
xrange=np.arange(-(cols-1)/2,(cols-1)/2+1)/(cols-1)
else:
xrange=np.arange(-cols/2,cols/2)/cols
if rows%2>0:
yrange=np.arange(-(rows-1)/2,(rows-1)/2+1)/(rows-1)
else:
yrange=np.arange(-rows/2,rows/2)/rows
x,y=np.meshgrid(xrange,yrange)
radius=(x**2+y**2)**0.5
theta=tf.math.atan2(-y,x).numpy()
radius=tf.signal.ifftshift(radius).numpy()
theta=tf.signal.ifftshift(theta).numpy()
radius[0,0]=1
sintheta = tf.math.sin(theta).numpy()
costheta = tf.math.cos(theta).numpy()
lp=lowpassfilter([rows,cols],0.45,15)
logGabor=[None for x in range(nscale)]
for s in range(1,nscale+1):
wavelength = minWaveLength*mult**(s-1)
fo = 1.0/wavelength
logGabor[s-1]=tf.math.exp((-(tf.math.log(radius/fo))**2) / tf.cast(2 * tf.math.log(sigmaOnf)**2,dtype=tf.float64)).numpy()
logGabor[s-1]=logGabor[s-1]*lp
logGabor[s-1][0,0]=0
spread=[None for x in range(nscale)]
for o in range(1,norient+1):
angl = (o-1)*math.pi/norient
ds = sintheta * math.cos(angl) - costheta * math.sin(angl)
dc = costheta * math.cos(angl) + sintheta * math.sin(angl)
dtheta = tf.math.abs(tf.math.atan2(ds,dc)).numpy()
spread[o-1] = tf.math.exp((-dtheta**2) / (2 * thetaSigma**2)).numpy()
EnergyAll=np.zeros((rows,cols))
AnAll=np.zeros((rows,cols))
for o in range(1,norient+1):
sumE_ThisOrient=np.zeros((rows,cols))
sumO_ThisOrient=np.zeros((rows,cols))
sumAn_ThisOrient=np.zeros((rows,cols))
Energy=np.zeros((rows,cols))
for s in range(1,nscale+1):
filter = logGabor[s-1] * spread[o-1]
ifftFilt=(tf.math.real(tf.signal.ifft2d(filter))*math.sqrt(rows*cols)).numpy()
ifftFilterArray[s-1]=ifftFilt
EO[s-1][o-1]=tf.signal.ifft2d(imagefft*filter).numpy()
An=tf.math.abs(EO[s-1][o-1]).numpy()
sumAn_ThisOrient = sumAn_ThisOrient + An
sumE_ThisOrient = sumE_ThisOrient + tf.math.real(EO[s-1][o-1]).numpy()
sumO_ThisOrient = sumO_ThisOrient + tf.math.imag(EO[s-1][o-1]).numpy()
if s==1:
EM_n=np.sum(filter**2)
maxAn = An
else:
maxAn =tf.math.maximum(maxAn, An).numpy()
XEnergy=tf.math.sqrt(sumE_ThisOrient**2+sumO_ThisOrient**2).numpy()+epsilon
MeanE = sumE_ThisOrient / XEnergy
MeanO = sumO_ThisOrient / XEnergy
for s in range(1,nscale+1):
E=tf.math.real(EO[s-1][o-1]).numpy()
O=tf.math.imag(EO[s-1][o-1]).numpy()
Energy = Energy + E*MeanE + O*MeanO - tf.math.abs(E*MeanO - O*MeanE).numpy()
medianE2n = np.median(np.reshape((tf.math.abs(EO[0][o-1]).numpy())**2,(rows*cols,)))
meanE2n = -medianE2n/math.log(0.5)
estMeanE2n[o-1] = meanE2n
noisePower = meanE2n/EM_n
EstSumAn2=np.zeros((rows,cols))
for s in range(1,nscale+1):
EstSumAn2 = EstSumAn2 + ifftFilterArray[s-1]**2
EstSumAiAj=np.zeros((rows,cols))
for si in range(1,nscale):
for sj in range(si+1,nscale+1):
EstSumAiAj = EstSumAiAj + ifftFilterArray[si-1]*ifftFilterArray[sj-1]
sumEstSumAn2=np.sum(EstSumAn2)
sumEstSumAiAj=np.sum(EstSumAiAj)
EstNoiseEnergy2 = 2*noisePower*sumEstSumAn2 + 4*noisePower*sumEstSumAiAj
tau = math.sqrt(EstNoiseEnergy2/2)
EstNoiseEnergy = tau*math.sqrt(math.pi/2)
EstNoiseEnergySigma = math.sqrt( (2-math.pi/2)*tau**2 )
T = EstNoiseEnergy + k*EstNoiseEnergySigma
T = T/1.7
Energy=Energy-T
Energy=tf.math.maximum(Energy,tf.zeros((rows,cols))).numpy()
EnergyAll = EnergyAll + Energy
AnAll = AnAll + sumAn_ThisOrient
ResultPC = EnergyAll / AnAll
return ResultPC
def FeatureSIM(imageRef, imageDis):
imageRef=np.squeeze(imageRef)
imageDis=np.squeeze(imageDis)
img_shape=np.shape(imageRef)
rows,cols=img_shape[:2]
I1=np.ones((rows,cols))
I2=np.ones((rows,cols))
Q1=np.ones((rows,cols))
Q2=np.ones((rows,cols))
if len(img_shape)==3:
Y1 = 0.299 * imageRef[:,:,0] + 0.587 * imageRef[:,:,1] + 0.114 * imageRef[:,:,2]
Y2 = 0.299 * imageDis[:,:,0] + 0.587 * imageDis[:,:,1] + 0.114 * imageDis[:,:,2]
I1 = 0.596 * imageRef[:,:,0] - 0.274 * imageRef[:,:,1] - 0.322 * imageRef[:,:,2]
I2 = 0.596 * imageDis[:,:,0] - 0.274 * imageDis[:,:,1] - 0.322 * imageDis[:,:,2]
Q1 = 0.211 * imageRef[:,:,0] - 0.523 * imageRef[:,:,1] + 0.312 * imageRef[:,:,2]
Q2 = 0.211 * imageDis[:,:,0] - 0.523 * imageDis[:,:,1] + 0.312 * imageDis[:,:,2]
else:
Y1=imageRef
Y2=imageDis
Y1=Y1.astype(np.float32)
Y2=Y2.astype(np.float32)
I1=I1.astype(np.float32)
I2=I2.astype(np.float32)
Q1=Q1.astype(np.float32)
Q2=Q2.astype(np.float32)
minDimension = min(rows,cols)
F = max(1,round(minDimension / 256))
aveKernel=np.ones((F,F))/(F*F)
aveKernel=aveKernel.astype(np.float32)
aveI1=tf.nn.conv2d(tf.reshape(I1,[1,rows,cols,1]),tf.reshape(aveKernel,[F,F,1,1]),strides=[1,1,1,1],padding='SAME').numpy()
aveI2=tf.nn.conv2d(tf.reshape(I2,[1,rows,cols,1]),tf.reshape(aveKernel,[F,F,1,1]),strides=[1,1,1,1],padding='SAME').numpy()
I1=aveI1[0,0:rows:F,0:cols:F,0]
I2=aveI2[0,0:rows:F,0:cols:F,0]
aveQ1=tf.nn.conv2d(tf.reshape(Q1,[1,rows,cols,1]),tf.reshape(aveKernel,[F,F,1,1]),strides=[1,1,1,1],padding='SAME').numpy()
aveQ2=tf.nn.conv2d(tf.reshape(Q2,[1,rows,cols,1]),tf.reshape(aveKernel,[F,F,1,1]),strides=[1,1,1,1],padding='SAME').numpy()
Q1=aveQ1[0,0:rows:F,0:cols:F,0]
Q2=aveQ2[0,0:rows:F,0:cols:F,0]
aveY1=tf.nn.conv2d(tf.reshape(Y1,[1,rows,cols,1]),tf.reshape(aveKernel,[F,F,1,1]),strides=[1,1,1,1],padding='SAME').numpy()
aveY2=tf.nn.conv2d(tf.reshape(Y2,[1,rows,cols,1]),tf.reshape(aveKernel,[F,F,1,1]),strides=[1,1,1,1],padding='SAME').numpy()
Y1=aveY1[0,0:rows:F,0:cols:F,0]
Y2=aveY2[0,0:rows:F,0:cols:F,0]
PC1 = phasecong2(Y1)
PC2 = phasecong2(Y2)
dx=np.array([[3,0,-3],[10,0,-10],[3,0,-3]],np.float32)/16
dy=np.array([[3,10,3],[0,0,0],[-3,-10,-3]],np.float32)/16
IxY1=tf.nn.conv2d(tf.reshape(Y1,[1,Y1.shape[0],Y1.shape[1],1]),tf.reshape(dx,[3,3,1,1]),strides=[1,1,1,1],padding='SAME').numpy()
IyY1=tf.nn.conv2d(tf.reshape(Y1,[1,Y1.shape[0],Y1.shape[1],1]),tf.reshape(dy,[3,3,1,1]),strides=[1,1,1,1],padding='SAME').numpy()
gradientMap1=tf.math.sqrt(IxY1**2+IyY1**2).numpy()