2018-06-27 16:30:41 heiheiya 阅读数 400
  • 卷积网络中特征的N种使用方式

    卷积神经网络视频教程,该课程以卷积神经网络处理图像为例,探讨了卷积得到的特征图(feature maps)的特性和运用,展示了特征在数据重建、图像生成、对抗样本、相似图查找等等领域的广泛运用,并辅以代码示例,帮助学员更好地理解深度学习和传统机器学习,乃至传统计算机视觉的关系。

    1609 人正在学习 去看看 CSDN讲师

定义  

  卷积是图像处理中很常见的操作,它通过计算原图像和一个卷积核的加权和来对图像进行滤波。根据卷积核的不同,可以完成对图像的模糊、锐化、降噪、边缘检测等其他功能。

  离散二维卷积公式可以表示为,

  

  上述公式中,f即表示原图像,g表示卷积核。卷积核的中心总是对准当前计算的像素点。

  在OpenGL中可以使用GLSL语言对shader进行编程,在shader中计算卷积。这个过程应该放在fragment shader中进行,但是在计算一个点的卷积时需要周围点的像素值共同计算,但当前的fragment是不能访问其他fragment的值。一个办法是将原图像以纹理的形式绑定到texture memory,就可以共享了。

  不同的卷积核可以完成不同的图像处理效果。

一、 平滑

 

  图像平滑可以衰减图像中的高频分量。最常见的平滑是领域均值滤波,它的卷积核的每一个值都等于1,比如一个3x3的卷积核是这样的,

  

  最终该点像素值等于该领域内像素的均值。

  这样的卷积可以写成如下shader,

// maximum size supported by this shaderconst 
int MaxKernelSize = 25; 
// array of offsets for accessing the base imageuniform 
vec2 Offset[MaxKernelSize]; 
// size of kernel (width * height) for this executionuniform 
int KernelSize; 
// final scaling valueuniform 
vec4 ScaleFactor; // image to be convolveduniform 
sampler2D BaseImage; 
void main(){    
int i;    
vec4 sum = vec4(0.0);     
for (i = 0; i < KernelSize; i++)        
    sum += texture2D(BaseImage,gl_TexCoord[0].st + Offset[i]);     
gl_FragColor = sum * ScaleFactor;}

  图像平滑通常被用来做图像降噪,这对稠密的或者纯色的区域表现很好,但是它有一个副作用就是会滤掉高频分量,也就是会影响到图像边缘信息。如果对越接近中心的值给予越来的权重,就能在降噪的同时保持好边缘信息,比如高斯滤波器。

下图是对一副灰度图像分别做了均值滤波和高斯滤波的效果。

 

  

 

  但是随着卷积核的增大,对纹理的读取次数以核的维度的平方增加,核越大,计算效率越低。但是对于像高斯这样的滤波器,一个widthxheight大小的卷积核,可以分成水平widthx1和垂直1xheight两个一维的卷积。虽然这样每个像素会增加一次写操作,但是纹理的读取却从widthxheight减少到width+height次。

 

二、 边缘检测

  使用拉普拉斯卷积核可以实现边缘检测,

  

  最终效果如下所示。

  

三、 锐化

 

  完成锐化一个简单常用的方法是把边缘检测的结果与原图像相加。为控制锐化的程度,需要给边缘检测的图像乘以一个权重。锐化时使用的是负的拉普拉斯卷积核。

  shader如下:

// maximum size supported by this shaderconst 
int MaxKernelSize = 25; 
// array of offsets for accessing the base imageuniform 
vec2 Offset[MaxKernelSize]; 
// size of kernel (width * height) for this executionuniform 
int KernelSize;
// value for each location in the convolution kerneluniform 
vec4 KernelValue[MaxKernelSize]; 
// scaling factor for edge imageuniform
vec4 ScaleFactor; 
// image to be convolveduniform
sampler2D BaseImage; 
void main(){    
int i;    
vec4 sum = vec4(0.0);     
for (i = 0; i < KernelSize; i++)    {        
    vec4 tmp = texture2D(BaseImage, 
    gl_TexCoord[0].st + Offset[i]);        
    sum += tmp * KernelValue[i];   }
vec4 baseColor = texture2D(BaseImage,vec2(gl_TexCoord[0]));    
gl_FragColor = ScaleFactor * sum + baseColor;}

  最后出来的效果如下图。

