图像平滑(二)

中值平滑

种植平滑,类似于卷积,也是一种邻域运算,但计算的不是加权求和,而是对邻域中像素点按灰度值进行排序,然后选择该组中的中值作为输出的灰度值。

中值滤波最重要的能力是去除椒盐噪声。

椒盐噪声是指图像在传输系统中由于解码误差等原因,导致图像中出现孤立的白点或黑点。

import numpy as np
import random
def salt(image,number):
    """
    模拟添加椒盐噪声
    """
    # 图像的高、宽
    rows,cols = image.shape
    # 加入椒盐噪声后的图像
    salt_image = np.copy(image)
    for i in range(number):
        rand_r = random.randint(0,rows-1)
        rand_c = random.randint(0,cols-1)
        salt_image[rand_r][rand_c] = 255
    return salt_image

def median_blur(image,win_size):
    rows,cols = image.shape
    win_h,win_w = win_size
    half_win_h = (win_h-1)/2
    half_win_w = (win_w-1)/2
    median_blur_image = np.zeros(image.shape,image.dtype)
    for r in range(rows):
        for c in range(cols):
            # 判断边界
            rTop = 0 if r-half_win_h<0 else r-half_win_h
            rBottom = rows-1 ifr+half_win_h>rows-1 else r+half_win_h
            cLeft = 0 if c-half_win_w<0 else c-half_win_w
            cRight = cols-1 if c+half_win_w>cols-1 else c+half_win_w
            # 取邻域
            region = image[rTop:rBottom+1,cLeft:cRight+1]
            # 求中值
            median_blur_image[r][c] = np.median(region)
    return median_blur_image

双边滤波

均值平滑和高斯平滑本质上都是计算每个位置的邻域加权和作为该位置的输出。

双边滤波是根据每个位置的邻域,对该位置构建不同的权重模板,构建过程如下:

第一步:构建winH×winW的空间距离权重模板。

c l o s e n e s s W e i g h t ( h , w ) = e x p ( − ( h − w i n H − 1 2 ) 2 + ( w − w i n W − 1 2 ) 2 2 σ 1 2 ) closenessWeight(h,w) = exp(-\frac{(h-\frac{winH-1}{2})^2+(w-\frac{winW-1}{2})^2}{2\sigma_{1}^{2}}) closenessWeight(h,w)=exp(2σ12(h2winH1)2+(w2winW1)2)

