Python----計算機視覺處理(Opencv:圖像邊緣檢測:非極大值抑制,雙閾值篩選)

一、 高斯濾波

????????邊緣檢測本身屬于銳化操作,對噪點比較敏感,所以需要進行平滑處理。這里使用的是一個5*5的高斯 核對圖像進行消除噪聲。

二、計算圖像的梯度和方向

三、非極大值抑制

? ? ? ? 在得到每個邊緣的方向之后,其實把它們連起來邊緣檢測就算完了,經過第二步得到的邊緣不經過處理是沒辦法使用的,因為高斯濾波的原因,邊緣會變得模糊,導 致經過第二步后得到的邊緣像素點非常多,因此我們需要對其進行一些過濾操作,而非極大值抑制就是 一個很好的方法,它會對得到的邊緣像素進行一個排除,使邊緣盡可能細一點。

????????在該步驟中,我們需要檢查每個像素點的梯度方向上的相鄰像素,并保留梯度值最大的像素,將其他像 素抑制為零。假設當前像素點為(x,y),其梯度方向是0°,梯度值為G(x,y),那么我們就需要比 較G(x,y)與兩個相鄰像素的梯度值:G(x-1,y)和G(x+1,y)。如果G(x,y)是三個值里面最 大的,就保留該像素值,否則將其抑制為零。

????????并且如果梯度方向不是0°、45°、90°、135°這種特定角度,那么就要用到插值算法來計算當前像素點在 其方向上進行插值的結果了,然后進行比較并判斷是否保留該像素點。這里使用的是單線性插值,通過 A1和A2兩個像素點獲得dTmp1與dTmp2處的插值,然后與中心點C進行比較。具體的插值算法請參考圖 像旋轉實驗。

四、 雙閾值篩選

????????經過非極大值抑制之后,我們還需要設置閾值來進行篩選,當閾值設的太低,就會出現假邊緣,而閾值 設的太高,一些較弱的邊緣就會被丟掉,因此使用了雙閾值來進行篩選,推薦高低閾值的比例為2:1到 3:1之間

????????當某一像素位置的幅值超過最高閾值時,該像素必是邊緣像素;當幅值低于最低像素時,該像素必不是 邊緣像素;幅值處于最高像素與最低像素之間時,如果它能連接到一個高于閾值的邊緣時,則被認為是 邊緣像素,否則就不會被認為是邊緣。

????????也就是說,上圖中的A和C是邊緣,B不是邊緣。因為C雖然不超過 最高閾值,但其與A相連,所以C就是邊緣。

????????具體來說,對于非極大值抑制之后的圖像來說,設置兩個閾值threshold1和threshold2,其中 threshold1是低閾值,threshold2是高閾值。然后遍歷圖像,把梯度值小于低閾值的點的梯度值設為 0,得到圖像1,把梯度值小于高閾值的點的梯度值設為0,得到圖像2。由于圖像2的閾值比較高,所以 其中會損失掉很多有用的圖像信息,而圖像1的閾值比較低,所以會保留很多的信息,包括真正的邊緣和虛假的邊緣。

????????那么我們就可以以圖像2為基礎,以圖像1為補充來連接圖像的邊緣,其具體步驟為:

?????????對圖像2進行遍歷,當遇到一個非零的像素點P時,記錄以P為開始的輪廓線,知道輪廓線的終點位 置Q。

?????????考察圖像1中與圖像2中的Q點位置對應的點S的8鄰近區域,如果在S點的8鄰近區域內有非零像素存 在,就將其作為邊界點放入圖像2中作為點R。然后再從點R開始重復第一步,直到在圖像1和圖像2 中都無法繼續為止。

?????????當完成對包含點P的輪廓線的尋找之后,將這條輪廓線標為已尋找,然后接著尋找下一條輪廓,就 是重復第1步、第2步、第3步,直到圖像2中找不到新的輪廓為止。

????????經過篩選之后的所保存下來的點就是我們圖像中的邊緣點了

五、圖像邊緣檢測?

5.1、有二值化

導入模塊

import cv2

輸入圖像

img=cv2.imread('lenda01.png')

灰度化

img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

二值化

ret1,img_threshold1=cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY)

高斯濾波

img_Guss1=cv2.GaussianBlur(img_threshold1,(5,5),sigmaX=1.5)

梯度與方向

非極大值抑制

雙閾值篩選

img_Canny1=cv2.Canny(img_Guss1,122,127,L2gradient=True)

輸出圖像

cv2.imshow('img',img)
cv2.imshow('img_Canny1',img_Canny1)
cv2.waitKey(0)

完整代碼?

import cv2  img = cv2.imread('lenda01.png')  # 將圖像從BGR顏色空間轉換為灰度圖像  
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 使用全局閾值進行二值化處理  
#   - ret1:  計算得到的閾值 (127)  
#   - img_threshold1:  二值化后的圖像,像素值大于127設置為255,否則設置為0  
ret1, img_threshold1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)  # 使用 Otsu's 閾值法進行二值化處理,并進行反轉  
#   - ret2:  Otsu's算法計算得到的閾值  
#   - img_threshold2:  二值化后的圖像,像素值小于閾值設置為255,否則設置為0  
ret2, img_threshold2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)  # 對二值化后的圖像進行高斯模糊處理,以減少噪聲  
#   - img_threshold1:  輸入圖像(二值化后的圖像)  
#   - (5, 5):  高斯核的大小  
#   - sigmaX=1.5:  X方向上的高斯核標準差  
img_Guss1 = cv2.GaussianBlur(img_threshold1, (5, 5), sigmaX=1.5)  # 使用 Canny 邊緣檢測算法提取圖像的邊緣  
#   - img_Guss1:  輸入圖像(高斯模糊后的二值化圖像)  
#   - ret2:  低閾值,用于邊緣檢測的閾值下限 (這里使用Otsu算法計算得到的閾值)  
#   - ret1:  高閾值,用于邊緣檢測的閾值上限 (這里使用固定閾值127)  
#   - L2gradient=True:  使用 L2 范數計算圖像梯度,更準確  
img_Canny1 = cv2.Canny(img_Guss1, ret2, ret1, L2gradient=True)  # 顯示原始圖像  
cv2.imshow('img', img)  
# 顯示 Canny 邊緣檢測后的圖像  
cv2.imshow('img_Canny1', img_Canny1)  
# 等待用戶按下鍵盤上的任意鍵  
cv2.waitKey(0)  

5.2、無二值化?

import cv2img = cv2.imread('lenda01.png')# 將圖像從BGR顏色空間轉換為灰度圖像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 使用全局閾值進行二值化處理
#   - ret1:  計算得到的閾值 (127)
#   - img_threshold1:  二值化后的圖像,像素值大于127設置為255,否則設置為0
ret1, img_threshold1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)# 使用 Otsu's 閾值法進行二值化處理,并進行反轉
#   - ret2:  Otsu's算法計算得到的閾值
#   - img_threshold2:  二值化后的圖像,像素值小于閾值設置為255,否則設置為0
ret2, img_threshold2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)# 對灰度圖像進行高斯模糊處理,以減少噪聲
#   - (5, 5):  高斯核的大小
#   - sigmaX=1.5:  X方向上的高斯核標準差
img_Guss2 = cv2.GaussianBlur(img_gray, (5, 5), sigmaX=1.5)# 使用 Canny 邊緣檢測算法提取圖像的邊緣
#   - img_Guss2:  輸入圖像(高斯模糊后的灰度圖像)
#   - ret2:  低閾值,用于邊緣檢測的閾值下限
#   - ret1:  高閾值,用于邊緣檢測的閾值上限
#   - L2gradient=True:  使用 L2 范數計算圖像梯度,更準確
img_Canny2 = cv2.Canny(img_Guss2, ret2, ret1, L2gradient=True)# 顯示原始圖像
cv2.imshow('img', img)
# 顯示 Canny 邊緣檢測后的圖像
cv2.imshow('img_Canny2', img_Canny2)
# 等待用戶按下鍵盤上的任意鍵
cv2.waitKey(0)
```

六、庫函數

Canny()

使用 Canny 算法查找圖像中的邊緣

該函數在輸入圖像中查找邊緣,并使用 Canny 算法在輸出映射邊緣中標記它們。threshold1 和 threshold2 之間的最小值用于 Edge 鏈接。最大值用于查找強邊緣的初始分段。查看?http://en.wikipedia.org/wiki/Canny_edge_detector

cv.Canny(	image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]	) ->	edges
cv.Canny(	dx, dy, threshold1, threshold2[, edges[, L2gradient]]	) ->	edges
方法描述
image8 位輸入圖像。
edges輸出邊緣映射;單通道 8 位圖像,其大小與 圖像 相同。
threshold1磁滯過程的第一個閾值。
threshold2滯后程序的第二個閾值。
apertureSize孔徑大小。
L2gradient
dx輸入圖像的 16 位 x 導數(CV_16SC1 或 CV_16SC3)
dy輸入圖像的 16 位 y 導數(與 dx 類型相同)。

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

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

相關文章

Maven工具學習使用(四)——倉庫

倉庫分類 對于Mavne來說,倉庫只分為兩類:本地倉庫和遠程倉庫。當Maven根據坐標查詢尋找構件的時候,它首先會查看本地倉庫,如果本地倉庫存在此構件,則直接使用;如果本地倉庫不存在此構件,或者需要查看是否有更新的構件版本,Maven就會去遠程倉庫查找,發現需要的構件之后…

Axure PR 9.0(發音:Ack-sure)原型圖工具入門教程:鏈接交互

文章目錄 引言Axure? RP 9I Axure RP9入門介紹元件庫對兩個元件進行連接頁面:導航視圖、概要母版交互II 鏈接交互從A頁面跳轉到B頁面返回之前的頁面see also引言 【 產品原型圖】核心價值和實際應用場景:可視化需求,統一團隊理解 https://blog.csdn.net/z929118967/articl…

docker遠程debug

1. 修改 Java 啟動命令 在 Docker 容器中啟動 Java 程序時,需要添加 JVM 調試參數,jdk8以上版本 java -agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005 -jar your-app.jar jdk8及以下版本: java -Xdebug -Xrunjdwp:tra…

K8S學習之基礎五十四:jenkins新建測試流水線

jenkins新建測試流水線 新建任務 node(testak) {stage(第1步:從gitee上下載源代碼) {git url: "https://gitee.com/akang007/jenkins-sample"script {build_tag sh(returnStdout: true, script: git rev-parse --short HEAD).trim()}}stage(第2步:基…

SylixOS 中 select 原理及使用分析

1、select接口簡介 1.1 select接口使用用例 select 是操作系統多路 I/O 復用技術實現的方式之一。 select 函數允許程序監視多個文件描述符,等待所監視的一個或者多個文件描述符變為“準備好”的狀態。所謂的”準備好“狀態是指:文件描述符不再是阻塞狀…

Spring WebFlux之ServerWebExchange

ServerWebExchange 是 Spring WebFlux 中的一個核心接口,用于表示服務器端處理的 HTTP 請求和響應。它封裝了請求和響應的所有信息,并提供了相應的方法來操作這些信息。ServerWebExchange 在響應式編程模型中扮演著關鍵角色,支持非阻塞、異步…

Flutter 常見錯誤和坑

1. 狀態管理問題 StatefulWidget 生命周期誤用 // 錯誤:在 build 方法中修改狀態 override Widget build(BuildContext context) {setState(() { counter; }); // 會導致無限重建循環return Text($counter); }// 正確:在事件處理中修改狀態 Widget bui…

C++智能指針萬字詳細講解(包含智能指針的模擬實現)

在筆試,面試中智能指針經常出現,如果你對智能指針的作用,原理,用法不了解,那么可以看看這篇博客講解,此外本博客還簡單模擬實現了各種指針,在本篇的最后還應對面試題對智能指針的知識點進行了拓…

【Go】Go語言結構體筆記

整體介紹 雖然 Go 語言不是傳統意義上的面向對象語言,但它提供了結構體(struct)來組織數據,并且可以為結構體綁定方法,從而達到面向對象的部分效果。 關鍵知識點包括: 結構體定義與實例化 定義結構體時使用…

Three.js 快速入門教程【十八】射線拾取模型——鼠標點擊屏幕選中模型或物體

系列文章目錄 Three.js 快速入門教程【一】開啟你的 3D Web 開發之旅 Three.js 快速入門教程【二】透視投影相機 Three.js 快速入門教程【三】渲染器 Three.js 快速入門教程【四】三維坐標系 Three.js 快速入門教程【五】動畫渲染循環 Three.js 快速入門教程【六】相機控件 Or…

Object.defineProperty()Proxy詳解(Vue23數據劫持實現)

底層原理👇🏿 總結一下,結構應該包括: 1. 方法的基本作用和參數。 2. 數據描述符和存取描述符的區別。 3. 屬性定義的內部處理流程。 4. 在Vue中的應用實例。 5. 常見錯誤和正確實踐。 每個部分都要結合搜索結果的信息&…

MySQL 進階語法:函數、約束、多表查詢、事務

目錄 一、MySQL 常用函數 1. 字符串函數 1.1 基本字符串操作 1.2 字符串截取與處理 1.3 字符串搜索與替換 2. 數值函數 2.1 基本數學運算 2.2 數學計算 2.3 隨機數與符號 3. 日期時間函數 3.1 獲取當前時間 3.2 日期時間計算 3.3 日期時間提取 3.4 日期時間格式化…

第 12 章(番外)| Solidity 安全前沿趨勢 × 審計生態 × 職業路徑規劃

🌐 第 12 章(番外)| Solidity 安全前沿趨勢 審計生態 職業路徑規劃 ——做得了審計,也接得了項目,走進 Web3 安全工程師的職業實戰地圖 ? 本章導讀 Solidity 安全,不只是代碼安全、業務安全、審計安全…

1、pytest基本用法

目錄 先給大家分享下學習資源 1. 安裝pytest 2. 編寫用例規則 3. 執行用例 最近在學習pytest的用法 并且用這套框架替換了原來的unittest, 同是測試框架 確實感覺到pytest更加便捷 這邊分享給大家我得學習心得 先給大家分享下學習資源 1 官方文檔 pytest 官方…

【sylar-webserver】5 協程調度模塊

文章目錄 設計思路三種協程的切換 協程調度模塊,需要把前面的線程模塊和協程模塊結合使用 ~ 設計思路 構造函數定義 線程池 基本信息。start(),創建線程池,每個線程創建都執行 run()。每個線程在 run() 里,查找任務隊列 m_tasks…

Go 語言規范學習(1)

文章目錄 IntroductionNotation示例(Go 語言的 if 語句): Source code representationCharacters例子:變量名可以是中文 Letters and digits Lexical elementsCommentsTokensSemicolons例子:查看程序所有的token Ident…

探索抓包利器ProxyPin,實現手機APP請求抓包,支持https請求

以下是ProxyPin的簡單介紹: - ProxyPin是一個開源免費HTTP(S)流量捕獲神器,支持 Windows、Mac、Android、IOS、Linux 全平臺系統- 可以使用它來攔截、檢查并重寫HTTP(S)流量,支持捕獲各種應用的網絡請求。ProxyPin基于Flutter開發&#xff0…

深度學習3-pytorch學習

深度學習3-pytorch學習 Tensor 定義與 PyTorch 操作 1. Tensor 定義: Tensor 是 PyTorch 中的數據結構,類似于 NumPy 數組。可以通過不同方式創建 tensor 對象: import torch# 定義一個 1D Tensor x1 torch.Tensor([3, 4])# 定義一個 Fl…

深入淺出Spring-Boot-3.x.pdf

通過網盤分享的文件:深入淺出Spring-Boot-3.x.pdf 鏈接: https://pan.baidu.com/s/10ZkhmeIXphEwND9Rv4EBlg?pwduatm 提取碼: uatm

springboot啟動事件CommandLineRunner使用

什么是CommandRunner CommandRunner是springboot啟動完成時會調用的一個runner 啟動參數會傳遞到這個runner 我們能用來做一些初始化工作和緩存預熱等工作 ApplicationRunner VS CommandRunner? 這兩個Runner作用一樣 只是得到的啟動參數格式不一樣 前者是一個Argument對象…