OpenCV筆記(4)(直方圖、傅里葉變換、高低通濾波)


一、直方圖

用於統計圖片中各像素值:

# 畫一個圖像各通道的直方圖
def draw_hist(img):
    color = ('b', 'g', 'r')
    for i, col in enumerate(color):
        hist = cv.calcHist([img], [i], None, [256], [0, 256])
        # print(hist.shape)
        plt.plot(hist, color=col)
        plt.xlim([0, 256])
    plt.show()

計算直方圖時使用mask:

# 使用掩碼
def draw_hist_with_mask(img):
    mask = np.zeros(img.shape[:2], np.uint8)
    mask[50:200, 100:350] = 255
    cv.imshow('mask', mask)
    
    # 將掩碼轉換為bool類型
    bi_mask = (mask == 255)
    # 將掩碼作用於原圖上
    cv.imshow('masked img', img * bi_mask[:, :, np.newaxis])

    color = ('b', 'g', 'r')
    for i, col in enumerate(color):
        # 使用mask,只計算mask中的像素的直方圖
        hist = cv.calcHist([img], [i], mask, [256], [0, 256])
        # print(hist.shape)
        plt.plot(hist, color=col)
        plt.xlim([0, 256])
    plt.show()

 直方圖均衡:

# 直方圖均衡
def equal_hist(image):
    image = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    equ = cv.equalizeHist(image)
    plt.hist(image.ravel(), 256)
    plt.hist(equ.ravel(), 256)
    plt.show()

圖中藍色部分為原圖的直方圖,橙色部分為均衡后的直方圖,均衡前后的效果如下圖所示:

CLAHE(限制對比度自適應直方圖均衡):

# 自適應直方圖均衡化
def CLAHE_proc(image):
    'CLAHE:限制對比度自適應直方圖均衡'
    # 先轉換為灰度圖像
    image = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    # 創建CLAHE分塊
    clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
    # 執行CLAHE均衡化
    res_clahe = clahe.apply(image)
    cv.imshow('res_clahe', res_clahe)
    
    # 對比普通均衡化
    equ = cv.equalizeHist(image)
    cv.imshow('equ', equ)

左圖為CLAHE效果,右圖為普通均衡化效果。CLAHE可以減少過爆或過暗,因為他不是基於整張圖片來均衡。

二、傅里葉變換

通過傅里葉變換,我們可以將圖像從空間域轉換到頻率域,然后在頻率域中對其進行濾波,主要有高通濾波和低通濾波。

概念:

  高頻:變化劇烈的灰度分量,例如邊界

  低頻:變化緩慢的灰度分量

  高通濾波器:只保留高頻,過濾出邊界

  低通濾波器:只保留低頻,使圖像變模糊

 

空間域轉頻率域:

# 將圖像從空間域轉換為頻率域
def fourier_trans(img):
    # 使用灰度圖像
    img = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    # uint8轉換為float32
    img_float32 = np.float32(img)
    # 傅里葉轉換為復數
    dft = cv.dft(img_float32, flags=cv.DFT_COMPLEX_OUTPUT)
    # 將低頻從左上角轉換到中心
    dft_shift = np.fft.fftshift(dft)
    # 轉換為可以顯示的圖片(頻譜圖)
    magnitude_spectrum = 20 * np.log(cv.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))

    # 使用plt展示原圖的灰度圖
    plt.subplot(121)
    plt.imshow(img, cmap='gray')
    plt.title('Input Image')
    plt.xticks([])
    plt.yticks([])
    # 展示頻譜圖
    plt.subplot(122)
    plt.imshow(magnitude_spectrum, cmap='gray')
    plt.title('magnitude_spectrum')
    plt.xticks([])
    plt.yticks([])
    plt.show()

頻率域轉回空間域(並實驗低通和高通濾波):

低頻濾波:

# 從頻率域轉換回空間域(並使用低通濾波)
def fourier_trans_back(img):
    # 使用灰度圖像
    img = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    # uint8轉換為float32
    img_float32 = np.float32(img)
    # 傅里葉轉換為復數
    dft = cv.dft(img_float32, flags=cv.DFT_COMPLEX_OUTPUT)
    # 將低頻從左上角轉換到中心
    dft_shift = np.fft.fftshift(dft)

    # 在這里進行低通濾波
    rows, cols = img.shape
    c_row, c_col = int(rows / 2), int(cols / 2)
    mask_low = np.zeros_like(dft_shift, np.uint8)
    mask_low[c_row - 30:c_row + 30, c_col - 50:c_col + 50] = 1
    # 使用低通濾波
    fshift_low = dft_shift * mask_low
    # 轉換為可以顯示的圖片(fshift_low),fshift_low中包含實部和虛部
    magnitude_spectrum_low = 20 * np.log(cv.magnitude(fshift_low[:, :, 0], fshift_low[:, :, 1]))

    f_ishift_low = np.fft.ifftshift(fshift_low)
    img_back_low = cv.idft(f_ishift_low)
    img_back_low = cv.magnitude(img_back_low[:, :, 0], img_back_low[:, :, 1])

    # 使用plt低通濾波后的圖像
    plt.subplot(121)
    plt.imshow(img_back_low, cmap='gray')
    plt.title('Output Image')
    plt.xticks([])
    plt.yticks([])
    # 展示低通濾波后的頻譜圖
    plt.subplot(122)
    plt.imshow(magnitude_spectrum_low, cmap='gray')
    plt.title('magnitude_spectrum')
    plt.xticks([])
    plt.yticks([])
    plt.show()

高頻濾波:

# 從頻率域轉換回空間域(並使用高通濾波)
def fourier_trans_back(img):
    # 使用灰度圖像
    img = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    # uint8轉換為float32
    img_float32 = np.float32(img)
    # 傅里葉轉換為復數
    dft = cv.dft(img_float32, flags=cv.DFT_COMPLEX_OUTPUT)
    # 將低頻從左上角轉換到中心
    dft_shift = np.fft.fftshift(dft)

    # 在這里進行高通濾波
    rows, cols = img.shape
    c_row, c_col = int(rows / 2), int(cols / 2)
    mask_high = np.ones_like(dft_shift, np.uint8)
    mask_high[c_row - 30:c_row + 30, c_col - 50:c_col + 50] = 0
    # 使用高通濾波
    fshift_high = dft_shift * mask_high
    # 轉換為可以顯示的圖片(fshift_high),fshift_high中包含實部和虛部
    magnitude_spectrum_high = 20 * np.log(cv.magnitude(fshift_high[:, :, 0], fshift_high[:, :, 1]))

    f_ishift_high = np.fft.ifftshift(fshift_high)
    img_back_high = cv.idft(f_ishift_high)
    img_back_high = cv.magnitude(img_back_high[:, :, 0], img_back_high[:, :, 1])

    # 使用plt高通濾波后的圖像
    plt.subplot(121)
    plt.imshow(img_back_high, cmap='gray')
    plt.title('Output Image')
    plt.xticks([])
    plt.yticks([])
    # 展示高通濾波后的頻譜圖
    plt.subplot(122)
    plt.imshow(magnitude_spectrum_high, cmap='gray')
    plt.title('magnitude_spectrum')
    plt.xticks([])
    plt.yticks([])
    plt.show()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM