【高斯滤波】Python底层实现

 完整文件:2022_UCAS_Image_Processing/Homework1 at main · uestchjw/2022_UCAS_Image_Processing · GitHub



''' Author: UCAS-Hao Jiuwu '''
''' Date: 2022-10-1 '''

# %%
''' Problem 1 '''
import matplotlib.pyplot as plt
import numpy as np
import cv2,math
# 扫描函数
def scanLine4e(f,I,loc):
    if loc == 'row':
        return f[I,:]
    elif loc == 'column':
        return f[:,I]
    else:
        raise Exception('Wrong loc!')
# 找到中心行和中心列,扫描后可视化输出
def extract(path):
    img = cv2.imread(path,flags=0)
    rows,columns = img.shape[0],img.shape[1]
    if rows%2 == 1:
        crow_value = scanLine4e(img,math.floor(rows/2),'row')
    else:
        crow_value = (scanLine4e(img,int(rows/2)-1,'row') + scanLine4e(img,int(rows/2),'row'))/2

    if columns%2 == 1:
        ccolumn_value = scanLine4e(img,math.floor(columns/2),'column')
    else:
        ccolumn_value = (scanLine4e(img,int(columns/2)-1,'column') + scanLine4e(img,int(columns/2),'column'))/2

    # 可视化部分
    ax1 = plt.subplot(1,2,1)
    font1 = {'family':'Times New Roman','weight':'normal','size':20}
    plt.plot(np.arange(1,len(crow_value)+1),crow_value)
    plt.title('Central row',font1)

    x_kedu = ax1.get_xticklabels()
    [i.set_fontname('Times New Roman') for i in x_kedu]
    y_kedu = ax1.get_yticklabels()
    [i.set_fontname('Times New Roman') for i in y_kedu]
    plt.tick_params(labelsize = 20)

    ax2 = plt.subplot(1,2,2)
    font1 = {'family':'Times New Roman','weight':'normal','size':20}
    plt.plot(np.arange(1,len(ccolumn_value)+1),ccolumn_value)
    plt.title('Central column',font1)

    x_kedu = ax2.get_xticklabels()
    [i.set_fontname('Times New Roman') for i in x_kedu]
    y_kedu = ax2.get_yticklabels()
    [i.set_fontname('Times New Roman') for i in y_kedu]
    plt.tick_params(labelsize = 20)
    plt.show()
    return crow_value,ccolumn_value
path1 = r'C:\Users\Lenovo\Desktop\Images\cameraman.tif'
path2 = r'C:\Users\Lenovo\Desktop\Images\einstein.tif'
r1,c1 = extract(path1)
r2,c2 = extract(path2)


# %%
''' Problem 2 '''
import cv2
def rgb1gray(f,method='NTSC'):
    if method == 'average':
        gray = (f[:,:,0]+f[:,:,1]+f[:,:,2])/3
        return gray.astype(np.uint8)
    elif method == 'NTSC':
        gray = 0.1140*f[:,:,0] + 0.5870*f[:,:,1] + 0.2989*f[:,:,2]
        return gray.astype(np.uint8)
    else:
        raise Exception('Wrong method!')
path1 = r'C:\Users\Lenovo\Desktop\Images\mandril_color.tif'
path2 = r'C:\Users\Lenovo\Desktop\Images\lena512color.tiff'
img1,img2 = cv2.imread(path1),cv2.imread(path2)
gray11,gray12 = rgb1gray(img1,'average'),rgb1gray(img1)
gray21,gray22 = rgb1gray(img2,'average'),rgb1gray(img2)
img1gray,img2gray = cv2.imread(path1,flags=0),cv2.imread(path2,flags=0)
gray = [gray11,gray12,img1gray,gray21,gray22,img2gray]
kk = 1
for i in gray:
    cv2.imwrite(f'C:/Users/Lenovo/Desktop/Images/{kk}.png',i)
    kk += 1
a = (gray12 == img1gray).all()
print(a)


