OpenCV計算機視覺(5)——直方圖和傅里葉變換

直方圖(統計像素點值的數量)

 

 cv2.calcHist(images,channels,mask,histSize,ranges)

  • images:原圖像格式爲uint8或float32,當傳入函數時應用中括號 [] 括住表示,例如[img]
  • channels:同樣用[]括,它會告訴函數,我們統幅圖像的直方圖。如果傳入圖像是灰度圖,它的值就是 [0] 如果是彩色圖像的傳入參數可以是 [0] [1] [2] 它們分別對應着R G B
  • mask:掩膜圖像。統整幅圖像的直方圖就把它爲None。但是如果你想統圖像某一部分的直方圖,你就製作一個掩膜圖像,並使用它。
  • histSize:BIN 的數目。也應運用中括號,直方圖多少個bin
  • ranges:像素值範圍常爲[0 256]
img = cv2.imread('./cat.jpg',0)
hist = cv2.calcHist([img], [0], None,[256], [0,256])
# [img] :傳入圖像, [0]:通道數只有1個,None:不用mask掩膜,[256]:BINS,[0,256]直方圖範圍
print(hist.shape)
 
plt.hist(img.ravel(), 256) # 注意matplot是RGB的,opencv是BGR的
plt.show()
 
 
img = cv2.imread('./cat.jpg')
color = ('b','g','r')
# 遍歷顏色通道
for i ,col in enumerate(color): #col B G R
    histr = cv2.calcHist([img], [i], None,[256], [0,256])
# [img] :傳入圖像, [0]:通道數只有1個,None:不用mask掩膜,[256]:BINS,[0,256]直方圖範圍
 
    plt.hist( histr ,color = col) # 注意matplot是RGB的,opencv是BGR的
    plt.xlim([0,256])
plot.show()

mask操作

# 創建mask
mask = np.zeros(img.shape[:2], np.uint8) #np.uint8 無符號整型0-255
mask[100:300, 100:400] = 255 #mask範圍保存部分爲白色置爲255,黑色0
cv_show(mask,'mask')

img = cv2.imread('./cat.jpg',0)
cv_show(img,'img')
 
mask_img = cv2.bitwise_and(img, img, mask=mask) # 與操作
cv_show(mask_img ,'mask_img')

 
hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])

plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(mask_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)

plt.xlim([0, 256])
plt.show()

直方圖均衡化

均衡化操作,就是將灰度直方圖分佈,根據函數映射成另一種形式,累計概率是,像素所佔總體概率,再加上前面的像素的概率

累計概率*取值範圍就是映射之後的灰度值,再取整。

均衡化效果

equ = cv2.equlizeHist(img)
plt.hist(equ.ravel(),255)
plt.show()
res = np.hstack((img, equ))
cv_show(res, 'res')

自適應直方圖均衡化

分塊做局部均衡化,可以更好的保留細節。

clche = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
res_clahe = clahe.apply(img)      #clahe 自適應直方圖均衡化
res = np.hstack((img,equ,res_clahe))
cv_show(res,'res')

傅里葉變換

再生活中,按照時間爲參照就是時域分析。頻域上不變。

傅里葉變換的作用

  • 高頻:變化劇烈的灰度分量,例如邊界
  • 低頻:變化緩慢的灰度分量,例如一片大海 

濾波

  • 低通濾波器:只保留低頻,會使圖像變得模糊(圖像內部)
  • 高頻濾波器:只保留高頻,會使得圖像細節增強(圖像邊緣,變化劇烈,爲高頻)
  • opencv中主要就是cv2.dif() 和cv2.idif() 【傅里葉逆變換】,輸入圖像需要先轉換成np.float32 格式
  • 得到的結果中頻率爲0的部分會在左上角,通常要轉換到中心位置,可以通過shift變換來實現
  • cv2.dif() 返回的結果是雙通道的(實部,虛部),通常還需要轉換成圖像格式才能展示(0,255)
# -*- coding: utf-8 -*-
"""
Created on Sun Jan 27 22:33:15 2019
@author: ZIXI
"""
 
 
import cv2
import numpy as np
import matplotlib.pyplot as plt
 
img = cv2.imread('F:/picture/img/lena.jpg',0)         #讀灰度圖
 
img_float32 = np.float32(img)
 
#執行傅里葉變換,
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
 
#numpy中有fft.shift操作,可以將得到的低頻,拉到中間
dft_shift = np.fft.fftshift(dft)
 
#得到灰度圖能表示的形式
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
# 對兩個通道進行操作,函數得出的數很小,在20np.log(),映射到0-255範圍
 
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()
 
 
 

中間亮的是低頻分量,高頻分量向四周發散。

# -*- coding: utf-8 -*-
"""
Created on Sun Jan 27 22:33:15 2019
@author: Zixi
"""
 
 
import cv2
import numpy as np
import matplotlib.pyplot as plt
    
img = cv2.imread('F:/picture/img/lena.jpg',0)         #讀灰度圖
 
img_float32 = np.float32(img)
 
#執行傅里葉變換,
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
 
#numpy中有fft.shift操作,可以將得到的低頻,拉到中間
dft_shift = np.fft.fftshift(dft)
#得到灰度圖能表示的形式
 
rows,cols = img.shape
crow,ccol = int(rows/2),int(cols/2) # 中心位置
 
#低通濾波
mask = np.zeros((rows,cols,2) ,np.uint8) #制定掩膜,大小和圖像一樣,np.zeros初始化
mask[crow-30:crow+30,ccol-30:ccol+30] = 1 #使中心位置,上下左右距離30,置爲1
 
#DFT 
fshift = dft_shift*mask            #掩碼與dft後結果相乘只保留出中間區域
f_ishift = np.fft.ifftshift(fshift) #執行idft逆變換之前,執行ishift,從中間再還到原來的位置
img_back = cv2.idft(f_ishift)       #執行idft,還原回去了
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1]) #實部虛部處理成圖像格式
 
 
plt.subplot(121),plt.imshow(img,cmap = 'gray')  
plt.title('Input Image'),plt.xticks([]),plt.yticks([])#隱藏座標軸
plt.subplot(122),plt.imshow(img_back,cmap = 'gray')
 
plt.title('result'),plt.xticks([]),plt.yticks([])
plt.show()
 
 
 

低通濾波器後變得模糊了

mask = np.ones((rows,cols,2) ,np.uint8) #制定掩膜,大小和圖像一樣,np.zeros初始化
mask[crow-30:crow+30,ccol-30:ccol+30] =0

在對圖像處理時,想要更加高效,有層次,在頻域處理效果更好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章