天天看点

图像卷积及其Python实现

  • 卷积简介

卷积(Convolution)是数学上的一种积分变换,主要作用是为了获取某个函数的局部信息,被广泛应用于信号、图像和机器学习等领域。本文给出了图像卷积的Python实现。

  • 算法实现
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
class ImageCov( object ):
    #image   :原图像
    #convImg :卷积图像
    #mfilter :滤波器
    def __init__( self, filename, filterArr ):
        self.image = np.array( Image.open( filename ) )
        [ mI, nI ] = np.shape( self.image )
        self.convImg = np.zeros( (mI, nI) )
        self.mfilter = filterArr
    #显示图像
    def showImg( self ):
         plt.figure(  )
         plt.imshow( self.image )
         plt.axis( 'off' )
         
         plt.figure(  )
         plt.imshow( self.convImg )
         plt.axis( 'off' )
    #计算两个矩阵的内积
    def Dot2D( self, a, b ):
        c = np.multiply( a, b )
        d = np.sum( c )
        if d < 0:
            d = -d
        elif d > 255:
            d = 255
        return d
    
    #计算二维滤波器的大小和半径
    def FilterRadius( self ): 
        [mF, nF] = np.shape( self.mfilter )
        half_mF = int( mF / 2 )
        half_nF = int( nF / 2 )
        return mF, nF, half_mF, half_nF
    
    #根据滤波器的大小对原始图像进行扩充,以确保卷积之后的图像与原图像大小相同
    #fWidth, fHeight, fHalfWidht, fHalfHeight:滤波器的:宽、高、宽半径、高半径
    #tempImage:扩充后的图像
    def  ImageExtension( self, fWidth, fHeight, fHalfWidht, fHalfHeight ):
        [mI, nI] = np.shape( self.image )
        if fHeight % 2 > 0 :
            fHeight = fHeight - 1
        if fWidth % 2  > 0:
            fWidth = fWidth - 1

        tempImage = np.zeros( (mI + fHeight, nI + fWidth) )
        aUp       = np.zeros( (fHalfHeight, nI + fWidth) )  #上侧和下侧增加部分的数据
        aLeft     = np.zeros( (mI, fHalfWidht) )            #左侧和右侧增加部分的数据
        aMiddle   = np.hstack( (aLeft, self.image, aLeft) )    #中间部分的数据
        tempImage = np.vstack( (aUp, aMiddle, aUp) )      #扩展之后的图像数据

        return tempImage


    def ImageConvolution( self ):
        [ mI, nI ] = np.shape( self.image )
        [ mF, nF ] = np.shape( self.mfilter )
        
        if mF % 2 > 0:
            tempmI = mI - 1
        else:
            tempmI = mI
        if nF % 2 > 0:
            tempnI = nI - 1
        else:
            tempnI = nI
        
        #依次截取与滤波器大小相同的图像块进行内积运算
        for i in range( tempmI - 1 ):
            for j in range( tempnI - 1 ):
                localImage = np.zeros( (mF, nF) )
                for it in range( mF ):
                    for jt in range( nF ):
                        localImage[it][jt] = self.image[i+it][j+jt]
                self.convImg[i][j] = self.Dot2D( localImage, self.mfilter )


def main():
    filter1 = [ [-1, -2, -1], [0, 0, 0], [1, 2, 1] ]
    img1 = ImageCov ( 'lena.bmp', filter1 ) 
    img1.ImageConvolution()
    img1.showImg()
    
    filter2 = [ [-1, 0, 1], [-2, 0, 2], [-1, 0, 1] ]
    img2 = ImageCov ( 'lena.bmp', filter2 ) 
    img2.ImageConvolution()
    img2.showImg()
    
    filter3 = [ [1, -1], [1, -1] ]
    img3 = ImageCov ( 'lena.bmp', filter3 ) 
    img3.ImageConvolution()
    img3.showImg()
    
    filter4 = [ [1, 1], [-1, -1] ]
    img4 = ImageCov ( 'lena.bmp', filter4 ) 
    img4.ImageConvolution()
    img4.showImg()

if __name__ == '__main__':
    main()
           

作者:YangYF

继续阅读