第二步:构建winH×winW的相似性权重模板,是通过(r,c)处的值与其邻域值的差值的指数衡量的。
s i m i l a r i t y W e i g h t ( h , w ) = e x p ( − ∣ ∣ I ( r , c ) − I ( r + ( h − w i n H − 1 2 ) , c + ( w − w i n W − 1 2 ) ∣ ∣ 2 2 σ 2 2 ) similarityWeight(h,w) = exp(-\frac{||I(r,c)-I(r+(h-\frac{winH-1}{2}),c+(w-\frac{winW-1}{2})||^2}{2\sigma_{2}^{2}}) similarityWeight(h,w)=exp(2σ22I(r,c)I(r+(h2winH1),c+(w2winW1)2)
第三步:将 c l o s e n e s s W e i g h t closenessWeight closenessWeight s i m i l a r i t y W e i g h t similarityWeight similarityWeight 的对应位置相乘(即点乘)

第四步:归一化,得到该位置权重模板

第五步:将得到的权重模板和该位置邻域的对应位置相乘,然后求和得到该位置的输出值。

import numpy as np
import cv2 as cv
import math

def get_closenessWeight(sigma_g,H,W):
    """
    构建空间距离权重模板
    """
    r,c = np.mgrid[0:H:1,0:W:1]
    r-=(h-1)/2
    c-=(w-1)/2
    closenessWeight = np.exp(-0.5*(np.power(r,2)+np.power(c,2)/math.pow(sigma_g,2)))
    return closenessWeight
def bfltGray(I,H,W,sigma_g,sigma_d):
    """
    sigma_g: 代表空间距离权重模板的标准差
    sigma_d:代表相似性权重模板的标准差
    令sigma_g>1,sigma_d<1效果会比较好
    """
    # 构建空间距离模板
    closenessWeight = get_closenessWeight(sigma_g,H,W)
    # 模板的中心位置
    cH = (H-1)/2
    cW = (W-1)/2
    # 图像矩阵的行数和列数
    rows,cols = I.shape
    # 双边滤波后的结果
    bfltGrayImage = np.zeros(I.shape,np.float32)
    for r in range(rows):
        for c in range(cols):
            piexl = T[r][c]
            # 判断边界
            rTop = 0 if r-cH<0 else r-cH
            rBottom = rows-1 if r+cH >rows-1 else r+cH
            cLeft = 0 if c-cW<0 else c-cW
            cRight = cols-1 if c+cW>cols-1 else c+cW
            # 权重模板作用的区域
            region = I[rTop:rBottom+1,cLeft:cRight+1]
            # 构建灰度值相似性的权重因子
            similarityWeightTemp = np.exp(-0.5*np.power(region-piexl,2.0)/math.pow(sigma_d,2))
            closenessWeightTemp = closenessWeight[rTop-r+cH:rBottom-r+cH+1,cLeft-c+cW:cRight-c+cW+1]
            # 权重模板相乘
            weightTemp = similarityWeightTemp*closenessWeightTemp
            # 归一化权重模板
            weightTemp = weightTemp/np.sum(weightTemp)
            # 权重模板和对应的邻域值相乘求和
            bfltGrayImage[r][c] = np.sum(region*weightTemp)
    return bfltGrayImage

联合双边滤波

联合双边滤波与双边滤波类似,在双边滤波的基础上做了些改动,两者的区别在于双边滤波是在原灰度图的基础上构建的相似性权重模板,而联合双边滤波是在原灰度图经过高斯平滑后的图像的基础上构建的相似性权重模板,其他都是相同的。

注意:最终的权重模板是与原图(不是高斯平滑后的结果)在该位置的邻域对应位置积的和作为输出值。

import numpy as np
import cv2 as cv
import math

def get_closenessWeight(sigma_g,H,W):
    """
    构建空间距离权重模板
    """
    r,c = np.mgrid[0:H:1,0:W:1]
    r-=(h-1)/2
    c-=(w-1)/2
    closenessWeight = np.exp(-0.5*(np.power(r,2)+np.power(c,2)/math.pow(sigma_g,2)))
    return closenessWeight

def jointBLF(I,H,W,sigma_g,sigma_d,borderType=cv.BORDER_DEFAULT):
    """
    sigma_g: 代表空间距离权重模板的标准差
    sigma_d:代表相似性权重模板的标准差
    令sigma_g>1,sigma_d<1效果会比较好
    """
    # 构建空间距离模板
    closenessWeight = get_closenessWeight(sigma_g,H,W)
    # 对I进行高斯平滑
    Ig = cv.GaussianBlur(I,(W,H),sigma_g)
    # 模板的中心位置
    cH = (H-1)/2
    cW = (W-1)/2
    # 对原图和高斯平滑后的结果扩充边界
    Ip = cv.copyMakeBorder(I,cH,cH,cW,cW,borderType)
    Igp = cv.copyMakeBorder(Ig,cH,cH,cW,cW,borderType)
    # 图像矩阵的行数和列数
    rows,cols = I.shape
    i,j =0,0
    # 联合双边滤波后的结果
    jblf = np.zeros(I.shape,np.float64)
    for r in range(cH,cH+rows,1):
        for c in range(cW,cW+cols,1):
            piexl = T[r][c]
            # 当前位置的邻域
            rTop,rBottom = r-cH,r+cH
            cLeft,cRight = c-cW,c+cW
            # 权重模板作用的区域
            region = Igp[rTop:rBottom+1,cLeft:cRight+1]
            # 构建灰度值相似性的权重因子
            similarityWeightTemp = np.exp(-0.5*np.power(region-piexl,2.0)/math.pow(sigma_d,2))
            # 权重模板相乘
            weightTemp = similarityWeightTemp*closenessWeight
            # 归一化权重模板
            weightTemp = weightTemp/np.sum(weightTemp)
            # 权重模板和对应的邻域值相乘求和
            jblf[r][c] = np.sum(Ip[rTop:rBottom+1,cLeft:cRight+1]*weightTemp)
            j+=1
        j=0
        i+=1
    return jblf

注:文中所书内容来自张平的《opencv算法精解》,作为自己所学的输出,如若撰写过程中出现错误欢迎指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值