python opencv 高斯平滑

python opencv 高斯平滑

import cv2
import numpy as np
from datetime import datetime
from scipy import signal #二维离散卷积运算
import math
#full卷积,valid卷积,
#same卷积 假设将K f lip(K逆时针翻转180度)的左上角即第0行第0列作为锚点的位置
def printWithdate(str):
    time2 = datetime.now()
    time2a = time2.strftime("%Y-%m-%d %H:%M:%S")
    print(time2a+' '+str)
def getGaussKernel(sigma,H,W):
    '''
    三个步骤构建高斯卷积算子,代码实现。 API实现:cv2.getGaussianKernel(3,2,cv2.CV_64F)
    '''
    #1,构建高斯矩阵
    gaussMatrix = np.zeros([H,W],np.float32)
    #得到中心点的位置
    cH =(H-1)/2
    cW = (W-1)/2
    #计算gauss(sigma,r,c)
    for r in range(H):
        for c in range(W):
            norm2 = math.pow(r-cH,2) + math.pow(c-cW,2)
            gaussMatrix[r][c] = math.exp(-norm2/(2*math.pow(sigma,2)))
    #2:j计算高斯矩阵的和
    sumGM = np.sum(gaussMatrix)
    #3:归一化
    gaussKernel = gaussMatrix/sumGM
    return gaussKernel
def GaussBlur(image,sigma,H,W,_boundary = 'fill',_fillvalue =0):
    '''
    代码实现高斯平滑步骤;
    码实现返回的卷积结果的数据类型是浮点型,假设输入的图像是8位图,进行
    高斯卷积后,需要将结果用命令asty pe(numpy.uint8)进行数据类型转换,从而进行灰
    度级显示,否则用imshow显示时为黑色
    
    也可以用API实现
    '''
    #构建水平方向上的高斯卷积核
    gaussKernel_x = cv2.getGaussianKernel(sigma,W,cv2.CV_64F)
    #转置
    #W 水平,width
    gaussKernel_x = np.transpose(gaussKernel_x) # 介绍:https://www.cnblogs.com/txwtech/p/18051127
    #图像矩阵与水平高斯核卷积
    img_gaussBlur_x = signal.convolve2d(image,gaussKernel_x,mode='same',
                                    boundary= _boundary,fillvalue=_fillvalue)
    #构建垂直方向上的高斯卷积核
    gaussKernel_y = cv2.getGaussianKernel(sigma,H,cv2.CV_64F)
    #与垂直方向上的高斯核卷积核
    img_gaussBlur_xy = signal.convolve2d(img_gaussBlur_x,gaussKernel_y,mode='same',
                                         boundary=_boundary,fillvalue=_fillvalue)
    return img_gaussBlur_xy

if __name__=="__main__":
    printWithdate("hello")
    img = cv2.imread(r'dayan.png',cv2.IMREAD_GRAYSCALE)
    # cv2.imshow('img',img)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    mat_i = np.array([[1,2],[3,4]],np.float32)
    H1,W1 = mat_i.shape[:2]
    #核卷积
    K_core = np.array([[-1,-2],[2,1]],np.float32)
    H2,W2 = K_core.shape[:2]
    #计算full卷积
    c_full = signal.convolve2d(mat_i,K_core,mode='full')
    #指定锚点位置
    kr,kc = 0,0
    #根据锚点的位置,从full卷积中截取得到same卷积
    c_same = c_full[H2-kr-1:H1+H2-kr-1,W2-kc-1:W1+W2-kc-1]
    print(c_same)
#可分离卷积核,在图像处理中经常使用这样的卷积核,它可以分离为一维水平方向和一维垂直方向上的卷积核
#full卷积是不满足交换律的,但是一维水平方向和一维垂直方向上的卷积核的full卷积是满足交换律的  
    #计算两个核的全卷积
    kernel1 = np.array([[1,2,3]],np.float32)
    kernel2 = np.array([[4],[5],[6]],np.float32)
    kernel_full = signal.convolve2d(kernel1,kernel2,mode='full')
    print(kernel_full)

    #API实现高斯卷积核
    gk = cv2.getGaussianKernel(3,2,cv2.CV_64F)
    print(gk)
    '''
    由于高斯卷积算子是可分离的,所以真正对图像进行高斯平滑时,可根据same卷积
    的结合律和卷积核的分离性对图像先进行一维水平方向上的高斯平滑,然后再进行一维
    垂直方向上的高斯平滑,或者反过来,先垂直后水平
    '''
    #高斯平滑
    blurImg = GaussBlur(img,5,51,51,'symm')
    #图像进行灰度级显示
    blurImg = np.round(blurImg)
    blurImg = blurImg.astype(np.uint8)
    #卷积结果的数据类型是浮点型,假设输入的图像是8位图,进行
    #高斯卷积后,需要将结果用命令asty pe(numpy.uint8)进行数据类型转换,从而进行灰
    #度级显示,否则用imshow显示时为黑色
    # cv2.imshow("GaussBlur",blurImg)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    #API实现:
    ksize = (31,31)
    dst_img = img
    sigma_x =1 #标准差
    sigma_y = 1
    #borderType : str {'fill', 'wrap', 'symm'}, optional
    dst_img = cv2.GaussianBlur(img,ksize,sigma_x,dst_img,5,borderType=2)
    cv2.imshow("api_dst_img",dst_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

 

posted @ 2024-03-04 10:36  txwtech  阅读(60)  评论(0编辑  收藏  举报