2018-08-07 20:01:18 Kedongyu_ 阅读数 780
  • 卷积网络中特征的N种使用方式

    卷积神经网络视频教程,该课程以卷积神经网络处理图像为例,探讨了卷积得到的特征图(feature maps)的特性和运用,展示了特征在数据重建、图像生成、对抗样本、相似图查找等等领域的广泛运用,并辅以代码示例,帮助学员更好地理解深度学习和传统机器学习,乃至传统计算机视觉的关系。

    1609 人正在学习 去看看 CSDN讲师

先来几张图认识什么是一维数组卷积:

卷积的应用,图像处理很多地方都会用到卷积运算,具体用在哪方面我也不知道,坐等老师讲解,百度:图像中滤波、均值滤波、锐化等都是在空间域里进行卷积,也就是二维卷积

进入正题,一维数组卷积,用一个例子讲解。

数组 f = [ 0, 1, 2, 3, 4 ] ,g = [0, 1, 2]

设数组h 为 f 和 g 卷积后的结果,则 数组的长度为 len( f ) + len ( g ) – 1 = 7

如下图所示,

可以得出:

           Len(h) = Len(f) + Len(g) - 1 

实现此函数

        定义函数 def convolution( f , g ) 为实现数组f 与数组 g的卷积,并将结果数组h返回

def convolution ( f, g):

         #第一步创建并初始化结果数组h

         #使用numpy.zeros( num )函数,其功能主要创建一个长度为num的数组,并将数组数据初始化为0 

         h = numpy.zeros( len(f) + len(g) – 1)   #初始化一个长度为 f和g数组的长度之和-1

 #实现卷积运算,我们将其分为三部分:

         #实现卷积运算,我们将其分为三部分:

         #第一部分为数组g刚开始进入数组f的过程

         #第二部分为数组g在数组f中

         #第三部分为数组g出数组f的过程

 

 第一部分:

 

                   #即上图k从0到2的状态为第一部分

                   #k从3到4为第二部分

                   #k从5到6为第三部分

                   #首先实现第一部分

                   #由图可知,

            for k in range( len(g) ):  
                #range()函数为创建一个数组[0, len(g) ),
                #即0到len(g)的左闭右开数组,此条语句k将依次取该数组元素进行循环,
                #即k从0到len(g) 循环
		h[k] =sum (f[:k+1] * g_[len(g) - 1 - k:])
                #sum(range) 中,range为数组,sum(range)为计算一个数组所有元素之和
                #即sum( [ 1, 2, 3,4 ]) = 10
                #先看f数组   f[:k+1]
                #f[ :k+1] 等价于 f[0:k+1]
                #右下图可知,上标一直在最头部up = 0,而下标为down = k+1

 

                # 再看g_[len(g) - 1 - k:]
                # 首先g函数原本是[0, 1, 2],如图所示,
                #卷积需要将其反转为[2, 1, 0],也就是从右到左,即g_ = g[::-1] = [2, 1, 0]
                #g_数组下标down不变为尾部,头部up 从len(g)-1的位置往前移动k,即up=len(g)-1-k

                                                 所以 h[k] =sum (f[:k+1] * g_[len(g) - 1 - k:])

第二部分:即整个数组g进入数组f

         第二部分  

 

      for k in range(len(g), len(f)):
            h[k] = sum(f[k + 1 - len(g) : k + 1 ] * g[::-1])

   

第二部中g数组整个数组的所有元素都被用到即 g[::-1]

再看f[k + 1 - len(g) : k + 1 ]

如上图,f数组与g数组的重合的三个数有效,

先看f数组的下标 down = k+1 此下标与第一部分一样。

因为f数组参加运算元素的长度与g数组长度一样,下标确定,那么上标为up=down-len(g)    即:  up=k+1-len(g)

第一二步理解了第三步也就容易理解了

第三部分:G数组出f数组,

        h[k] = sum(f[k + 1 - len(g):]*g_[: len(g) - (k + 1 - len(f))])

先看g数组,首先取反 即g_=g[::-1]

然后上标不变为最前,下标每次随着k的增大1而减少最尾部1个元素

而在第三部分 k的范围是   len(f) - 1 <k <len(f)+len(g)-1

k增大多少次,尾部减少多少个元素 如和判断k增加了多少,那就是 k-len(f)+1

即减少个范围为   0<k-len(f)+1<len(g)  也就是

减少到只剩下一个元素那么卷积就结束了,整个g数组就出去了

即 原本没减是g’[:len(g)],现在尾部减少k-len(f)+1个元素,

那么就是:g_[: len(g) - (k - len(f) + 1)]

 

f[k + 1 - len(g):]

和 g数组差不多,但是f是取尾部,g数组是取头部

尾部其实和头部道理一样,取头部修改下标,取尾部修改上标,让 k的关系和取得位置对应起来就可以了

