深度學習圖像增強方法全總結!
一、什么是圖像增強?
圖像增強是指通過一系列技術和方法對圖像進行處理,以改善其視覺效果和特征表現(xiàn)。
1. 主要指標:
(1) 亮度(Brightness):
- 影響圖像的整體光照程度。
- 確保圖像在視覺上既不過暗也不過亮。
(2) 對比度(Contrast):
- 增強圖像中亮部和暗部之間的差異。
- 使得細節(jié)更加明顯,高對比度有助于更清晰地展示圖像的紋理和特征。
(3) 清晰度(Sharpness):
- 提高圖像邊緣的清晰度。
- 使物體輪廓更加鮮明,便于細節(jié)識別。
(4) 色彩飽和度(Color Saturation):
- 增強顏色的豐富性。
- 使圖像色彩更加鮮艷,提升視覺吸引力。
(5) 紋理(Texture):
- 突出圖像中的紋理細節(jié)。
- 增強表面特征,對于醫(yī)學影像和材料檢測等領域尤為重要。
(6) 去噪(Denoising):
- 降低圖像中的噪聲。
- 提高信號質量,減少噪聲對重要細節(jié)的干擾。
(7) 增強特征(Feature Enhancement):
- 提高重要特征的可見性。
- 方便觀察和分析。
(8) 視覺一致性(Visual Consistency):
- 確保圖像不同區(qū)域在亮度、對比度和色彩表現(xiàn)上的一致性。
- 便于用戶進行全面分析。
2. 應用領域:
圖像增強技術廣泛應用于多個領域,包括:
- 醫(yī)學影像:改善X光、CT和MRI圖像,以輔助醫(yī)生診斷。
- 衛(wèi)星和遙感圖像:增強地理數(shù)據(jù),支持土地利用分類和環(huán)境監(jiān)測。
- 安防監(jiān)控:提升監(jiān)控視頻質量,促進人臉識別和行為分析。
- 工業(yè)檢測:提高質量控制中的產(chǎn)品檢測精度。
- 圖像搜索和檢索:改善圖像搜索結果的準確性和相關性。
二、亮度和對比度調整
1. 線性方法
(1) 灰度反轉(Gray Inversion)
灰度反轉是指將圖像中的每個像素值反轉,使得圖像的亮部變暗,暗部變亮。具體來說,對于一個灰度圖像,像素值范圍通常是0到255,灰度反轉后,像素值G' = 255 - G,其中G是原始像素值,G'是反轉后的像素值。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gray_inversion(image):
"""
灰度反轉
:param image: 輸入圖像(灰度圖像)
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
inverted_image = 255 - image
return inverted_image
def main():
# 讀取圖像
image = cv2.imread('example.jpg')
if image is None:
print("Error: Could not read image.")
return
# 灰度反轉
inverted_image = gray_inversion(image)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(inverted_image, cmap='gray')
plt.title('Inverted Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()import cv2
import numpy as np
import matplotlib.pyplot as plt
def gray_inversion(image):
"""
灰度反轉
:param image: 輸入圖像(灰度圖像)
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
inverted_image = 255 - image
return inverted_image
def main():
# 讀取圖像
image = cv2.imread('example.jpg')
if image is None:
print("Error: Could not read image.")
return
# 灰度反轉
inverted_image = gray_inversion(image)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(inverted_image, cmap='gray')
plt.title('Inverted Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 對比度拉伸(Contrast Stretching)
對比度拉伸是一種線性變換方法,通過擴展圖像的動態(tài)范圍來增強對比度。具體來說,將圖像的最小像素值映射到0,最大像素值映射到255,中間的像素值按比例線性變換。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def contrast_stretching(image):
"""
對比度拉伸
:param image: 輸入圖像(灰度圖像)
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
min_val = np.min(image)
max_val = np.max(image)
stretched_image = (image - min_val) * (255 / (max_val - min_val))
stretched_image = stretched_image.astype(np.uint8)
return stretched_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 對比度拉伸
stretched_image = contrast_stretching(image)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(stretched_image, cmap='gray')
plt.title('Contrast Stretched Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 對比度和亮度增強(Contrast and Brightness)
對比度和亮度增強是指同時調整圖像的對比度和亮度。具體來說,可以通過以下公式進行調整:
其中,G是原始像素值,G'是調整后的像素值,是對比度增益因子(大于1時對比度增強,小于1時對比度減弱),是亮度偏移量(正值使圖像變亮,負值使圖像變暗)。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def adjust_contrast_brightness(image, alpha=1.0, beta=0):
"""
對比度和亮度增強
:param image: 輸入圖像
:param alpha: 對比度增益因子(大于1時對比度增強,小于1時對比度減弱)
:param beta: 亮度偏移量(正值使圖像變亮,負值使圖像變暗)
:return: 處理后的圖像
"""
new_image = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
return new_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 對比度和亮度增強
enhanced_image = adjust_contrast_brightness(image, alpha=1.5, beta=50)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(enhanced_image, cv2.COLOR_BGR2RGB))
plt.title('Contrast and Brightness Enhanced Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
2. 非線性方法
(1) 指數(shù)變換(Exponential Transformation)
通過指數(shù)函數(shù)來調整圖像的亮度和對比度。具體公式如下:
其中,G是原始像素值,G'是調整后的像素值,c和k是常數(shù)。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def exponential_transformation(image, c=1.0, k=10):
"""
指數(shù)變換
:param image: 輸入圖像(灰度圖像)
:param c: 常數(shù)c
:param k: 常數(shù)k
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
exp_image = c * (np.exp(image / k) - 1)
exp_image = np.clip(exp_image, 0, 255).astype(np.uint8)
return exp_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 指數(shù)變換
exp_image = exponential_transformation(image, c=1.0, k=10)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(exp_image, cmap='gray')
plt.title('Exponential Transformed Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 伽馬變換(Gamma Transformation)
通過伽馬函數(shù)來調整圖像的亮度和對比度。具體公式如下:
其中,G是原始像素值,G'是調整后的像素值,c和是常數(shù)。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gamma_transformation(image, gamma=1.0):
"""
伽馬變換
:param image: 輸入圖像(灰度圖像)
:param gamma: 伽馬值
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
inv_gamma = 1.0 / gamma
table = np.array([((i / 255.0) ** inv_gamma) * 255 for i in np.arange(0, 256)]).astype("uint8")
gamma_image = cv2.LUT(image, table)
return gamma_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 伽馬變換
gamma_image = gamma_transformation(image, gamma=0.5)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(gamma_image, cmap='gray')
plt.title('Gamma Transformed Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 對數(shù)變換(Logarithmic Transformation)
通過對數(shù)函數(shù)來調整圖像的亮度和對比度。具體公式如下:
其中,G是原始像素值,G'是調整后的像素值,c是常數(shù)。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def logarithmic_transformation(image, c=1.0):
"""
對數(shù)變換
:param image: 輸入圖像(灰度圖像)
:param c: 常數(shù)c
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
log_image = c * np.log1p(image)
log_image = np.clip(log_image, 0, 255).astype(np.uint8)
return log_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 對數(shù)變換
log_image = logarithmic_transformation(image, c=255 / np.log1p(np.max(image)))
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(log_image, cmap='gray')
plt.title('Logarithmic Transformed Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
三、直方圖均衡化
1. 普通直方圖均衡化
直方圖均衡化的原理是將圖像的灰度直方圖展平,使得每個灰度級都有更多的像素分布,從而增強圖像的對比度。具體步驟如下:
- 計算灰度直方圖:統(tǒng)計圖像中每個灰度級的像素數(shù)量。
- 計算累積分布函數(shù)(CDF):計算每個灰度級的累積概率。
- 映射灰度值:將原始圖像中的每個灰度值映射到新的灰度值,使得新的灰度分布更加均勻。
- 生成均衡化后的圖像:使用映射后的灰度值生成新的圖像。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def histogram_equalization(image):
"""
直方圖均衡化
:param image: 輸入圖像(灰度圖像)
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
equalized_image = cv2.equalizeHist(image)
return equalized_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 直方圖均衡化
equalized_image = histogram_equalization(image)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(equalized_image, cmap='gray')
plt.title('Histogram Equalized Image')
plt.axis('off')
plt.tight_layout()
plt.show()
# 顯示直方圖
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.hist(image.ravel(), 256, [0, 256], color='gray', alpha=0.7)
plt.title('Histogram of Original Image')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.subplot(1, 2, 2)
plt.hist(equalized_image.ravel(), 256, [0, 256], color='gray', alpha=0.7)
plt.title('Histogram of Equalized Image')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
2. 限制對比度自適應直方圖均衡化(Contrast Limited Adaptive Histogram Equalization, CLAHE)
限制對比度自適應直方圖均衡化在直方圖均衡化的基礎上進行了改進,通過限制對比度和局部均衡化來避免過度增強圖像的對比度,從而減少噪聲和不自然的效果?;驹砣缦拢?/p>
- 圖像分割:將圖像分割成若干個小塊(稱為“tiles”),每個小塊的大小由 tileGridSize 參數(shù)指定。
- 局部均衡化:對每個小塊分別進行直方圖均衡化。為了限制對比度,使用 clipLimit 參數(shù)來限制每個小塊的直方圖中像素值的最大數(shù)量。
- 插值平滑:將每個小塊均衡化后的結果通過插值技術合并,以避免明顯的邊界和不連續(xù)性。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def clahe_equalization(image, clipLimit=2.0, tileGridSize=(8, 8)):
"""
CLAHE均衡化
:param image: 輸入圖像(灰度圖像)
:param clipLimit: 對比度限制閾值
:param tileGridSize: 小塊大小
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=clipLimit, tileGridSize=tileGridSize)
clahe_image = clahe.apply(image)
return clahe_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# CLAHE均衡化
clahe_image = clahe_equalization(image, clipLimit=2.0, tileGridSize=(8, 8))
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(clahe_image, cmap='gray')
plt.title('CLAHE Equalized Image')
plt.axis('off')
plt.tight_layout()
plt.show()
# 顯示直方圖
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.hist(image.ravel(), 256, [0, 256], color='gray', alpha=0.7)
plt.title('Histogram of Original Image')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.subplot(1, 2, 2)
plt.hist(clahe_image.ravel(), 256, [0, 256], color='gray', alpha=0.7)
plt.title('Histogram of CLAHE Equalized Image')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
四、空間域(增強)
空間域增強方法直接操作圖像的像素值,常用于提高圖像的可視性和特征表現(xiàn)??臻g域增強方法可以分為線性濾波和非線性濾波兩大類。此外,邊緣檢測也是一種重要的空間域增強技術,用于突出圖像中的邊緣和細節(jié)。
1. 線性濾波
線性濾波通過卷積操作對圖像進行處理,常用的線性濾波器包括方框濾波、均值濾波器、高斯濾波器和銳化濾波器等。
(1) 方框濾波(Box Filtering)
方框濾波是一種簡單的均值濾波,通過計算每個像素鄰域內的平均值來平滑圖像。具體來說,對于每個像素,取其鄰域內的所有像素值的平均值作為該像素的新值。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def box_filter(image, kernel_size=(3, 3)):
"""
方框濾波
:param image: 輸入圖像
:param kernel_size: 濾波器大小
:return: 處理后的圖像
"""
filtered_image = cv2.boxFilter(image, -1, kernel_size)
return filtered_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 方框濾波
box_filtered_image = box_filter(image, kernel_size=(5, 5))
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(box_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Box Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 均值濾波器(Mean Filter)
均值濾波器通過計算每個像素鄰域內的平均值來平滑圖像。具體來說,對于每個像素,取其鄰域內的所有像素值的平均值作為該像素的新值。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def mean_filter(image, kernel_size=(3, 3)):
"""
均值濾波
:param image: 輸入圖像
:param kernel_size: 濾波器大小
:return: 處理后的圖像
"""
filtered_image = cv2.blur(image, kernel_size)
return filtered_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 均值濾波
mean_filtered_image = mean_filter(image, kernel_size=(5, 5))
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(mean_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Mean Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 高斯濾波器(Gaussian Filter)
高斯濾波器通過高斯核對圖像進行卷積操作,以平滑圖像并減少噪聲。高斯核的權重分布符合高斯分布,中心權重最大,邊緣權重逐漸減小。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gaussian_filter(image, kernel_size=(5, 5), sigmaX=0):
"""
高斯濾波
:param image: 輸入圖像
:param kernel_size: 濾波器大小
:param sigmaX: 高斯核的標準差
:return: 處理后的圖像
"""
filtered_image = cv2.GaussianBlur(image, kernel_size, sigmaX)
return filtered_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 高斯濾波
gaussian_filtered_image = gaussian_filter(image, kernel_size=(5, 5), sigmaX=0)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(gaussian_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Gaussian Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(4) 銳化濾波器(Sharpening Filter)
銳化濾波器通過增強圖像的邊緣和細節(jié)來提高圖像的清晰度。常用的銳化濾波器包括拉普拉斯算子和高通濾波器。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def sharpen_filter(image, kernel_size=(3, 3), alpha=1.5):
"""
銳化濾波
:param image: 輸入圖像
:param kernel_size: 濾波器大小
:param alpha: 銳化因子
:return: 處理后的圖像
"""
# 創(chuàng)建銳化濾波器
kernel = np.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
# 應用濾波器
sharpened_image = cv2.filter2D(image, -1, kernel)
# 確保像素值在有效范圍內
# sharpened_image = np.clip(sharpened_image, 0, 255).astype(np.uint8)
return sharpened_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 銳化濾波
sharpened_image = sharpen_filter(image, kernel_size=(3, 3), alpha=1.5)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(sharpened_image, cv2.COLOR_BGR2RGB))
plt.title('Sharpened Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
2. 非線性濾波
非線性濾波通過非線性操作對圖像進行處理,常用的非線性濾波器包括中值濾波器、雙邊濾波器、最小/最大濾波器、自適應中值濾波和形態(tài)學濾波。
(1) 中值濾波器(Median Filter)
中值濾波器通過計算每個像素鄰域內的中值來平滑圖像,特別適用于去除椒鹽噪聲和斑點噪聲。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def median_filter(image, kernel_size=3):
"""
中值濾波
:param image: 輸入圖像
:param kernel_size: 濾波器大?。ㄆ鏀?shù))
:return: 處理后的圖像
"""
filtered_image = cv2.medianBlur(image, kernel_size)
return filtered_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 中值濾波
median_filtered_image = median_filter(image, kernel_size=5)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(median_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Median Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 雙邊濾波器(Bilateral Filter)
雙邊濾波器通過考慮像素值和空間距離來進行濾波,能夠在去噪的同時保留圖像邊緣和細節(jié)。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def bilateral_filter(image, d=9, sigmaColor=75, sigmaSpace=75):
"""
雙邊濾波
:param image: 輸入圖像
:param d: 每個像素鄰域的直徑
:param sigmaColor: 顏色空間的標準差
:param sigmaSpace: 坐標空間的標準差
:return: 處理后的圖像
"""
filtered_image = cv2.bilateralFilter(image, d, sigmaColor, sigmaSpace)
return filtered_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 雙邊濾波
bilateral_filtered_image = bilateral_filter(image, d=9, sigmaColor=75, sigmaSpace=75)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(bilateral_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Bilateral Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 最小/最大濾波器(Min/Max Filter)
最小濾波器通過計算每個像素鄰域內的最小值來處理圖像,最大濾波器通過計算每個像素鄰域內的最大值來處理圖像。這兩種濾波器常用于形態(tài)學操作。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def min_filter(image, kernel_size=3):
"""
最小濾波
:param image: 輸入圖像
:param kernel_size: 濾波器大?。ㄆ鏀?shù))
:return: 處理后的圖像
"""
filtered_image = cv2.erode(image, np.ones((kernel_size, kernel_size), np.uint8))
return filtered_image
def max_filter(image, kernel_size=3):
"""
最大濾波
:param image: 輸入圖像
:param kernel_size: 濾波器大小(奇數(shù))
:return: 處理后的圖像
"""
filtered_image = cv2.dilate(image, np.ones((kernel_size, kernel_size), np.uint8))
return filtered_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 最小濾波
min_filtered_image = min_filter(image, kernel_size=3)
# 最大濾波
max_filtered_image = max_filter(image, kernel_size=3)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(12, 6))
plt.subplot(1, 3, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 3, 2)
plt.imshow(cv2.cvtColor(min_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Min Filtered Image')
plt.axis('off')
plt.subplot(1, 3, 3)
plt.imshow(cv2.cvtColor(max_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Max Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(4) 自適應中值濾波(Adaptive Median Filtering)
自適應中值濾波器通過動態(tài)調整濾波器大小來去除噪聲,同時保留圖像邊緣和細節(jié)。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def auto_median_filter(image, max_size):
origen = 3 # 初始窗口大小
board = origen // 2 # 初始應擴充的邊界
copy = cv.copyMakeBorder(image, board, board, board, board, borderType=cv.BORDER_REFLECT) # 擴充邊界
out_img = np.zeros_like(image, dtype=np.uint8)
def sub_func(src, i, j, size):
# 確保 i 和 j 在有效范圍內
if i < 0 or i + size > src.shape[0] or j < 0 or j + size > src.shape[1]:
return src[i, j]
kernel = src[i:i + size, j:j + size]
z_med = np.median(kernel)
z_max = np.max(kernel)
z_min = np.min(kernel)
if z_min < z_med < z_max: # 層次A
if z_min < image[i][j] < z_max: # 層次B
return image[i][j]
else:
return z_med
else:
next_size = size + 2 # 增加尺寸
if next_size <= max_size:
return sub_func(src, i - 1, j - 1, next_size) # 遞歸調用
else:
return z_med
for i in range(image.shape[0]):
for j in range(image.shape[1]):
out_img[i][j] = sub_func(copy, i + board, j + board, origen)
return out_img
def main():
# 讀取圖像
image = cv.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
gray_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# 自適應中值濾波
adaptive_filtered_image = auto_median_filter(gray_image, max_size=7)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv.cvtColor(image, cv.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(adaptive_filtered_image, cmap='gray')
plt.title('Adaptive Median Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(5) 形態(tài)學濾波(Morphological Filtering)
形態(tài)學濾波通過形態(tài)學操作(如腐蝕、膨脹、開運算和閉運算)來處理圖像,常用于去噪、邊緣檢測和形狀分析。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def morphological_filter(image, operation='opening', kernel_size=3):
"""
形態(tài)學濾波
:param image: 輸入圖像
:param operation: 操作類型('opening', 'closing', 'erosion', 'dilation')
:param kernel_size: 濾波器大?。ㄆ鏀?shù))
:return: 處理后的圖像
"""
kernel = np.ones((kernel_size, kernel_size), np.uint8)
if operation == 'opening':
filtered_image = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
elif operation == 'closing':
filtered_image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
elif operation == 'erosion':
filtered_image = cv2.erode(image, kernel)
elif operation == 'dilation':
filtered_image = cv2.dilate(image, kernel)
else:
raise ValueError("Invalid operation. Choose from 'opening', 'closing', 'erosion', 'dilation'.")
return filtered_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 開運算
opening_image = morphological_filter(image, operation='opening', kernel_size=3)
# 閉運算
closing_image = morphological_filter(image, operation='closing', kernel_size=3)
# 腐蝕
erosion_image = morphological_filter(image, operation='erosion', kernel_size=3)
# 膨脹
dilation_image = morphological_filter(image, operation='dilation', kernel_size=3)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(12, 8))
plt.subplot(2, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(cv2.cvtColor(opening_image))
plt.title('Opening Image')
plt.axis('off')
plt.subplot(2, 2, 3)
plt.imshow(cv2.cvtColor(closing_image))
plt.title('Closing Image')
plt.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(cv2.cvtColor(erosion_image))
plt.title('Erosion Image')
plt.axis('off')
plt.tight_layout()
plt.show()
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(dilation_image))
plt.title('Dilation Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
3. 邊緣檢測(Edge Enhancement)
邊緣檢測是圖像處理中的一個重要技術,用于檢測圖像中的邊緣和輪廓。
(1) Prewitt算子
Prewitt算子是一種簡單的梯度算子,用于計算圖像的梯度幅值和方向。Prewitt算子通過兩個3x3的卷積核分別計算水平和垂直方向上的梯度。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def prewitt_edge_detection(image):
"""
Prewitt邊緣檢測
:param image: 輸入圖像(灰度圖像)
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 定義Prewitt算子的水平和垂直卷積核
prewitt_x = np.array([[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]], dtype=np.float32)
prewitt_y = np.array([[-1, -1, -1],
[0, 0, 0],
[1, 1, 1]], dtype=np.float32)
# 應用卷積核
gradient_x = cv2.filter2D(image, -1, prewitt_x)
gradient_y = cv2.filter2D(image, -1, prewitt_y)
# 計算梯度幅值
gradient_magnitude = np.sqrt(gradient_x**2 + gradient_y**2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
return gradient_magnitude
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# Prewitt邊緣檢測
prewitt_image = prewitt_edge_detection(image)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(prewitt_image, cmap='gray')
plt.title('Prewitt Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) Roberts算子
Roberts算子是一種簡單的梯度算子,用于計算圖像的梯度幅值和方向。Roberts算子通過兩個2x2的卷積核分別計算水平和垂直方向上的梯度。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def roberts_edge_detection(image):
"""
Roberts邊緣檢測
:param image: 輸入圖像(灰度圖像)
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 定義Roberts算子的水平和垂直卷積核
roberts_x = np.array([[1, 0],
[0, -1]], dtype=np.float32)
roberts_y = np.array([[0, 1],
[-1, 0]], dtype=np.float32)
# 應用卷積核
gradient_x = cv2.filter2D(image, -1, roberts_x)
gradient_y = cv2.filter2D(image, -1, roberts_y)
# 計算梯度幅值
gradient_magnitude = np.sqrt(gradient_x ** 2 + gradient_y ** 2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
return gradient_magnitude
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# Roberts邊緣檢測
roberts_image = roberts_edge_detection(image)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(roberts_image, cmap='gray')
plt.title('Roberts Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) Sobel算子
Sobel算子是一種廣泛使用的梯度算子,用于計算圖像的梯度幅值和方向。Sobel算子通過兩個3x3的卷積核分別計算水平和垂直方向上的梯度。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def sobel_edge_detection(image):
"""
Sobel邊緣檢測
:param image: 輸入圖像(灰度圖像)
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 計算水平和垂直方向上的梯度
gradient_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
gradient_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
# 計算梯度幅值
gradient_magnitude = np.sqrt(gradient_x ** 2 + gradient_y ** 2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
return gradient_magnitude
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# Sobel邊緣檢測
sobel_image = sobel_edge_detection(image)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(sobel_image, cmap='gray')
plt.title('Sobel Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(4) Scharr算子
Scharr算子是Sobel算子的一種改進版本,提供了更高的精度。Scharr算子通過兩個3x3的卷積核分別計算水平和垂直方向上的梯度。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def scharr_edge_detection(image):
"""
Scharr邊緣檢測
:param image: 輸入圖像(灰度圖像)
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 計算水平和垂直方向上的梯度
gradient_x = cv2.Scharr(image, cv2.CV_64F, 1, 0)
gradient_y = cv2.Scharr(image, cv2.CV_64F, 0, 1)
# 計算梯度幅值
gradient_magnitude = np.sqrt(gradient_x ** 2 + gradient_y ** 2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
return gradient_magnitude
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# Scharr邊緣檢測
scharr_image = scharr_edge_detection(image)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(scharr_image, cmap='gray')
plt.title('Scharr Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(5) 拉普拉斯算子
拉普拉斯算子是一種二階導數(shù)算子,用于檢測圖像中的邊緣。拉普拉斯算子通過一個3x3的卷積核計算圖像的二階導數(shù)。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def laplacian_edge_detection(image):
"""
拉普拉斯邊緣檢測
:param image: 輸入圖像(灰度圖像)
:return: 處理后的圖像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 應用拉普拉斯算子
laplacian_image = cv2.Laplacian(image, cv2.CV_64F, ksize=3)
# 將結果轉換為8位圖像
laplacian_image = np.clip(laplacian_image, 0, 255).astype(np.uint8)
return laplacian_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 拉普拉斯邊緣檢測
laplacian_image = laplacian_edge_detection(image)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(laplacian_image, cmap='gray')
plt.title('Laplacian Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(6) Canny邊緣檢測
Canny邊緣檢測是一種多階段的邊緣檢測算法,能夠檢測出圖像中的強邊緣。Canny邊緣檢測包括以下步驟:
- 高斯濾波:平滑圖像,減少噪聲。
- 計算梯度幅值和方向:使用Sobel算子計算圖像的梯度幅值和方向。
- 非極大值抑制:抑制非極大值像素,保留邊緣。
- 雙閾值檢測:使用高低閾值檢測和連接邊緣。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gaussian_blur(image, kernel_size=(5, 5), sigmaX=0):
"""
高斯濾波
:param image: 輸入圖像
:param kernel_size: 濾波器大小
:param sigmaX: 高斯核的標準差
:return: 處理后的圖像
"""
return cv2.GaussianBlur(image, kernel_size, sigmaX)
def compute_gradients(image):
"""
計算圖像的梯度幅值和方向
:param image: 輸入圖像(灰度圖像)
:return: 梯度幅值和方向
"""
# 計算水平和垂直方向上的梯度
gradient_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
gradient_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
# 計算梯度幅值
gradient_magnitude = np.sqrt(gradient_x ** 2 + gradient_y ** 2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
# 計算梯度方向
gradient_angle = np.arctan2(gradient_y, gradient_x) * 180 / np.pi
gradient_angle[gradient_angle < 0] += 180
return gradient_magnitude, gradient_angle
def non_max_suppression(gradient_magnitude, gradient_angle):
"""
非極大值抑制
:param gradient_magnitude: 梯度幅值
:param gradient_angle: 梯度方向
:return: 抑制后的梯度幅值
"""
M, N = gradient_magnitude.shape
suppressed = np.zeros((M, N), dtype=np.uint8)
for i in range(1, M-1):
for j in range(1, N-1):
angle = gradient_angle[i, j]
if (0 <= angle < 22.5) or (157.5 <= angle <= 180):
q = gradient_magnitude[i, j+1]
r = gradient_magnitude[i, j-1]
elif (22.5 <= angle < 67.5):
q = gradient_magnitude[i+1, j-1]
r = gradient_magnitude[i-1, j+1]
elif (67.5 <= angle < 112.5):
q = gradient_magnitude[i+1, j]
r = gradient_magnitude[i-1, j]
elif (112.5 <= angle < 157.5):
q = gradient_magnitude[i-1, j-1]
r = gradient_magnitude[i+1, j+1]
if (gradient_magnitude[i, j] >= q) and (gradient_magnitude[i, j] >= r):
suppressed[i, j] = gradient_magnitude[i, j]
else:
suppressed[i, j] = 0
return suppressed
def double_thresholding(suppressed, low_threshold, high_threshold):
"""
雙閾值檢測
:param suppressed: 抑制后的梯度幅值
:param low_threshold: 低閾值
:param high_threshold: 高閾值
:return: 邊緣圖像
"""
M, N = suppressed.shape
strong = np.zeros((M, N), dtype=np.uint8)
weak = np.zeros((M, N), dtype=np.uint8)
strong_i, strong_j = np.where(suppressed >= high_threshold)
weak_i, weak_j = np.where((suppressed >= low_threshold) & (suppressed < high_threshold))
strong[strong_i, strong_j] = 255
weak[weak_i, weak_j] = 50
return strong, weak
def edge_tracking(strong, weak):
"""
邊緣跟蹤
:param strong: 強邊緣圖像
:param weak: 弱邊緣圖像
:return: 最終的邊緣圖像
"""
M, N = strong.shape
final_edges = np.zeros((M, N), dtype=np.uint8)
final_edges[np.where(strong == 255)] = 255
def dfs(i, j):
if i < 0 or i >= M or j < 0 or j >= N:
return
if weak[i, j] == 50:
final_edges[i, j] = 255
weak[i, j] = 0
dfs(i-1, j)
dfs(i+1, j)
dfs(i, j-1)
dfs(i, j+1)
dfs(i-1, j-1)
dfs(i-1, j+1)
dfs(i+1, j-1)
dfs(i+1, j+1)
for i in range(M):
for j in range(N):
if strong[i, j] == 255:
dfs(i, j)
return final_edges
def canny_edge_detection(image, low_threshold=50, high_threshold=150, kernel_size=(5, 5), sigmaX=0):
"""
Canny邊緣檢測
:param image: 輸入圖像(灰度圖像)
:param low_threshold: 低閾值
:param high_threshold: 高閾值
:param kernel_size: 高斯濾波器大小
:param sigmaX: 高斯核的標準差
:return: 邊緣圖像
"""
# 1. 高斯濾波
blurred_image = gaussian_blur(image, kernel_size, sigmaX)
# 2. 計算梯度幅值和方向
gradient_magnitude, gradient_angle = compute_gradients(blurred_image)
# 3. 非極大值抑制
suppressed = non_max_suppression(gradient_magnitude, gradient_angle)
# 4. 雙閾值檢測
strong, weak = double_thresholding(suppressed, low_threshold, high_threshold)
# 5. 邊緣跟蹤
final_edges = edge_tracking(strong, weak)
return final_edges
def main():
# 讀取圖像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 轉換為灰度圖像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Canny邊緣檢測
canny_image = canny_edge_detection(gray_image, low_threshold=50, high_threshold=150)
# 顯示原始圖像和處理后的圖像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(canny_image, cmap='gray')
plt.title('Canny Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
五、頻率域(增強)
在圖像處理中,頻率域增強方法通過將圖像轉換到頻率域,通過修改頻率分量來增強圖像中的特定特征,再將其轉換回空間域得到增強效果。常見的頻率域增強方法包括濾波和頻譜調整,如低通濾波、高通濾波、帶通濾波等。
以下是頻率域增強方法的主要步驟:
(1) 傅里葉變換:使用傅里葉變換將空間域圖像轉換到頻率域。
(2) 濾波器設計:根據(jù)需要增強的特征(如邊緣或噪聲),設計頻域濾波器。
- 低通濾波器:保留低頻成分,抑制高頻成分,用于去噪或平滑處理。
- 高通濾波器:保留高頻成分,抑制低頻成分,用于邊緣增強。
- 帶通濾波器:保留特定頻率區(qū)間的成分,適用于增強特定頻率范圍的細節(jié)。
(3) 頻譜濾波:將設計好的濾波器應用于頻率域圖像。
(4) 逆傅里葉變換:將處理后的頻率域圖像轉換回空間域,得到增強后的圖像。
1. 傅里葉變換(Fourier Transform)
傅里葉變換是一種將時域信號轉換到頻域的方法。在圖像處理中,傅里葉變換將空間域圖像轉換到頻率域,使得圖像的頻率成分更加直觀。通過傅里葉變換,可以分析圖像的頻率特性,從而進行圖像增強、去噪等處理。
其基本思想是將一個信號分解為多個正弦波和余弦波的組合。
對于一個連續(xù)函數(shù)f(x),其傅里葉變換F(u)可以表示為:
其中,j是虛數(shù)單位,u是頻率變量。
對于離散信號f(x),其離散傅里葉變換DFT可以表示為:
其中,N是信號的長度。
1. 快速傅里葉變換(Fast Fourier Transform, FFT)
快速傅里葉變換是一種高效的傅里葉變換算法,能夠快速計算離散傅里葉變換。FFT通過將DFT分解為多個小的DFT計算,從而大大減少了計算復雜度。
2. 離散傅里葉變換(Discrete Fourier Transform, DFT)
離散傅里葉變換是傅里葉變換的離散版本,適用于數(shù)字圖像處理。DFT將離散的圖像信號轉換為離散的頻率信號。
3. 傅里葉逆變換(Inverse Fourier Transform)
傅里葉逆變換將頻率域圖像轉換回空間域。對于離散傅里葉變換,其逆變換可以表示為:
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fft_transform(image):
"""
傅里葉變換
:param image: 輸入圖像(灰度圖像)
:return: 頻率域圖像
"""
# 計算傅里葉變換
f = np.fft.fft2(image)
# 將零頻率分量移到頻譜中心
fshift = np.fft.fftshift(f)
return fshift
def ifft_transform(fshift):
"""
傅里葉逆變換
:param fshift: 頻率域圖像
:return: 空間域圖像
"""
# 將零頻率分量移到頻譜邊緣
f_ishift = np.fft.ifftshift(fshift)
# 計算逆傅里葉變換
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
return img_back
def main():
# 讀取圖像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 傅里葉變換
fshift = fft_transform(image)
# 顯示原始圖像和頻譜圖像
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(np.log(cv2.magnitude(fshift.real, fshift.imag)), cmap='gray')
plt.title('Magnitude Spectrum')
plt.axis('off')
plt.tight_layout()
plt.show()
# 傅里葉逆變換
img_back = ifft_transform(fshift)
# 顯示逆傅里葉變換后的圖像
plt.figure(figsize=(8, 4))
plt.imshow(img_back, cmap='gray')
plt.title('Inverse Fourier Transform')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
4. 濾波器設計
(1) 低通濾波
低通濾波器保留圖像的低頻成分,抑制高頻成分。低頻成分通常對應于圖像的平滑部分,如背景和大尺度結構,而高頻成分對應于圖像的細節(jié)和噪聲。因此,低通濾波可以用于圖像平滑和去噪。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fft_transform(image):
"""
傅里葉變換
:param image: 輸入圖像(灰度圖像)
:return: 頻率域圖像
"""
# 計算傅里葉變換
f = np.fft.fft2(image)
# 將零頻率分量移到頻譜中心
fshift = np.fft.fftshift(f)
return fshift
def ifft_transform(fshift):
"""
傅里葉逆變換
:param fshift: 頻率域圖像
:return: 空間域圖像
"""
# 將零頻率分量移到頻譜邊緣
f_ishift = np.fft.ifftshift(fshift)
# 計算逆傅里葉變換
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
return img_back
def low_pass_filter(fshift, d0=30):
"""
低通濾波器
:param fshift: 頻率域圖像
:param d0: 截止頻率
:return: 濾波后的頻率域圖像
"""
rows, cols = fshift.shape
crow, ccol = rows // 2, cols // 2
mask = np.zeros((rows, cols), np.uint8)
cv2.circle(mask, (ccol, crow), d0, 1, -1)
fshift_filtered = fshift * mask
return fshift_filtered
def main():
# 讀取圖像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 傅里葉變換
fshift = fft_transform(image)
# 低通濾波
fshift_lowpass = low_pass_filter(fshift, d0=30)
img_lowpass = ifft_transform(fshift_lowpass)
# 顯示原始圖像、頻譜圖像和低通濾波結果
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(img_lowpass, cmap='gray')
plt.title('Low-pass Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 高通濾波(High-pass Filtering)
高通濾波器保留圖像的高頻成分,抑制低頻成分。高頻成分通常對應于圖像的細節(jié)和邊緣,而低頻成分對應于圖像的平滑部分。因此,高通濾波可以用于邊緣檢測和細節(jié)增強。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fft_transform(image):
"""
傅里葉變換
:param image: 輸入圖像(灰度圖像)
:return: 頻率域圖像
"""
# 計算傅里葉變換
f = np.fft.fft2(image)
# 將零頻率分量移到頻譜中心
fshift = np.fft.fftshift(f)
return fshift
def ifft_transform(fshift):
"""
傅里葉逆變換
:param fshift: 頻率域圖像
:return: 空間域圖像
"""
# 將零頻率分量移到頻譜邊緣
f_ishift = np.fft.ifftshift(fshift)
# 計算逆傅里葉變換
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
return img_back
def low_pass_filter(fshift, d0=30):
"""
低通濾波器
:param fshift: 頻率域圖像
:param d0: 截止頻率
:return: 濾波后的頻率域圖像
"""
rows, cols = fshift.shape
crow, ccol = rows // 2, cols // 2
mask = np.zeros((rows, cols), np.uint8)
cv2.circle(mask, (ccol, crow), d0, 1, -1)
fshift_filtered = fshift * mask
return fshift_filtered
def main():
# 讀取圖像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 傅里葉變換
fshift = fft_transform(image)
# 低通濾波
fshift_lowpass = low_pass_filter(fshift, d0=30)
img_lowpass = ifft_transform(fshift_lowpass)
# 顯示原始圖像、頻譜圖像和低通濾波結果
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(img_lowpass, cmap='gray')
plt.title('Low-pass Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 帶通濾波(Band-pass Filtering)
帶通濾波器保留圖像中特定頻率范圍內的成分,抑制低于和高于該頻率范圍的成分。帶通濾波可以用于提取特定頻率范圍內的細節(jié),常用于圖像的特定特征增強。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fft_transform(image):
"""
傅里葉變換
:param image: 輸入圖像(灰度圖像)
:return: 頻率域圖像
"""
# 計算傅里葉變換
f = np.fft.fft2(image)
# 將零頻率分量移到頻譜中心
fshift = np.fft.fftshift(f)
return fshift
def ifft_transform(fshift):
"""
傅里葉逆變換
:param fshift: 頻率域圖像
:return: 空間域圖像
"""
# 將零頻率分量移到頻譜邊緣
f_ishift = np.fft.ifftshift(fshift)
# 計算逆傅里葉變換
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
return img_back
def high_pass_filter(fshift, d0=30):
"""
高通濾波器
:param fshift: 頻率域圖像
:param d0: 截止頻率
:return: 濾波后的頻率域圖像
"""
rows, cols = fshift.shape
crow, ccol = rows // 2, cols // 2
mask = np.ones((rows, cols), np.uint8)
cv2.circle(mask, (ccol, crow), d0, 0, -1)
fshift_filtered = fshift * mask
return fshift_filtered
def main():
# 讀取圖像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 傅里葉變換
fshift = fft_transform(image)
# 高通濾波
fshift_highpass = high_pass_filter(fshift, d0=30)
img_highpass = ifft_transform(fshift_highpass)
# 顯示原始圖像、頻譜圖像和高通濾波結果
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(img_highpass, cmap='gray')
plt.title('High-pass Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 小波變換(Wavelet Transform)
小波變換是一種將信號分解為不同尺度和位置的成分的方法。與傅里葉變換不同,小波變換能夠提供時間和頻率的局部化信息。
import cv2
import numpy as np
import matplotlib.pyplot as plt
import pywt
def dwt_transform(image, wavelet='haar', level=1):
"""
離散小波變換
:param image: 輸入圖像(灰度圖像)
:param wavelet: 小波類型
:param level: 分解層數(shù)
:return: 分解后的系數(shù)
"""
coeffs = pywt.wavedec2(image, wavelet, level=level)
return coeffs
def idwt_transform(coeffs, wavelet='haar'):
"""
離散小波逆變換
:param coeffs: 分解后的系數(shù)
:param wavelet: 小波類型
:return: 重構后的圖像
"""
reconstructed_image = pywt.waverec2(coeffs, wavelet)
return reconstructed_image
def main():
# 讀取圖像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 離散小波變換
coeffs = dwt_transform(image, wavelet='haar', level=1)
LL, (LH, HL, HH) = coeffs
# 顯示原始圖像和分解后的系數(shù)
plt.figure(figsize=(12, 6))
plt.subplot(2, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(LL, cmap='gray')
plt.title('LL (Approximation)')
plt.axis('off')
plt.subplot(2, 2, 3)
plt.imshow(LH, cmap='gray')
plt.title('LH (Horizontal Detail)')
plt.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(HL, cmap='gray')
plt.title('HL (Vertical Detail)')
plt.axis('off')
plt.tight_layout()
plt.show()
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(HH, cmap='gray')
plt.title('HH (Diagonal Detail)')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(idwt_transform(coeffs, wavelet='haar'), cmap='gray')
plt.title('Reconstructed Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()