加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

用Theano实现LeCun局部对比度规范化

发布时间:2020-12-20 11:40:00 所属栏目:Python 来源:网络整理
导读:我正在尝试使用我发现的代码来实现LeCun局部对比度规范化,但结果不正确.代码在 Python中并使用theano库. def lecun_lcn(input,img_shape,kernel_shape,threshold=1e-4): """ Yann LeCun's local contrast normalization Orginal code in Theano by: Guillaum
我正在尝试使用我发现的代码来实现LeCun局部对比度规范化,但结果不正确.代码在 Python中并使用theano库.

def lecun_lcn(input,img_shape,kernel_shape,threshold=1e-4):
    """
    Yann LeCun's local contrast normalization
    Orginal code in Theano by: Guillaume Desjardins
    """
    input = input.reshape(input.shape[0],1,img_shape[0],img_shape[1])
    X = T.matrix(dtype=theano.config.floatX)
    X = X.reshape(input.shape)

    filter_shape = (1,kernel_shape)
    filters = gaussian_filter(kernel_shape).reshape(filter_shape)

    convout = conv.conv2d(input=X,filters=filters,image_shape=(input.shape[0],img_shape[1]),filter_shape=filter_shape,border_mode='full')

    # For each pixel,remove mean of 9x9 neighborhood

    mid = int(np.floor(kernel_shape / 2.))
    centered_X = X - convout[:,:,mid:-mid,mid:-mid]
    # Scale down norm of 9x9 patch if norm is bigger than 1
    sum_sqr_XX = conv.conv2d(input=centered_X ** 2,border_mode='full')

    denom = T.sqrt(sum_sqr_XX[:,mid:-mid])
    per_img_mean = denom.mean(axis=[1,2])
    divisor = T.largest(per_img_mean.dimshuffle(0,'x',1),denom)
    divisor = T.maximum(divisor,threshold)

    new_X = centered_X / divisor
    new_X = new_X.dimshuffle(0,2,3,1)
    new_X = new_X.flatten(ndim=3)

    f = theano.function([X],new_X)
    return f(input)

这是测试代码:

x_img_origin = plt.imread("..//data//Lenna.png")
x_img = plt.imread("..//data//Lenna.png")
x_img_real_result = plt.imread("..//data//Lenna_Processed.png")

x_img = x_img.reshape(1,x_img.shape[0],x_img.shape[1],x_img.shape[2])
for d in range(3):
    x_img[:,d] = tools.lecun_lcn(x_img[:,d],(x_img.shape[1],x_img.shape[2]),9)
x_img = x_img[0]

pylab.subplot(1,1); pylab.axis('off'); pylab.imshow(x_img_origin)
pylab.gray()
pylab.subplot(1,2); pylab.axis('off'); pylab.imshow(x_img)
pylab.subplot(1,3); pylab.axis('off'); pylab.imshow(x_img_real_result)
pylab.show()

结果如下:

(从左到右:原点,我的结果,预期结果)

有人能告诉我我的代码错了吗?

解决方法

以下是我在Jarrett等人( http://yann.lecun.com/exdb/publis/pdf/jarrett-iccv-09.pdf)中报道的如何实现局部对比度归一化的方法.您可以将其用作单独的图层.

我在theano的LeNet教程的代码中对它进行了测试,其中我将LCN应用于输入和每个卷积层,产生稍好的结果.

你可以在这里找到完整的代码:
https://github.com/jostosh/theano_utils/blob/master/lcn.py

class LecunLCN(object):
def __init__(self,X,image_shape,threshold=1e-4,radius=9,use_divisor=True):
    """
    Allocate an LCN.

    :type X: theano.tensor.dtensor4
    :param X: symbolic image tensor,of shape image_shape

    :type image_shape: tuple or list of length 4
    :param image_shape: (batch size,num input feature maps,image height,image width)
    :type threshold: double
    :param threshold: the threshold will be used to avoid division by zeros

    :type radius: int
    :param radius: determines size of Gaussian filter patch (default 9x9)

    :type use_divisor: Boolean
    :param use_divisor: whether or not to apply divisive normalization
    """

    # Get Gaussian filter
    filter_shape = (1,image_shape[1],radius,radius)

    self.filters = theano.shared(self.gaussian_filter(filter_shape),borrow=True)

    # Compute the Guassian weighted average by means of convolution
    convout = conv.conv2d(
        input=X,filters=self.filters,image_shape=image_shape,border_mode='full'
    )

    # Subtractive step
    mid = int(numpy.floor(filter_shape[2] / 2.))

    # Make filter dimension broadcastable and subtract
    centered_X = X - T.addbroadcast(convout[:,mid:-mid],1)

    # Boolean marks whether or not to perform divisive step
    if use_divisor:
        # Note that the local variances can be computed by using the centered_X
        # tensor. If we convolve this with the mean filter,that should give us
        # the variance at each point. We simply take the square root to get our
        # denominator

        # Compute variances
        sum_sqr_XX = conv.conv2d(
            input=T.sqr(centered_X),border_mode='full'
        )


        # Take square root to get local standard deviation
        denom = T.sqrt(sum_sqr_XX[:,mid:-mid])

        per_img_mean = denom.mean(axis=[2,3])
        divisor = T.largest(per_img_mean.dimshuffle(0,'x'),denom)
        # Divisise step
        new_X = centered_X / T.maximum(T.addbroadcast(divisor,threshold)
    else:
        new_X = centered_X

    self.output = new_X


def gaussian_filter(self,kernel_shape):
    x = numpy.zeros(kernel_shape,dtype=theano.config.floatX)

    def gauss(x,y,sigma=2.0):
        Z = 2 * numpy.pi * sigma ** 2
        return  1. / Z * numpy.exp(-(x ** 2 + y ** 2) / (2. * sigma ** 2))

    mid = numpy.floor(kernel_shape[-1] / 2.)
    for kernel_idx in xrange(0,kernel_shape[1]):
        for i in xrange(0,kernel_shape[2]):
            for j in xrange(0,kernel_shape[3]):
                x[0,kernel_idx,i,j] = gauss(i - mid,j - mid)

    return x / numpy.sum(x)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读