美文网首页
opencv各种卷积核滤波器

opencv各种卷积核滤波器

作者: 原上的小木屋 | 来源:发表于2020-05-26 23:15 被阅读0次

    高斯滤波

    • 使图像平滑,可以用来去除噪声。高斯滤波器将中心像素周围的像素按照高斯分布加权平均进行平滑化。
    def gaussian_filter(img, K_size=3, sigma=1.3):
        if len(img.shape) == 3:
            H, W, C = img.shape
        else:
            img = np.expand_dims(img, axis=-1)
            H, W, C = img.shape
        print(H,W,C)
        ## Zero padding
        pad = K_size // 2此处是为后面构造一个将整个图像包裹进去的面做准备 注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2, C), dtype=np.float)//out将img整个包进去,外面还裹着一半的k_size层
        print(out)
        out[pad: pad + H, pad: pad + W] = img.copy().astype(np.float)//out内层与img完全一样,外层为0
        print(out)
        ## prepare Kernel
        K = np.zeros((K_size, K_size), dtype=np.float)//构造卷积核
        for x in range(-pad, -pad + K_size):
            for y in range(-pad, -pad + K_size):
                K[y + pad, x + pad] = np.exp(-(x ** 2 + y ** 2) / (2 * (sigma ** 2)))
        K /= (2 * np.pi * sigma * sigma)
        K /= K.sum()//卷积核归一化
        tmp = out.copy()
    
        # filtering
        for y in range(H):
            for x in range(W):
                for c in range(C):
                    out[pad + y, pad + x, c] = np.sum(K * tmp[y: y + K_size, x: x + K_size, c])//核心运算,重新计算out与img对应位置的加权像素值
        out = np.clip(out, 0, 255)
        out = out[pad: pad + H, pad: pad + W].astype(np.uint8)//重新将out外层的0去掉
        return out
    

    中值滤波

    • 这种滤波器用滤波器范围内像素点的中值进行滤波,效果甚至比高斯滤波器效果更加显著。逐值进行的运算,开销极大
    //此处代码与上述高斯卷积核对应起来看
    def median_filter(img, K_size=3):
        H, W, C = img.shape
        ## Zero padding
        pad = K_size // 2   注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad*2, W + pad*2, C), dtype=np.float)//同样是生成一个长宽均比img大一个K_size的黑色图像
        out[pad:pad+H, pad:pad+W] = img.copy().astype(np.float)//同样是out与img上下对应填值
        tmp = out.copy()
        # filtering
        for y in range(H):
            for x in range(W):
                for c in range(C):
                    out[pad+y, pad+x, c] = np.median(tmp[y:y+K_size, x:x+K_size, c])//取中值进行填充,这也就没啥加权的概念了
        out = out[pad:pad+H, pad:pad+W].astype(np.uint8)//同样截取原来的尺寸
        return out
    

    均值滤波

    • 与中值滤波基本相同
    def mean_filter(img, K_size=3):
        H, W, C = img.shape
        # zero padding
        pad = K_size // 2   注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2, C), dtype=np.float)
        out[pad: pad + H, pad: pad + W] = img.copy().astype(np.float)
        tmp = out.copy()
        # filtering
        for y in range(H):
            for x in range(W):
                for c in range(C):
                    out[pad + y, pad + x, c] = np.mean(tmp[y: y + K_size, x: x + K_size, c])//只有这里和中值滤波有一点小小的差别
        out = out[pad: pad + H, pad: pad + W].astype(np.uint8)
        return out
    

    Motion Filter 对角线滤波

    • 与高斯滤波不同的是,高斯滤波器形如[[1,2,1],[2,4,2],[1,2,1]],而motion filter滤波器形如[[0,0,1/3],[0,1/3,0],[1/3,0,0]]处于对角线上的像素加权
    def motion_filter(img, K_size=3):
        H, W, C = img.shape
        # Kernel,构造卷积核
        K = np.diag( [1] * K_size ).astype(np.float)
        K /= K_size
        # zero padding
        pad = K_size // 2   注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2, C), dtype=np.float)
        out[pad: pad + H, pad: pad + W] = img.copy().astype(np.float)
        tmp = out.copy()
        # filtering
        for y in range(H):
            for x in range(W):
                for c in range(C):
                    out[pad + y, pad + x, c] = np.sum(K * tmp[y: y + K_size, x: x + K_size, c])
        out = out[pad: pad + H, pad: pad + W].astype(np.uint8)
        return out
    

    MAX-MIN滤波器

    • 使用网格内像素的最大值和最小值的差值对网格内像素重新赋值。通常用于边缘检测。
    • 边缘检测用于检测图像中的线。像这样提取图像中的信息的操作被称为特征提取。
    • 边缘检测通常在灰度图像上进行。
    def max_min_filter(img, K_size=3):
        H, W = img.shape
    
        # Zero padding
        pad = K_size // 2    注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)
        out[pad: pad + H, pad: pad + W] = gray.copy().astype(np.float)
        tmp = out.copy()
    
        # filtering
        for y in range(H):
            for x in range(W):
                out[pad + y, pad + x] = np.max(tmp[y: y + K_size, x: x + K_size]) - \
                    np.min(tmp[y: y + K_size, x: x + K_size])
        out = out[pad: pad + H, pad: pad + W].astype(np.uint8)
        return out
    

    差分滤波器

    • 差分滤波器对图像亮度急剧变化的边缘有提取效果,可以获得邻接像素的差值
    • 纵向 K=[[0, -1, 0], [0, 1, 0], [0, 0, 0]],可用来检测纵向的分界线
    • 横向 K=[[0, 0, 0], [-1, 1, 0], [0, 0, 0]],可用来检测横向的分界线
    def different_filter(img, K_size=3):
        H, W, C = img.shape
        # Zero padding
        pad = K_size // 2   注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)
        out[pad: pad + H, pad: pad + W] = gray.copy().astype(np.float)
        tmp = out.copy()
        out_v = out.copy()
        out_h = out.copy()
        # vertical kernel
        Kv = [[0., -1., 0.],[0., 1., 0.],[0., 0., 0.]]
        # horizontal kernel
        Kh = [[0., 0., 0.],[-1., 1., 0.], [0., 0., 0.]]
        # filtering
        for y in range(H):
            for x in range(W):
                out_v[pad + y, pad + x] = np.sum(Kv * (tmp[y: y + K_size, x: x + K_size]))
                out_h[pad + y, pad + x] = np.sum(Kh * (tmp[y: y + K_size, x: x + K_size]))
        out_v = np.clip(out_v, 0, 255)
        out_h = np.clip(out_h, 0, 255)
        out_v = out_v[pad: pad + H, pad: pad + W].astype(np.uint8)
        out_h = out_h[pad: pad + H, pad: pad + W].astype(np.uint8)
        return out_v, out_h
    

    Sobel滤波器

    • Sobel滤波器可以提取特定方向(纵向或横向)的边缘,与上述的差分滤波器相似
    • 纵向 K=[[1, 2, 1], [0, 0, 0], [-1, -2, -1]],可用来检测纵向的分界线
    • 横向 K=[[1, 0, -1], [2, 0, -2], [1, 0, -1]],可用来检测横向的分界线
    def sobel_filter(img, K_size=3):
        if len(img.shape) == 3:
            H, W, C = img.shape
        else:
            img = np.expand_dims(img, axis=-1)
            H, W, C = img.shape
        # Zero padding
        pad = K_size // 2   注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)
        out[pad: pad + H, pad: pad + W] = gray.copy().astype(np.float)
        tmp = out.copy()
        out_v = out.copy()
        out_h = out.copy()
        ## Sobel vertical
        Kv = [[1., 2., 1.],[0., 0., 0.], [-1., -2., -1.]]
        ## Sobel horizontal
        Kh = [[1., 0., -1.],[2., 0., -2.],[1., 0., -1.]]
        # filtering
        for y in range(H):
            for x in range(W):
                out_v[pad + y, pad + x] = np.sum(Kv * (tmp[y: y + K_size, x: x + K_size]))
                out_h[pad + y, pad + x] = np.sum(Kh * (tmp[y: y + K_size, x: x + K_size]))
        out_v = np.clip(out_v, 0, 255)
        out_h = np.clip(out_h, 0, 255)
        out_v = out_v[pad: pad + H, pad: pad + W].astype(np.uint8)
        out_h = out_h[pad: pad + H, pad: pad + W].astype(np.uint8)
        return out_v, out_h
    

    Prewitt滤波器

    • 与上述差分滤波器和Sobel滤波器一样,Prewitt滤波器也是用于边缘检测的一种滤波器
    • 纵向 K=[[-1, -1, -1], [0, 0, 0], [1, 2, 1]],可用来检测纵向的分界线
    • 横向 K=[[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]],可用来检测横向的分界线
    def prewitt_filter(img, K_size=3):
        if len(img.shape) == 3:
            H, W, C = img.shape
        else:
            img = np.expand_dims(img, axis=-1)
            H, W, C = img.shape
        # Zero padding
        pad = K_size // 2    注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)
        out[pad: pad + H, pad: pad + W] = gray.copy().astype(np.float)
        tmp = out.copy()
        out_v = out.copy()
        out_h = out.copy()
        ## prewitt vertical kernel
        Kv = [[-1., -1., -1.],[0., 0., 0.], [1., 1., 1.]]
        ## prewitt horizontal kernel
        Kh = [[-1., 0., 1.],[-1., 0., 1.],[-1., 0., 1.]]
        # filtering
        for y in range(H):
            for x in range(W):
                out_v[pad + y, pad + x] = np.sum(Kv * (tmp[y: y + K_size, x: x + K_size]))
                out_h[pad + y, pad + x] = np.sum(Kh * (tmp[y: y + K_size, x: x + K_size]))
        out_v = np.clip(out_v, 0, 255)
        out_h = np.clip(out_h, 0, 255)
        out_v = out_v[pad: pad + H, pad: pad + W].astype(np.uint8)
        out_h = out_h[pad: pad + H, pad: pad + W].astype(np.uint8)
        return out_v, out_h
    

    Laplacian滤波器

    • Laplacian滤波器是对图像亮度进行二次微分从而检测边缘的滤波器
    • Ix(x,y)=[I(x+1,y)−I(x,y)]/[(x+1)−x]=I(x+1,y)−I(x,y)
    • 同理Iy(x,y)=[I(x,y+1)−I(x,y)]/[(y+1)−y]=I(x,y+1)−I(x,y)
    • 同理可得Ixx(x,y)=[Ix(x,y)−Ix(x-1,y)]/[(x−(x-1)]=Ix(x,y)−Ix(x-1,y)=I(x+1,y)−I(x,y)-(I(x,y)−I(x-1,y))=I(x+1,y)-2I(x,y)+I(x-1,y)
    • 同理可得Ixx(x,y)=I(x,y+1)-2I(x,y)+I(x,y-1)
    • 因此拉普拉斯表达式为Ixx(x,y)+Iyy(x,y)=I(x+1,y)-2I(x,y)+I(x-1,y)+I(x,y+1)-2I(x,y)+I(x,y-1)=I(x+1,y)+I(x-1,y)+I(x,y+1)-4I(x,y)+I(x,y-1)
    • 因此拉普拉斯卷积核为K=[[0, 1, 0], [1, -4, 1], [0, 1, 0] ]
    def laplacian_filter(img, K_size=3):
        H, W, C = img.shape
        # zero padding
        pad = K_size // 2    注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)
        out[pad: pad + H, pad: pad + W] = gray.copy().astype(np.float)
        tmp = out.copy()
        # laplacian kernle
        K = [[0., 1., 0.],[1., -4., 1.], [0., 1., 0.]]
        # filtering
        for y in range(H):
            for x in range(W):
                out[pad + y, pad + x] = np.sum(K * (tmp[y: y + K_size, x: x + K_size]))
        out = np.clip(out, 0, 255)
        out = out[pad: pad + H, pad: pad + W].astype(np.uint8)
        return out
    

    Emboss滤波器

    • Emboss滤波器可以使物体轮廓更加清晰
    def emboss_filter(img, K_size=3):
        H, W, C = img.shape
        # zero padding
        pad = K_size // 2   注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)
        out[pad: pad + H, pad: pad + W] = gray.copy().astype(np.float)
        tmp = out.copy()
        # emboss kernel
        K = [[-2., -1., 0.],[-1., 1., 1.], [0., 1., 2.]]
        # filtering
        for y in range(H):
            for x in range(W):
                out[pad + y, pad + x] = np.sum(K * (tmp[y: y + K_size, x: x + K_size]))
        out = np.clip(out, 0, 255)
        out = out[pad: pad + H, pad: pad + W].astype(np.uint8)
        return out
    

    LoG滤波器

    • LoG即高斯-拉普拉斯(Laplacian of Gaussian)的缩写,使用高斯滤波器使图像平滑化之后再使用拉普拉斯滤波器使图像的轮廓更加清晰。
    //log滤波器公式与高斯滤波器公式较为相似,为高斯滤波器和拉普拉斯滤波器的组合,具体见代码公式
    def LoG_filter(img, K_size=5, sigma=3):
        H, W, C = img.shape
        # zero padding
        pad = K_size // 2     注意啊,前面的灰色//2可不是注释,这是python3的真除法的写法,意思是取商
        out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)
        out[pad: pad + H, pad: pad + W] = gray.copy().astype(np.float)
        tmp = out.copy()
        # LoG Kernel
        K = np.zeros((K_size, K_size), dtype=np.float)
        for x in range(-pad, -pad + K_size):
            for y in range(-pad, -pad + K_size):
                K[y + pad, x + pad] = (x ** 2 + y ** 2 - sigma ** 2) * np.exp( -(x ** 2 + y ** 2) / (2 * (sigma ** 2)))
        K /= (2 * np.pi * (sigma ** 6))
        K /= K.sum()
        # filtering
        for y in range(H):
            for x in range(W):
                out[pad + y, pad + x] = np.sum(K * tmp[y: y + K_size, x: x + K_size])
        out = np.clip(out, 0, 255)
        out = out[pad: pad + H, pad: pad + W].astype(np.uint8)
        return out
    

    相关文章

      网友评论

          本文标题:opencv各种卷积核滤波器

          本文链接:https://www.haomeiwen.com/subject/gqlbahtx.html