文章目錄
- 1. 基本概念
- 2. 邊緣檢測原理
- 邊緣類型:
- 3. 常見邊緣檢測算法
- 3.1 Sobel算子
- 3.2 Canny邊緣檢測
- 3.3 Laplacian算子
- 4. Canny邊緣檢測詳細流程
- 流程圖示例:
- 詳細步驟說明:
- 5. 邊緣檢測算法比較
- 6. 參數調優建議
- Canny邊緣檢測參數:
- Sobel算子參數:
- 8. 實際應用場景
- 8.1 醫學圖像處理
- 8.2 工業檢測
- 8.3 自動駕駛
- 8.4 安防監控
1. 基本概念
邊緣檢測是圖像處理和計算機視覺中的基礎技術,用于識別圖像中物體的邊界。邊緣是指圖像中像素強度發生急劇變化的區域,通常對應于物體的輪廓、紋理變化或光照變化。
2. 邊緣檢測原理
邊緣檢測的基本原理是通過計算圖像中像素的梯度來檢測邊緣。梯度表示像素強度變化的速率和方向。在邊緣處,像素強度會發生顯著變化,因此梯度值會很大。
邊緣類型:
- 階躍邊緣:像素強度突然變化
- 屋頂邊緣:像素強度逐漸變化后恢復
- 線條邊緣:細線狀結構
3. 常見邊緣檢測算法
3.1 Sobel算子
Sobel算子是一種基于梯度的邊緣檢測算法,通過計算圖像在水平和垂直方向上的梯度來檢測邊緣。
import cv2
import numpy as np
import matplotlib.pyplot as pltdef sobel_edge_detection(image):"""使用Sobel算子進行邊緣檢測"""# 轉換為灰度圖像if len(image.shape) == 3:gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)else:gray = image# 計算x和y方向的梯度sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)# 計算梯度幅值sobel_combined = np.sqrt(sobelx**2 + sobely**2)return sobelx, sobely, sobel_combined# 示例使用
# image = cv2.imread('sample.jpg')
# sobelx, sobely, sobel_combined = sobel_edge_detection(image)
3.2 Canny邊緣檢測
Canny邊緣檢測是一種多階段算法,被認為是邊緣檢測的黃金標準。
def canny_edge_detection(image, low_threshold=50, high_threshold=150):"""使用Canny算法進行邊緣檢測"""# 轉換為灰度圖像if len(image.shape) == 3:gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)else:gray = image# 應用高斯濾波去噪blurred = cv2.GaussianBlur(gray, (5, 5), 0)# Canny邊緣檢測edges = cv2.Canny(blurred, low_threshold, high_threshold)return edges# 示例使用
# edges = canny_edge_detection(image)
3.3 Laplacian算子
Laplacian算子是二階導數算子,對噪聲敏感但能檢測到更精細的邊緣。
def laplacian_edge_detection(image):"""使用Laplacian算子進行邊緣檢測"""# 轉換為灰度圖像if len(image.shape) == 3:gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)else:gray = image# 應用高斯濾波去噪blurred = cv2.GaussianBlur(gray, (3, 3), 0)# Laplacian邊緣檢測laplacian = cv2.Laplacian(blurred, cv2.CV_64F)return laplacian
4. Canny邊緣檢測詳細流程
Canny邊緣檢測算法包含以下幾個步驟:
流程圖示例:
原始圖像↓
轉換為灰度圖像↓
高斯濾波去噪↓
計算梯度幅值和方向↓
非極大值抑制↓
雙閾值檢測↓
邊緣連接(滯后閾值)↓
最終邊緣圖像
詳細步驟說明:
- 灰度化:將彩色圖像轉換為灰度圖像
- 噪聲去除:使用高斯濾波器平滑圖像
- 梯度計算:計算每個像素的梯度幅值和方向
- 非極大值抑制:細化邊緣,使邊緣只有一個像素寬
- 雙閾值檢測:使用高低閾值確定強邊緣和弱邊緣
- 邊緣連接:通過滯后閾值連接邊緣
def detailed_canny_process(image):"""詳細展示Canny邊緣檢測的每個步驟"""# 步驟1: 轉換為灰度圖像if len(image.shape) == 3:gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)else:gray = image# 步驟2: 高斯濾波去噪blurred = cv2.GaussianBlur(gray, (5, 5), 1.4)# 步驟3: 計算梯度# 使用Sobel算子計算梯度grad_x = cv2.Sobel(blurred, cv2.CV_64F, 1, 0, ksize=3)grad_y = cv2.Sobel(blurred, cv2.CV_64F, 0, 1, ksize=3)# 計算梯度幅值和方向magnitude = np.sqrt(grad_x**2 + grad_y**2)angle = np.arctan2(grad_y, grad_x)# 步驟4: 非極大值抑制suppressed = non_maximum_suppression(magnitude, angle)# 步驟5: 雙閾值檢測weak = 50strong = 150thresholded = double_threshold(suppressed, weak, strong)# 步驟6: 邊緣連接edges = hysteresis(thresholded, weak, strong)return edgesdef non_maximum_suppression(magnitude, angle):"""非極大值抑制"""rows, cols = magnitude.shapesuppressed = np.zeros((rows, cols), dtype=np.int32)angle = angle * 180. / np.piangle[angle < 0] += 180for i in range(1, rows-1):for j in range(1, cols-1):try:q = 255r = 255# 角度0度if (0 <= angle[i,j] < 22.5) or (157.5 <= angle[i,j] <= 180):q = magnitude[i, j+1]r = magnitude[i, j-1]# 角度45度elif (22.5 <= angle[i,j] < 67.5):q = magnitude[i+1, j-1]r = magnitude[i-1, j+1]# 角度90度elif (67.5 <= angle[i,j] < 112.5):q = magnitude[i+1, j]r = magnitude[i-1, j]# 角度135度elif (112.5 <= angle[i,j] < 157.5):q = magnitude[i-1, j-1]r = magnitude[i+1, j+1]if (magnitude[i,j] >= q) and (magnitude[i,j] >= r):suppressed[i,j] = magnitude[i,j]else:suppressed[i,j] = 0except IndexError as e:passreturn suppresseddef double_threshold(img, weak, strong):"""雙閾值檢測"""high_threshold = img.max() * 0.2low_threshold = high_threshold * 0.05rows, cols = img.shaperesult = np.zeros((rows, cols), dtype=np.int32)weak_i, weak_j = np.where((img <= high_threshold) & (img >= low_threshold))strong_i, strong_j = np.where(img >= high_threshold)result[strong_i, strong_j] = strongresult[weak_i, weak_j] = weakreturn resultdef hysteresis(img, weak, strong):"""邊緣連接(滯后閾值)"""rows, cols = img.shapefor i in range(1, rows-1):for j in range(1, cols-1):if (img[i,j] == weak):try:if ((img[i+1, j-1] == strong) or (img[i+1, j] == strong) or (img[i+1, j+1] == strong)or (img[i, j-1] == strong) or (img[i, j+1] == strong)or (img[i-1, j-1] == strong) or (img[i-1, j] == strong) or (img[i-1, j+1] == strong)):img[i, j] = strongelse:img[i, j] = 0except IndexError as e:passreturn img
5. 邊緣檢測算法比較
算法 | 優點 | 缺點 | 適用場景 |
---|---|---|---|
Sobel | 計算簡單,對噪聲有一定抑制作用 | 邊緣較粗,定位不夠精確 | 實時應用,對精度要求不高的場景 |
Canny | 檢測精度高,邊緣連續性好 | 計算復雜,參數敏感 | 高精度邊緣檢測需求 |
Laplacian | 能檢測到細小邊緣 | 對噪聲敏感 | 需要檢測細節特征的場景 |
Prewitt | 計算簡單,各向同性 | 對噪聲敏感,邊緣較粗 | 簡單的邊緣檢測任務 |
6. 參數調優建議
Canny邊緣檢測參數:
- 低閾值:通常設為高閾值的0.4-0.5倍
- 高閾值:可根據圖像的噪聲水平調整
- 高斯核大小:一般選擇3x3或5x5
Sobel算子參數:
- 核大小:通常選擇3x3,也可選擇5x5以獲得更大范圍的梯度
8. 實際應用場景
8.1 醫學圖像處理
- 腫瘤邊界檢測
- 器官輪廓識別
- 細胞結構分析
8.2 工業檢測
- 產品質量檢測
- 缺陷識別
- 尺寸測量
8.3 自動駕駛
- 車道線檢測
- 行人和車輛識別
- 交通標志識別
8.4 安防監控
- 運動目標檢測
- 人臉識別預處理
- 行為分析