原本为 f[len(f)-len(g):len(f)] 现在随着k的增大,数组左边元素减少k-len(f)+1个

即:

f[len(f)-len(g)+(k-len(f)+1):len(f)]=f[k-len(g)+1:]

所以:

h[k] = sum(f[k + 1 - len(g):]*g_[: len(g) - (k - len(f) + 1)])

 

最后返回数组 h

完整代码(3个版本):

#这个函数也不重要了,可以理解就可以了,知道是做了什么事情
def conv1d_v0010_kdy(f, g):
    #创建并初始化数组,长度为f数组和g数组长度之和-1,
    h = numpy.zeros((len(f) + len(g) - 1, ))#数组数据都为0
   # g_ = g[::-1]
    
    for k in range(len(g)):
        h[k] = sum(f[:k+1] * g[ -len(g) + k::-1])
        #h[k] =sum (f[:k+1] * g_[len(g) - 1 - k:])
    
    for k in range(len(g), len(f)):
        h[k] = sum(f[k + 1 - len(g) : k + 1 ] * g[::-1])
    
    for k in range(len(f), len(f) + len(g) - 1):
        h[k] = sum(f[k + 1 - len(g):]*g[: k - len(f) - len(g):-1])
        #h[k] = sum(f[k + 1 - len(g):]*g_[: len(g) - (k - len(f) + 1)])
        
    return h
#这个函数也不重要了,可以理解就可以了
#老师这份代码是先把f反转,g不反转,而我做的上面那个是g反转,f不反转,道理是一样的,
#但正常来说应该是g反转,也就是小的数组反转,我问了老师,老师好像是说反转f比较容易讲。。。
def conv1d_v0010(f,g):
    h = numpy.zeros((len(f)+len(g)-1,))
    for k in range(len(g)):
        h[k] = (f[k::-1]*g[:k+1]).sum()
        
    for k in range(len(g), len(f)):
        h[k] = (f[k:k-len(g):-1]*g).sum()
        
    for k in range(len(f), len(h)):
        #h[11] = f[10:9] *g[2:3]=9*2=18
        h[k] = (f[:k-len(g):-1]*g[k-len(f)+1:]).sum()
        
    return h
#最重要的是这个函数
def conv1d(f_, g_):
    #创建卷积后的存放数组
    h = numpy.zeros((len(f_)+len(g_)-1,))
    #反转数组g
    g = g_[::-1]
    
    #创建一个和g数组一模一样大的数组,全部初始化为0
    zeroblock = numpy.zeros_like(g)
    #在f数组前后接上 zeroblock数组   也就是 假使原来数组f为      
    #1, 2, 3, 4   那么接后就是:0, 0,0 ,1,2,3,4,0,0,0
    # 例如 0, 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 0
    #   与    2,1,0     这样卷积起来就很容易了
    f = numpy.hstack((zeroblock, f_, zeroblock))
    
    #下面就是卷积的操作
    for k in range(len(g_)+len(f_)-1):
        h[k]=(f[k+1:k+1+len(g)]*g).sum()
        
    return h

测试用例:


if __name__ == "__main__":
    f_shape, g_shape = 15, 3
    f, g = numpy.arange(f_shape), numpy.arange(g_shape)
    h = conv1d_v0010(f,g)
    print (h)
    i = conv1d(f,g)
    print (i)
    j = conv1d_v0010_kdy(f, g)
    print (j)
    f, g = numpy.arange(f_shape, f_shape), numpy.arange(g_shape, g_shape)
    

(完)

2016-08-30 23:30:47 q6324266 阅读数 5034
  • 卷积网络中特征的N种使用方式

    卷积神经网络视频教程,该课程以卷积神经网络处理图像为例,探讨了卷积得到的特征图(feature maps)的特性和运用,展示了特征在数据重建、图像生成、对抗样本、相似图查找等等领域的广泛运用,并辅以代码示例,帮助学员更好地理解深度学习和传统机器学习,乃至传统计算机视觉的关系。

    1609 人正在学习 去看看 CSDN讲师

图像处理中滤波和卷积是常用到的操作。很多人认为卷积就是滤波,两者并无区别,其实不然。两者在原理上相似,但是在实现的细节上存在一些区别。这篇博文主要叙述这两者之间的区别。

1、滤波(或者叫相关)

简单来说,滤波操作就是图像对应像素与掩膜(mask)的乘积之和。

比如有一张图片和一个掩膜,如下图:



那么像素(i,j)的滤波后结果可以根据以下公式计算:

其中G(i,j)是图片中(i,j)位置像素经过滤波后的像素值。

