用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应用于输入和每个卷积层,产生稍好的结果. 你可以在这里找到完整的代码: 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) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |