OpenCV計算機視覺實戰(11)——邊緣檢測詳解

OpenCV計算機視覺實戰(11)——邊緣檢測詳解

    • 0. 前言
    • 1. Sobel 算子與方向梯度
      • 1.1 Sobel 算子簡介
      • 1.2 實現過程
    • 2. Laplacian 邊緣檢測
      • 2.1 Laplacian 算子簡介
      • 2.2 實現過程
    • 3. Canny 算法
      • 3.1 Canny 算法簡介
      • 3.2 實現過程
    • 小結
    • 系列鏈接

0. 前言

邊緣檢測能夠將圖像中最關鍵的輪廓與結構清晰呈現。從一階梯度的 Sobel 算子,到二階導數的 Laplacian,再到集平滑、非極大值抑制與雙閾值連接于一體的 Canny 算法,三者各有千秋,共同構筑了邊緣檢測的基石。本節將深入探索 OpenCV 中三大經典邊緣檢測算子:Sobel 算子、LaplacianCanny 算法,并詳細介紹每種方法的實現細節與優化技巧。

1. Sobel 算子與方向梯度

1.1 Sobel 算子簡介

Sobel 算子通過對圖像執行一階導數運算,計算水平方向和垂直方向的梯度,從而提取邊緣,能同時濾除高頻噪聲與提取梯度信息。它不僅告訴我們“哪里有邊緣”,更指明了“邊緣朝哪個方向”——非常適合做紋理分析、特征描述、甚至流場估計的第一步。可以分別獲取 Gx ( x 方向梯度)、Gy (y 方向梯度),再合成強度圖或直接根據方向信息進行后續處理。

1.2 實現過程

(1) 噪聲與紋理權衡:

  • 高斯平滑 (ksize ≈ 5, alpha ≈ 1.0):抑制圖像中細小噪聲,但會稍微模糊紋理
  • 中值濾波 (cv2.medianBlur):對椒鹽噪聲更有效,但對細節損傷較小
  • 根據場景選擇:工業檢測用高斯,中值或雙邊濾波;醫學影像則可考慮更強的噪聲抑制

(2) 梯度計算細節:

  • dx=1, dy=0:提取水平方向的亮度變化,突出垂直邊
  • dx=0, dy=1:提取垂直方向的亮度變化,突出水平邊
  • 卷積核大小 (ksize=3 vs 5):3×3 速度更快,5×5 更平滑

(3) 梯度合成與可視化:

  • 絕對值轉換后,不同通道的梯度可做彩色疊加:
    sobel_color = cv2.merge([abs_x, abs_y, np.zeros_like(abs_x)])
    
  • 方向圖: theta = arctan2(Gy, Gx) 可繪制 Pseudo-color 方向圖,輔助分割
import cv2
import numpy as np# 1. 讀取并灰度化
img = cv2.imread('10.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 可選降噪
blur = cv2.GaussianBlur(gray, (5, 5), 1.4)# 2. 計算 Sobel 梯度
# 參數 ksize=3 指定 Sobel 卷積核大小
grad_x = cv2.Sobel(blur, cv2.CV_16S, dx=1, dy=0, ksize=3)
grad_y = cv2.Sobel(blur, cv2.CV_16S, dx=0, dy=1, ksize=3)# 3. 轉換為絕對值并歸一化
abs_x = cv2.convertScaleAbs(grad_x)
abs_y = cv2.convertScaleAbs(grad_y)
sobel_combined = cv2.addWeighted(abs_x, 0.5, abs_y, 0.5, 0)# 4. 顯示結果
cv2.imshow('Original', img)
cv2.imshow('Sobel X', abs_x)
cv2.imshow('Sobel Y', abs_y)
cv2.imshow('Sobel Combined', sobel_combined)
cv2.waitKey(0)
cv2.destroyAllWindows()

sobel算子

關鍵函數解析:

  • cv2.Sobel(src, ddepth, dx, dy, ksize)

    • src:輸入圖像(建議先降噪)
    • ddepth:輸出圖像深度,CV_16S 可避免溢出后再轉換
    • dx, dy:分別指定求導的方向
    • ksizeSobel 卷積核大小(常用 35)
  • cv2.convertScaleAbs(src):將帶符號圖像轉換為無符號 8 位圖像,并計算絕對值,便于后續可視化

  • cv2.addWeighted(src1, alpha, src2, beta, gamma):對兩幅圖像按權重線性疊加,dst = src1*alpha + src2*beta + gamma,常用于合成 xy 梯度

2. Laplacian 邊緣檢測

2.1 Laplacian 算子簡介

Laplacian 算子基于二階導數,對亮度突變更為敏感,通過對圖像應用 Laplacian 卷積核,能夠在一次操作中同時獲得所有方向的邊緣,并且通過零交叉 (zero-crossing) 定位精確的邊界。但由于二階導數對噪聲非常敏感,通常需要先進行平滑再做檢測。

2.2 實現過程

(1) 高階平滑:

  • LoG (Laplacian of Gaussian):先高斯再 Laplacian,可直接調用 cv2.GaussianBlur + cv2.Laplacian
  • 也可用 cv2.filter2D 自定義 LoG 卷積核,一步到位

(2) 零交叉檢測:

  • lap 圖中,像素值符號變化(正→負)即為邊緣
  • 可通過掃描 3×3 鄰域,判斷中心像素與鄰居異號來定位“零交叉點”

(3) 閾值篩選與細化:

  • 首次檢測后,用 cv2.threshold 去除微弱響應
  • 再做形態學細化 (cv2.ximgproc.thinning) 得到單像素寬度邊緣
import cv2
import numpy as np# 1. 讀取與 LoG 平滑
img = cv2.imread('10.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur_log = cv2.GaussianBlur(gray, (7, 7), sigmaX=2)
lap = cv2.Laplacian(blur_log, cv2.CV_16S, ksize=3)
lap_abs = cv2.convertScaleAbs(lap)# 2. 零交叉檢測(簡易實現)
zero_cross = np.zeros_like(lap, dtype=np.uint8)
for y in range(1, lap.shape[0]-1):for x in range(1, lap.shape[1]-1):patch = lap[y-1:y+2, x-1:x+2]if np.min(patch) < 0 < np.max(patch):zero_cross[y, x] = 255# 3. 細化邊緣
thinned = cv2.ximgproc.thinning(zero_cross)# 4. 顯示
cv2.imshow('Laplacian', lap_abs)
cv2.imshow('Zero Crossing', zero_cross)
cv2.imshow('Thinned Edges', thinned)
cv2.waitKey(0)
cv2.destroyAllWindows()

laplacian

關鍵函數解析:

  • cv2.Laplacian(src, ddepth, ksize):計算二階導數,ksize 越大,對噪聲抑制越好但細節越模糊
  • 零交叉:檢測符號變化來定位精確邊緣點,是 LoG 方法的經典后處理
  • cv2.ximgproc.thinning(src):細化算法,將二值邊緣收斂為單像素寬度

3. Canny 算法

3.1 Canny 算法簡介

Canny 算法集平滑、梯度、非極大值抑制與雙閾值連接于一體,是產業、科研常用的邊緣檢測算法。合理調參與后處理,能在保持細節的同時,極大抑制噪聲與偽邊緣。

3.2 實現過程

(1) 高斯平滑:

  • 使用 cv2.GaussianBlur,核大小與 sigma 需配合調整:
  • 較大核與 sigma:去噪更多,但細節丟失
  • 較小核與 sigma:保留細節,但噪聲多

(2) 非極大值抑制 (Non-Maximum Suppression, NMS) 剖析:

  • Canny 內部已實現,但了解其原理有助于后續定制:
    • 根據梯度方向,將像素與梯度方向上的兩個鄰居比較
    • 保留局部最大值,抑制非極大響應
  • 可自定義 NMS,加入方向高精度分桶 ( 8 個方向),進一步細化

(3) 雙閾值與邊緣連接:

  • threshold1 (低閾值) 與 threshold2 (高閾值)
  • 一般建議 threshold2 ≈ 2~3 × threshold1

(4) (可選)自適應閾值:

  • 可先計算圖像梯度的全局統計量,再動態設置低高閾值
  • 或根據圖像直方圖 Otsu 自動選閾,再衍生雙閾值
import cv2# 1. 讀取并灰度化
img = cv2.imread('input.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 2. Gaussian 平滑
blur = cv2.GaussianBlur(gray, (5, 5), 1.4)# 3. Canny 邊緣檢測
low_thresh = 50
high_thresh = 150
edges = cv2.Canny(blur, low_thresh, high_thresh, apertureSize=3, L2gradient=True)# 4. 顯示結果
cv2.imshow('Original', img)
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

在這里插入圖片描述

關鍵函數解析:

  • cv2.Canny(image, threshold1, threshold2, apertureSize, L2gradient)
    • threshold1:較低閾值,用于連接邊緣
    • threshold2:較高閾值,定義強邊緣
    • apertureSizeSobel 卷積核大小,常用 3
    • L2gradient=True:使用更精確的歐氏梯度 ( ( d x 2 + d y 2 ) \sqrt {(dx2+dy2)} (dx2+dy2) ?) 替代 L1 范數

小結

在本節中,我們系統介紹了三大經典邊緣檢測算子,包括 Sobel 算子:一階導數平衡了噪聲抑制與邊緣提取,結合方向信息可用于紋理分析與車道檢測;Laplacian 算子:二階導數對微小亮度突變尤為敏感,配合零交叉和細化技術,可精確捕捉任意方向的細節邊緣;Canny 算法:集成多階段處理與雙閾值策略,通過多尺度融合與自適應閾值優化,達到抗噪與細節兼顧的卓越效果。

系列鏈接

OpenCV計算機視覺實戰(1)——計算機視覺簡介
OpenCV計算機視覺實戰(2)——環境搭建與OpenCV簡介
OpenCV計算機視覺實戰(3)——計算機圖像處理基礎
OpenCV計算機視覺實戰(4)——計算機視覺核心技術全解析
OpenCV計算機視覺實戰(5)——圖像基礎操作全解析
OpenCV計算機視覺實戰(6)——經典計算機視覺算法
OpenCV計算機視覺實戰(7)——色彩空間詳解
OpenCV計算機視覺實戰(8)——圖像濾波詳解
OpenCV計算機視覺實戰(9)——閾值化技術詳解
OpenCV計算機視覺實戰(10)——形態學操作詳解

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86118.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86118.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86118.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

哈爾濱idc服務器租用-青蛙云

在數字化浪潮洶涌的當下&#xff0c;企業對于服務器的需求愈發強烈。哈爾濱作為東北地區重要的經濟文化中心&#xff0c;其 IDC 服務器租用市場也呈現出蓬勃發展的態勢。眾多企業在尋求 IDC 服務器租用時&#xff0c;青蛙云憑借自身顯著優勢脫穎而出&#xff0c;成為眾多用戶的…

Zephyr 系統深入解析:SoC 支持包結構與中斷調度器調優實踐

本文將全面深入講解 Zephyr RTOS 的 SoC 支持包設計架構&#xff08;SoC Series / SoC Variant&#xff09;、中斷系統實現、調度器原理、時間片與優先級調優技巧&#xff0c;以及如何在實際項目中構建自定義 SoC 支持包、實現高效的調度器策略和系統性能優化。全文超過 5000 字…

FPGA基礎 -- Verilog 結構建模之模塊參數值

Verilog 中模塊參數值&#xff08;parameter&#xff09;的使用&#xff0c;這是結構建模和模塊可配置設計的核心機制&#xff0c;廣泛應用于 總線寬度配置、流水線級數、功能開關、模塊復用 等場景。 一、什么是模塊參數值&#xff08;parameter&#xff09; parameter 是 Ver…

Skrill是什么?中國用戶能用嗎?安全嗎?完整指南

什么是Skrill&#xff1f; Skrill 前身為 Moneybookers&#xff0c;成立于 2001 年&#xff0c;總部位于英國倫敦&#xff0c;目前隸屬于 Paysafe 集團。作為一個多功能電子支付平臺&#xff0c;Skrill 支持全球 100 多個國家和地區、40 多種貨幣&#xff0c;被廣泛用于&#…

java+vue+SpringBoo校園部門資料管理系統(程序+數據庫+報告+部署教程+答辯指導)

源代碼數據庫LW文檔&#xff08;1萬字以上&#xff09;開題報告答辯稿ppt部署教程代碼講解代碼時間修改工具 技術實現 開發語言&#xff1a;后端&#xff1a;Java 前端&#xff1a;vue框架&#xff1a;springboot數據庫&#xff1a;mysql 開發工具 JDK版本&#xff1a;JDK1.…

Java中的Map實現類詳解

Java中的Map實現類詳解 Java集合框架提供了多種Map接口的實現&#xff0c;每種實現都有其特定的使用場景和特點。以下是主要的Map實現類及其特性分析&#xff1a; 1. 通用Map實現 HashMap 特點&#xff1a;基于哈希表的實現&#xff0c;允許null鍵和null值線程安全&#xf…

Pytorch Lightning 進階 1 - 梯度檢查點(Gradient Checkpointing)

梯度檢查點&#xff08;Gradient Checkpointing&#xff09;是一種在深度學習訓練中優化顯存使用的技術&#xff0c;尤其適用于處理大型模型&#xff08;如Transformer架構&#xff09;時顯存不足的情況。下面用簡單的例子解釋其工作原理和優缺點&#xff1a; 核心原理 深度學…

SpreadJS 迷你圖:數據趨勢可視化的利器

引言 在數據處理和分析領域&#xff0c;直觀地展示數據趨勢對于理解數據和做出決策至關重要。迷你圖作為一種簡潔而有效的數據可視化方式&#xff0c;在顯示數據趨勢方面發揮著重要作用&#xff0c;尤其在與他人共享數據時&#xff0c;能夠快速傳達關鍵信息。SpreadJS 作為一款…

GESP2024年12月認證C++一級( 第三部分編程題(1)溫度轉換)

參考程序1&#xff1a; #include <cstdio> using namespace std;int main() {double K;scanf("%lf", &K);double C K - 273.15; //轉換為攝氏溫度 double F 32 C * 1.8; //轉換為華氏溫度 if (F > 212) //條件判斷 print…

從零開始手寫redis(18)緩存淘汰算法 FIFO 優化

項目簡介 大家好&#xff0c;我是老馬。 Cache 用于實現一個可拓展的高性能本地緩存。 有人的地方&#xff0c;就有江湖。有高性能的地方&#xff0c;就有 cache。 v1.0.0 版本 以前的 FIFO 實現比較簡單&#xff0c;但是 queue 循環一遍刪除的話&#xff0c;性能實在是太…

用Zynq實現脈沖多普勒雷達信號處理:架構、算法與實現詳解

用Zynq實現脈沖多普勒雷達信號處理:架構、算法與實現詳解 脈沖多普勒(PD)雷達是現代雷達系統的核心技術之一,廣泛應用于機載火控、氣象監測、交通監控等領域。其核心優勢在于能在強雜波背景下檢測運動目標,并精確測量其徑向速度。本文將深入探討如何利用Xilinx Zynq SoC(…

OpenCV CUDA模塊設備層-----線程塊級別的一個內存填充工具函數blockFill()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 在同一個線程塊&#xff08;thread block&#xff09;內&#xff0c;將 [beg, end) 范圍內的數據并行地填充為指定值 value。 它使用了 CUDA 線程…

SAP-ABAP:如何查詢 SAP 事務碼(T-Code)被包含在哪些權限角色或權限對象中

要查詢 SAP 事務碼&#xff08;T-Code&#xff09;被包含在哪些權限角色或權限對象中&#xff0c;可使用以下專業方法&#xff1a; &#x1f50d; 1. 通過權限瀏覽器 (SUIM) - 最推薦 事務碼&#xff1a;SUIM (權限信息系統) 操作步驟&#xff1a; 執行 SUIM → 選擇 “角色…

MySQL 多列 IN 查詢詳解:語法、性能與實戰技巧

在 MySQL 中&#xff0c;多列 IN 查詢是一種強大的篩選工具&#xff0c;它允許通過多字段組合快速過濾數據。相較于傳統的 OR 連接多個條件&#xff0c;這種語法更簡潔高效&#xff0c;尤其適合批量匹配復合鍵或聯合字段的場景。本文將深入解析其用法&#xff0c;并探討性能優化…

自由學習記錄(63)

編碼全稱&#xff1a;AV1&#xff08;Alliance for Open Media Video 1&#xff09;。 算力消耗大&#xff1a;目前&#xff08;截至 2025 年中&#xff09;軟件解碼 AV1 的 CPU 開銷非常高&#xff0c;如果沒有專門的硬件解碼單元&#xff0c;播放高清視頻時會很吃 CPU&#…

日本生活:日語語言學校-日語作文-溝通無國界(4)-題目:喜歡讀書

日本生活&#xff1a;日語語言學校-日語作文-溝通無國界&#xff08;4&#xff09;-題目&#xff1a;喜歡讀書 1-前言2-作文原稿3-作文日語和譯本&#xff08;1&#xff09;日文原文&#xff08;2&#xff09;對應中文&#xff08;3&#xff09;對應英文 4-老師評語5-自我感想&…

C++優化程序的Tips

轉自個人博客 1. 避免創建過多中間變量 過多的中間變量不利于代碼的可讀性&#xff0c;還會增加內存的使用&#xff0c;而且可能導致額外的計算開銷。 將用于同一種情況的變量統一管理&#xff0c;可以使用一種通用的變量來代替多個變量。 2. 函數中習慣使用引用傳參而不是返…

C#Blazor應用-跨平臺WEB開發VB.NET

在 C# 中實現 Blazor 應用需要結合 Razor 語法和 C# 代碼&#xff0c;Blazor 允許使用 C# 同時開發前端和后端邏輯。以下是一個完整的 C# Blazor 實現示例&#xff0c;包含項目創建、基礎組件和數據交互等內容&#xff1a; 一、創建 Blazor 項目 使用 Visual Studio 新建項目 …

前端的安全隱患之API惡意調用

永遠不要相信前端傳來的數據&#xff0c;對于資深開發者而言&#xff0c;這幾乎是一種本能&#xff0c;無需過多解釋。然而&#xff0c;初入職場的開發新手可能會感到困惑&#xff1a;為何要對前端傳來的數據持有如此不信任的態度&#xff1f;難道人與人之間連基本的信任都不存…

基于 Spark 實現 COS 海量數據處理

上周在組內分享了一下這個主題&#xff0c; 我覺得還是摘出一部分當文章輸出出來 分享主要包括三個方面&#xff1a; 1. 項目背景 2.Spark 原理 3. Spark 實戰 項目背景 主要是將海量日志進行多維度處理&#xff1b; 項目難點 1、數據量大&#xff08;壓縮包數量 6TB,60 億條數…