当掩膜中心m5位置移动到图像(i,j)像素位置时,图像(i,j)位置像素称为锚点

滤波步骤:

  1. 对原始图像的边缘进行某种方式的填充(一般为0填充)。
  2. 将掩膜划过整幅图像,计算图像中每个像素点的滤波结果。
依照这个步骤,假设我们有一个二维矩阵I,掩膜M,则滤波的结果如下:


滤波后的图像大小不变。



2、卷积

卷积的原理与滤波类似。但是卷积却有着细小的差别。
卷积操作也是卷积核与图像对应位置的乘积和。但是卷积操作在做乘积之前,需要先将卷积核翻转180度,之后再做乘积。

卷积步骤:
  1. 180度翻转卷积核。
  2. 不做边界填充,直接对图像进行相应位置乘积和。
从以上步骤可以看出,如果卷积核不是中心对称的,那么卷积和滤波操作将会得到完全不一样的结果。另外,卷积操作会改变图像大小!

由于卷积操作会导致图像变小(损失图像边缘),所以为了保证卷积后图像大小与原图一致,经常的一种做法是人为的在卷积操作之前对图像边缘进行填充。

最后,关于卷积后图像尺寸的计算:假设原始图像为M*M,卷积核大小为N*N,边缘填充像素个数为pad,步长为stride。则卷积后图像的尺寸变为:m =(M-N+2*pad)/sride+1。

2018-08-07 19:12:59 Kedongyu_ 阅读数 207
  • 卷积网络中特征的N种使用方式

    卷积神经网络视频教程,该课程以卷积神经网络处理图像为例,探讨了卷积得到的特征图(feature maps)的特性和运用,展示了特征在数据重建、图像生成、对抗样本、相似图查找等等领域的广泛运用,并辅以代码示例,帮助学员更好地理解深度学习和传统机器学习,乃至传统计算机视觉的关系。

    1609 人正在学习 去看看 CSDN讲师
# -*- coding: utf-8 -*-
"""
Created on Wed May 02 15:08:01 2018

@author: Diko
"""

import numpy 
from skimage import io ,data

def conv2d_v0010(f_, g_):
    g = g_[::-1, ::-1]
    f = f_
    h = numpy.vstack([numpy.zeros(f_.shape[1] + g_.shape[1] - 1)] * (g_.shape[0] + f_.shape[0] -1))
    
    f_up_and_dowm = numpy.vstack([numpy.zeros(f.shape[1])]*g.shape[0])
    f = numpy.vstack((f_up_and_dowm,f,f_up_and_dowm))
    
    f_left_and_right = numpy.vstack([numpy.zeros(g.shape[1])] * f.shape[0])
    f = numpy.hstack((f_left_and_right, f, f_left_and_right))
    
    for i in xrange(f_.shape[0] + g_.shape[0] - 1):
        for j in xrange(f_.shape[1] + g_.shape[1] -1):
            h[i, j]=(f[i+1:i+1+g_.shape[0],j+1:j+1+g_.shape[1]] *g).sum()
            
    print "f=\n", f
    print "g=\n", g
    print "h=\n", h
    io.imshow(h)
    return h
    
            

if __name__ == "__main__":
    f_shape, g_shape = 10, 3
    f_, g_ = numpy.arange(f_shape ), numpy.arange(g_shape)
    f = [f_+i for i in xrange(f_shape)]
    g = [g_+i*5 for i in xrange(g_shape)]
    
    f = numpy.vstack(f) 
    g = numpy.vstack(g)
    f = data.camera()
    io.imshow(f)
    conv2d_v0010(f, g)

 

2017-05-09 20:51:42 fzk118gd147 阅读数 272
  • 卷积网络中特征的N种使用方式

    卷积神经网络视频教程,该课程以卷积神经网络处理图像为例,探讨了卷积得到的特征图(feature maps)的特性和运用,展示了特征在数据重建、图像生成、对抗样本、相似图查找等等领域的广泛运用,并辅以代码示例,帮助学员更好地理解深度学习和传统机器学习,乃至传统计算机视觉的关系。

    1609 人正在学习 去看看 CSDN讲师


假设g = [g1 g2 g3               f = [f1 f2 f3  

g4 g5 g6                     f4 f5 f6

g7 g8 g9];                   f7 f8 f9];

即:

滤波为:乘加操作;

滤波为:h[m,n] = f1g1 + f2g2 + ...... + f9g9;

卷积为:对g倒序后乘加:

卷积:h[m,n] = f1g9 + f2g8 + ...... + f9g1;


没有更多推荐了,返回首页