Python 如何在keras中添加自定义图像锐化层?

Python 如何在keras中添加自定义图像锐化层?,python,tensorflow,neural-network,keras,deep-learning,Python,Tensorflow,Neural Network,Keras,Deep Learning,我正在keras中建立一个模型,从图像中检测建筑物屋顶。我想在模型中添加一个自定义锐化层。我知道我们可以在预处理中锐化图像,但如果我添加一个图层就好了。我用自定义锐化功能尝试了Lambda层,但它不起作用,然后我尝试了自定义层,得到了相同的错误: TypeError Traceback (most recent call last) <ipython-input-5-3062d6b8160d> in <module

我正在keras中建立一个模型,从图像中检测建筑物屋顶。我想在模型中添加一个自定义锐化层。我知道我们可以在预处理中锐化图像,但如果我添加一个图层就好了。我用自定义锐化功能尝试了Lambda层,但它不起作用,然后我尝试了自定义层,得到了相同的错误:

TypeError                                 Traceback (most recent call last)
<ipython-input-5-3062d6b8160d> in <module>()
      1 # MY MODEL
      2 from u_net import mymodel300
----> 3 model = mymodel300((300, 300, 3))

~\Desktop\SAVERA\MYCODE\u_net.py in mymodel300(input_shape)
    186     # LAYERS
    187     inputs = Input(shape=input_shape)
--> 188     sharp = Sharpen(num_outputs=(300,300,3))(inputs)
    189     # 300x300
    190 

~\Anaconda3\lib\site-packages\tensorflow\python\keras\engine\base_layer.py in __call__(self, inputs, *args, **kwargs)
    701 
    702       if not in_deferred_mode:
--> 703         outputs = self.call(inputs, *args, **kwargs)
    704         if outputs is None:
    705           raise ValueError('A layer\'s `call` method should return a Tensor '

~\Desktop\SAVERA\MYCODE\u_net.py in call(self, input_)
    179     kernel_sharp = np.array(([-2, -2, -2], [-2, 17, -2], [-2, -2, -2]), dtype='int')
    180     #denoised = cv2.fastNlMeansDenoisingColored(img,None,5,5,2,10)
--> 181     self.sharp = cv2.filter2D(input_, -1, kernel_sharp)
    182     return self.sharp
    183 

TypeError: src is not a numpy array, neither a scalar
下面是我要放置此层的模型:

def mymodel300(input_shape=(300, 300, 3)):
    inputs = Input(shape=input_shape)
    # MY CUSTOM LAYER
    sharp = Sharpen(num_outputs=(300,300,3))(inputs)
    # 300x300

    down0 = Conv2D(32, (3, 3), padding='same')(sharp)
    down0 = BatchNormalization()(down0)
    down0 = Activation('relu')(down0)
    down0 = Conv2D(32, (3, 3), padding='same')(down0)
    down0 = BatchNormalization()(down0)
    down0 = Activation('relu')(down0)
    down0_pool = MaxPooling2D((2, 2), strides=(2, 2))(down0)

我认为这应该作为预处理步骤的一部分来完成,因为在锐化层中没有您想要训练的参数来帮助特征生成或分类,所以它不需要是网络模型的一部分


Keras图像预处理文档在这里:

我发现了如何使用自定义内核创建自定义层。感谢apple提示您使用conv2d

我使用Tensorflow的tf.nn.conv2d,而不是cv2.filter2D,以及我的自定义锐化过滤器。这是自定义图层:

from tensorflow.keras.layers import Layer
from tensorflow.keras import backend as K
# CUSTOM SHARPEN LAYER
class Sharpen(Layer):
  def __init__(self, num_outputs):
    super(Sharpen, self).__init__()
    self.num_outputs = num_outputs

  def call(self, input_):
    import numpy as np
    import cv2
    # SHARPEN
    kernel_sharp = np.array(([-2, -2, -2], [-2, 17, -2], [-2, -2, -2]), dtype='int')
    #denoised = cv2.fastNlMeansDenoisingColored(img,None,5,5,2,10)
    self.sharp = cv2.filter2D(input_, -1, kernel_sharp)
    return self.sharp
# CUSTOM SHARPEN LAYER
class Sharpen(tf.keras.layers.Layer):
    def __init__(self, num_outputs):
        super(Sharpen, self).__init__()
        self.num_outputs = num_outputs

    def build(self, input_shape):
        self.kernel = np.array([[-2, -2, -2], 
                                [-2, 17, -2], 
                                [-2, -2, -2]])
        self.kernel = tf.expand_dims(self.kernel, 0)
        self.kernel = tf.expand_dims(self.kernel, 0)
        self.kernel = tf.cast(self.kernel, tf.float32)

    def call(self, input_):
        return tf.nn.conv2d(input_, self.kernel, strides=[1, 1, 1, 1], padding='SAME')

“我知道我们可以在预处理中锐化图像,但如果我添加一个层就好了”OP说。就像我们可以向Lambda层输入函数以获得自定义层,那么为什么我们不能添加直接自定义层。@appleapple说OP应该做什么,而不是他/她想做什么,是正确的答案——至少是个好答案。@P-Gn如果OP不知道这个方法,我会同意的。您需要在网络中设置一个固定的处理层(例如maxpool)是有原因的。您不应该使用
cv2
进行处理。它显然不会给你张量。也许您可以使用
trainable=false
尝试类似于
Conv2D
的方法。我们可以为Conv2D添加自定义内核吗?否则Conv2D会有什么帮助呢?我们也可以通过tf将cv2的结果转换成tensor来从cv2返回tensor。convert_to_tensor但是你不能通过
keras(tensorflow)
cv2
函数放在GPU上,对吗?或者可能有帮助。