圖像處理之基于標記的分水嶺算法(C++)

圖像處理之基于標記的分水嶺算法(C++)


文章目錄

  • 圖像處理之基于標記的分水嶺算法(C++)
  • 前言
  • 一、基于標記點的分水嶺算法應用
    • 1.實現步驟:
    • 2.代碼實現
  • 總結


前言

傳統分水嶺算法存在過分割的不足,OpenCV提供了一種改進的分水嶺算法,使用一系列預定義標記來引導圖像分割的定義方式。使用OpenCV的分水嶺算法cv::wathershed,需要輸入一個標記圖像,圖像的像素值為32位有符號正數(CV_32S類型),每個非零像素代表一個標簽。**它的原理是對圖像中部分像素做標記,表明它的所屬區域是已知的。分水嶺算法可以根據這個初始標簽確定其他像素所屬的區域。**傳統的基于梯度的分水嶺算法和改進后基于標記的分水嶺算法示意圖如下圖所示。
對比圖
從上圖可以看出,傳統基于梯度的分水嶺算法由于局部最小值過多造成分割后的分水嶺較多。而基于標記的分水嶺算法,水淹過程從預先定義好的標記圖像(像素)開始,較好的克服了過度分割的不足。本質上講,基于標記點的改進算法是利用先驗知識來幫助分割的一種方法。因此,改進算法的關鍵在于如何獲得準確的標記圖像,即如何將前景物體與背景準確的標記出來。


一、基于標記點的分水嶺算法應用

1.實現步驟:

  1. 封裝分水嶺算法
  2. 獲取標記圖像(在標記圖中前景設置為255,背景像素設置為128,未知像素設置為0)
  3. 將原圖和標記圖輸入分水嶺算法
  4. 顯示結果

2.代碼實現

