我想在Tensorflow / Keras中使用scipy.signal.fftconvolve
,有没有办法做到这一点?
现在我正在使用以下代码:
window = np.tile(window, (1, 1, 1, 3))
tf.nn.conv2d(img1, window, strides=[1,1,1,1], padding='VALID')
这些行是否等同于:
signal.fftconvolve(img1, window, mode='valid')
答案 0 :(得分:2)
scipy.signal.fftconvolve
import tensorflow as tf
def _centered(arr, newshape):
# Return the center newshape portion of the array.
currshape = tf.shape(arr)[-2:]
startind = (currshape - newshape) // 2
endind = startind + newshape
return arr[..., startind[0]:endind[0], startind[1]:endind[1]]
def fftconv(in1, in2, mode="full"):
# Reorder channels to come second (needed for fft)
in1 = tf.transpose(in1, perm=[0, 3, 1, 2])
in2 = tf.transpose(in2, perm=[0, 3, 1, 2])
# Extract shapes
s1 = tf.convert_to_tensor(tf.shape(in1)[-2:])
s2 = tf.convert_to_tensor(tf.shape(in2)[-2:])
shape = s1 + s2 - 1
# Compute convolution in fourier space
sp1 = tf.spectral.rfft2d(in1, shape)
sp2 = tf.spectral.rfft2d(in2, shape)
ret = tf.spectral.irfft2d(sp1 * sp2, shape)
# Crop according to mode
if mode == "full":
cropped = ret
elif mode == "same":
cropped = _centered(ret, s1)
elif mode == "valid":
cropped = _centered(ret, s1 - s2 + 1)
else:
raise ValueError("Acceptable mode flags are 'valid',"
" 'same', or 'full'.")
# Reorder channels to last
result = tf.transpose(cropped, perm=[0, 2, 3, 1])
return result
将宽度为20像素的高斯平滑应用于标准“面部”图像的简单示例如下:
if __name__ == '__main__':
from scipy import misc
import matplotlib.pyplot as plt
from tensorflow.python.ops import array_ops, math_ops
session = tf.InteractiveSession()
# Create gaussian
std = 20
grid_x, grid_y = array_ops.meshgrid(math_ops.range(3 * std),
math_ops.range(3 * std))
grid_x = tf.cast(grid_x[None, ..., None], 'float32')
grid_y = tf.cast(grid_y[None, ..., None], 'float32')
gaussian = tf.exp(-((grid_x - 1.5 * std) ** 2 + (grid_y - 1.5 * std) ** 2) / std ** 2)
gaussian = gaussian / tf.reduce_sum(gaussian)
face = misc.face(gray=False)[None, ...].astype('float32')
# Apply convolution
result = fftconv(face, gaussian, 'same')
result_r = session.run(result)
# Show results
plt.figure('face')
plt.imshow(face[0, ...] / 256.0)
plt.figure('convolved')
plt.imshow(result_r[0, ...] / 256.0)
答案 1 :(得分:0)
你想要一个普通的conv2d
然后......
如果您想在模型中的某个位置添加Conv2D(...,name='myLayer')
图层,并在模型中使用model.get_layer('myLayer').set_weights([filters,biases])
如果你想要它在一个损失函数中,只需创建一个损失函数:
import keras.backend as K
def myLoss(y_true, y_pred):
#where y_true is the true training data and y_pred is the model's output
convResult = K.conv2d(y_pred, kernel = window, padding = 'same')
anotherResult = K.depthwise_conv2d(y_pred, kernel = window, padding='same')
常规conv2D将假设过滤器中的每个输出通道将处理并求和所有输入通道。
深度卷积将保持输入通道分离。
但是,请小心窗外。我不知道tensorflow或scipy中的格式,但是keras中的内核应该具有这样的形状:(height, width, numberOfInputChannels, numberOfOutputChannels)
我相信,如果我理解正确的话,它应该是window = np.reshape(_FSpecialGauss(size, sigma), (size, size, 1, 1))
,考虑到“size”是内核的大小而你只有1个输入和输出通道。
我使用padding='same'
来获得与输入相同大小的结果图像。如果您使用padding='valid'
,则会丢失边框(尽管在您的情况下,您的过滤器似乎有大小(1,1),但不会删除边框)。
您也可以在损失函数中使用任何张量流函数:
def customLoss(yTrue,yPred):
tf.anyFunction(yTrue)
tf.anyFunction(yPred)
使用keras backend可以让您的代码以后可以移植到其他后端。
编译模型时,给它你的损失函数:
model.compile(loss=myLoss, optimizer =....)