# %%
''' Problem 3 '''
def twodConv(f,w,o='zero'): 
    # 若是卷积,则w需要进行旋转
    w = np.fliplr(np.flipud(w))
    kerner_size = w.shape[0]
    r,c = f.shape[0],f.shape[1]
    # default: stride=1, kerner_size is odd
    p = int((kerner_size-1)/2)
    # F是padding后的矩阵
    F = np.zeros((r+2*p,c+2*p))
    F[p:p+r,p:p+c] = f
    if o == 'replicate':
        F[0:p,0:p] = np.ones((p,p))*f[0,0]
        F[0:p,-p:] = np.ones((p,p))*f[0,-1]
        F[-p:,0:p] = np.ones((p,p))*f[-1,0]
        F[-p:,-p:] = np.ones((p,p))*f[-1,-1]
        for i in range(p):
            F[i,p:p+c] = f[0,:]
            F[p:p+r,i] = f[:,0]
            F[p+r+i,p:p+c] = f[-1,:]
            F[p:p+r,p+c+i] = f[:,-1]
    g = np.zeros_like(f,dtype=float)
    for i in range(r):
        for j in range(c):
            area = F[i:i+kerner_size,j:j+kerner_size]
            g[i,j] = round(np.sum(np.multiply(area,w)))   # !!!!! 这里不能是int,因为int直接舍弃小数;也不能不用round,下面指定unint8,因为同样会舍弃小数
            if g[i,j] > 255:
                g[i,j] = 255
    return g.astype(np.uint8)

# %%
''' Problem 4 '''
def gaussKernel(sig,m=0):
    M = 1 + 2*math.ceil(3*sig)
    # 没有提供m时
    if m == 0:
        m = M
    elif m < M:
        raise Warning('The giving size of gaussKernel is too small!')
    else:
        m = m 
    l = int((m-1)/2)
    kernel = []
    for i in range(-l,l+1):
        for j in range(-l,l+1):
            kernel.append(math.exp( -(i**2+j**2)/(2*sig**2)))
    kernel /= np.sum(kernel)
    kernel = np.reshape(np.array(kernel),(m,m))
    return kernel


# %%
''' Problem 5 '''
path1 = r'C:\Users\Lenovo\Desktop\Images\cameraman.tif'
path2 = r'C:\Users\Lenovo\Desktop\Images\einstein.tif'
img1,img2 = cv2.imread(path1,flags=0),cv2.imread(path2,flags=0)
images = [img1,img2,gray12,gray22]
sigma = [1,2,3,5]
for img in images:
    for sig in sigma:
        kernel = gaussKernel(sig)
        result = twodConv(img,kernel)
        cv2.imshow('a',result)
        cv2.waitKey(0)

# sig = 1时
# M为高斯滤波器大小
M = 1 + 2*math.ceil(3*1)
i = 1
for img in images:
    kernel = gaussKernel(1)
    result1 = twodConv(img,kernel)
    result2 = cv2.GaussianBlur(img,(M,M),1,borderType=cv2.BORDER_CONSTANT)
    result3 = cv2.GaussianBlur(img,(M,M),1,borderType=cv2.BORDER_REPLICATE)
    
    # dif = abs(result1 - result2)  # 不能这样:因为uint8相减,结果只有0和255,如灰度17-16=1,但是显示出来就是255
    dif = abs(result1.astype(int) - result2.astype(int))
    dif255 = result1-result2
    # print(np.max(dif))
    cv2.imwrite(f'C:/Users/Lenovo/Desktop/Images/Problem_5/{i}_me.png',result1)
    cv2.imwrite(f'C:/Users/Lenovo/Desktop/Images/Problem_5/{i}_offical.png',result2)
    cv2.imwrite(f'C:/Users/Lenovo/Desktop/Images/Problem_5/{i}_offical_replicate.png',result3)
    cv2.imwrite(f'C:/Users/Lenovo/Desktop/Images/Problem_5/{i}_dif.png',dif)
    cv2.imwrite(f'C:/Users/Lenovo/Desktop/Images/Problem_5/{i}_dif255.png',dif255)
    i += 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值