#include <iostream>
#include <opencv.hpp>class WatershedSegmenter {private:cv::Mat markers;		// 標記圖public:/** @param const cv::Mat& markerImage 傳入的標記圖* @brief 將傳入的標記圖轉換成CV_32S的標記圖*/void setMarkers(const cv::Mat& markerImage) {// Convert to image of intsmarkerImage.convertTo(markers, CV_32S);}/** @param const cv::Mat& image 原圖* @brief 對原圖和標記圖執行基于標記的分水嶺分割*/cv::Mat process(const cv::Mat& image) {// Apply watershedcv::watershed(image, markers);return markers;}// Return result in the form of an image/** @brief 得到分割結果的標簽*/cv::Mat getSegmentation() {cv::Mat tmp;// all segment with label higher than 255// will be assigned value 255markers.convertTo(tmp, CV_8U);return tmp;}// Return watershed in the form of an image以圖像的形式返回分水嶺cv::Mat getWatersheds() {cv::Mat tmp;//在變換前,把每個像素p轉換為255p+255(在conertTo中實現)markers.convertTo(tmp, CV_8U, 255, 255);return tmp;}
};int main()
{// 讀取圖片std::string filepath = "F://work_study//algorithm_demo//watershedSeg.jpg";cv::Mat src = cv::imread(filepath);if (src.empty()){return -1;}imshow("src", src);// 高斯濾波平滑圖像cv::Mat gaussImg;// 彩色圖轉換為灰度圖cv::cvtColor(src, gaussImg, cv::COLOR_BGR2GRAY);cv::GaussianBlur(gaussImg, gaussImg,cv::Size(7,7),1.0);imshow("gaussImg", gaussImg);// 形態學梯度cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));cv::morphologyEx(gaussImg, gaussImg, cv::MORPH_GRADIENT,kernel);imshow("morphologyEx", gaussImg);// OTSU大津法閾值cv::threshold(gaussImg, gaussImg, 0, 255, cv::THRESH_OTSU | cv::THRESH_BINARY);imshow("threshold", gaussImg);// 形態學操作,生成確定的背景區域cv::Mat kernel_bg = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7)); 開運算(先腐蝕后膨脹)消除噪聲點//cv::morphologyEx(gaussImg, gaussImg, cv::MORPH_OPEN, kernel1,cv::Point(-1,-1),2);// 生成確定的背景區域cv::Mat backgroundImg;cv::dilate(gaussImg, backgroundImg, kernel_bg);imshow("backgroundImg", backgroundImg);// 距離變換,生成確定的前景區域cv::Mat distanceImg,foregroundImg;cv::distanceTransform(gaussImg, distanceImg, cv::DIST_L1,5);double min, max;cv::minMaxLoc(distanceImg, &min, &max);cv::threshold(distanceImg, distanceImg, 0.1 * max, 255, cv::THRESH_BINARY);cv::normalize(distanceImg, foregroundImg, 0, 255, cv::NORM_MINMAX, CV_8U);imshow("foregroundImg", foregroundImg);// 去除連通域中的背景部分cv::Mat unknownImg;cv::subtract(backgroundImg, foregroundImg, unknownImg);	//待定區域,減去前景與背景的重合區域imshow("unknownImg", unknownImg);cv::Mat makers(gaussImg.size(),CV_8U,cv::Scalar(128));for (int i = 0; i < makers.rows; i++){for (int j = 0; j < makers.cols; j++){if (foregroundImg.at<uchar>(i, j) == 255){makers.at<uchar>(i, j) = 255;}else if (unknownImg.at<uchar>(i, j) == 255){makers.at<uchar>(i, j) = 0;}}}imshow("makers", makers);// 分水嶺算法分割圖像WatershedSegmenter seg;					// 實例化一個分水嶺分割對象seg.setMarkers(makers);					// 設置算法的標記圖像,使得水淹過程從這組預定義好的標記像素開始seg.process(src);						// 傳入待分割的原圖(要求為CV_8UC3)cv::Mat resultImg;resultImg = seg.getSegmentation();		// 將修改后的標記圖makers轉換為可顯示的8位灰度圖并返回分割結果(白色為前景,灰色為背景,0為邊緣)cv::threshold(resultImg, resultImg, 250, 1, cv::THRESH_BINARY);cv::cvtColor(resultImg, resultImg, cv::COLOR_GRAY2BGR);resultImg = src.mul(resultImg);cv::cvtColor(resultImg, resultImg, cv::COLOR_BGR2GRAY);std::cout << resultImg.type() << std::endl;for(int i=0;i<resultImg.rows;i++)for (int j = 0; j < resultImg.cols; j++){if (resultImg.at<uchar>(i, j) == 0){resultImg.at<uchar>(i, j) = 255;}}imshow("resultImg", resultImg);cv::waitKey(0);return 0;}

過程圖
在這里插入圖片描述


總結

本文主要介紹了一種基于標記的分水嶺算法的應用,關鍵在于如何巧妙地設計“標記圖”,歡迎討論交流。

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

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

相關文章

【C語言進階】動態內存管理及柔性數組

動態內存的開辟在C語言中相當重要的知識 1、為什么會存在動態內存分配 內存的開辟方式&#xff1a; int a20;//在棧空間上開辟4個字節 int arr[10];//在棧空間上開辟40個字節的連續空間 這種開辟空間的方式有兩個特點&#xff1a; 1、開辟的空間大小是固定的 2、數組在聲明的…

二叉樹創建和遍歷

個人主頁 &#xff1a;敲上癮-CSDN博客二叉樹介紹&#xff1a;二叉樹(詳解)-CSDN博客 目錄 一、二叉樹的創建 二、二叉樹的遍歷 1.前序遍歷 2.中序遍歷 3.后序遍歷 4.層序遍歷 三、相關計算 1.總節點個數計算 2.葉子節點個數計算 3.深度計算 一、二叉樹的創建 關于…

如何在路由器上安裝代理服務:詳細教程

如何在路由器上安裝代理服務&#xff1a;詳細教程 步驟一&#xff1a;通過漏洞進入路由器系統開啟Telnet服務使用Telnet登錄路由器系統查看系統信息和CPU信息步驟二&#xff1a;交叉編譯MIPS程序 Go對MIPS的支持 安裝TFTP Server使用BusyBox tftp傳輸文件在路由器系統中下載編譯…

?機器學習正則化算法的總結。耗時10個小時完成。?

?純 干 貨~? 目錄 純干貨 1、L1 正則化&#xff08;Lasso 正則化&#xff09; 2、L2 正則化&#xff08;嶺正則化&#xff09; 3、彈性網絡正則化&#xff08;Elastic Net 正則化&#xff09; 4、Dropout 正則化&#xff08;用于神經網絡&#xff09; 5、貝葉斯Rid…

海外盲盒小程序:跨文化營銷的利器

在全球化的浪潮下&#xff0c;跨境電商正迎來前所未有的發展機遇。作為這一領域中的新興力量&#xff0c;海外盲盒小程序憑借其獨特的魅力和優勢&#xff0c;正逐漸嶄露頭角&#xff0c;成為跨文化營銷的利器。本文將探討海外盲盒小程序在跨文化營銷中的應用及其帶來的價值。 一…

【30天精通Prometheus:一站式監控實戰指南】第16天:snmp_exporter從入門到實戰:安裝、配置詳解與生產環境搭建指南,超詳細

親愛的讀者們&#x1f44b; ??歡迎加入【30天精通Prometheus】專欄&#xff01;&#x1f4da; 在這里&#xff0c;我們將探索Prometheus的強大功能&#xff0c;并將其應用于實際監控中。這個專欄都將為你提供寶貴的實戰經驗。&#x1f680; ??Prometheus是云原生和DevOps的…

【java11】java11新特性之增強String的API

Java11在String類上引入了一系列新的API增強&#xff0c;這些改進顯著提升了開發者在處理字符串時的便捷性和效率。 以下是Java11中增強String API的主要新特性&#xff1a; String.repeat()&#xff1a;重復給定次數的字符串。返回連接的字符串。String.isBlank()&#xff1…

ldap協議(常用于統一身份認證)與dict協議(在線詞典)

文章目錄 LDAPDICT LDAP LDAP&#xff08;Light Directory Access Portocol&#xff09;&#xff0c;輕量目錄訪問協議。 目錄是一個為查詢、瀏覽和搜索而優化的數據庫&#xff0c;它成樹狀結構組織數據&#xff0c;類似文件目錄一樣。 目錄數據庫和關系數據庫不同&#xff0c…

spring security 使用記錄

spring security 使用記錄 Bad credentials配置類密碼匹配 Bad credentials org.springframework.security.authentication.BadCredentialsException: Bad credentialsat org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticatio…

Docker安裝極簡版(三分鐘搞定)

什么是Docker? Docker是一個開源的應用容器引擎&#xff0c;它允許開發者打包他們的應用以及依賴包到一個可移植的容器中&#xff0c;然后發布到任何流行的Linux機器上&#xff0c;也可以實現虛擬化。容器是完全使用沙箱機制&#xff0c;相互之間不會有任何接口。 化。容器是…

日志脫敏功能

前言 數據安全尤為重要&#xff0c;最為簡單的防線就是防止重要信息&#xff08;身份證、手機號、姓名等&#xff09;明文顯示&#xff0c;對此需要在數據庫層、日志層等做好數據加解密。 思路 1、編寫需加密的正則模板、加密字段 2、重寫ch.qos.logback.classic.pattern.Me…

簡易圖像處理器的設計

1 概述 Python是一種高級、通用、解釋型的編程語言&#xff0c;由Guido van Rossum于1991年創造。它被設計為易讀易寫的語言&#xff0c;具有簡潔而清晰的語法&#xff0c;使得它成為許多領域的首選語言&#xff0c;如Web開發、科學計算、人工智能、數據分析等。結合本科階段以…

三維地圖校內導航系統解決方案

在如今的數字化時代&#xff0c;越來越多的學校開始實施智慧校園計劃&#xff0c;旨在為學生和教師提供更高效、便捷的學習和教學環境。智慧校園運用互聯網、大數據、人工智能等技術&#xff0c;對校園內各信息進行收集、整合、分析和應用&#xff0c;實現教學、管理、服務等多…

【matlab】繪圖插入并放大/縮小子圖

參考鏈接 代碼分為兩個&#xff1a;繪圖代碼與magnify.m 繪圖代碼就是普通的繪圖代碼&#xff0c;以下為例 %https://zhuanlan.zhihu.com/p/655767542 clc clear close all x 0:pi/100:2*pi; y1 sin(x); plot(x,y1,r-o); hold on y2sin(x)-0.05; y3sin(x)0.05; xlim([0 2*…

C#關鍵字概覽

C#是一種面向對象的編程語言&#xff0c;由微軟開發并作為.NET框架的一部分。它具有豐富的關鍵字&#xff0c;用于定義程序的結構和行為。本文將詳細介紹C#中的關鍵字&#xff0c;包括基本關鍵字、上下文關鍵字以及它們在C#編程中的使用方式。 訪問修飾符 訪問修飾符控制成員…

Python變量age:深入探索其內涵與運用

Python變量age&#xff1a;深入探索其內涵與運用 在Python的世界里&#xff0c;變量age不僅是一個簡單的標識符&#xff0c;它更是一個承載著豐富信息和功能的實體。今天&#xff0c;我們就來深入探索這個看似簡單的age變量&#xff0c;揭示其背后的奧秘和魅力。 四個方面&am…

供應SKYA21001思佳訊芯片現貨

長期供應各進口品牌芯片現貨&#xff1a; SKYA21001 QM11024TR13 QM12113TR13 QM42391 QM45392 QM28005 RF8020TR13 QM77033DTR13 QM56021TR13-5K 885171 QM77043 QM78207 QM77038TR13 SKY58081-11 QPF5752QTR13-5K RF7198TR13-5K SKY58255-11 SKY85720-11 …

Ubuntu中安裝和配置SSH的完全指南

目錄 前言 第1步&#xff1a;安裝SSH服務器 第2步&#xff1a;檢查防火墻設置 第3步&#xff1a;連接到SSH服務器 第4步&#xff1a;配置SSH服務器&#xff08;可選&#xff09; 更改SSH端口 禁用root登錄 第5步&#xff1a;公鑰認證&#xff08;建議&#xff09; 結論…

XSS Challenges 闖關游戲環境準備:深入指南

在網絡安全領域&#xff0c;理解并掌握跨站腳本攻擊&#xff08;XSS&#xff09;的防御技巧至關重要。為了幫助學習者深入實踐XSS攻擊與防御&#xff0c;“XSS Challenges” 闖關游戲提供了一個實操平臺。本文將詳細介紹如何準備這一環境。 1. 環境準備概述 XSS Challenges 闖…

Kubernetes 之 Secret

Kubernetes 之 Secret Secret 的定義 Secret 解決了密碼、token、秘鑰等敏感數據的配置問題&#xff0c;它避免了把這些敏感數據直接暴露在鏡像或者 Pod 的配置文件中。但是它只是一種相對安全的策略&#xff0c;我們還是可以在容器內找到這些信息。 Secret 的認證方式 認證…