OpenCV清除小面積連通域的實(shí)現(xiàn)方法
場景需求
使用OpenCV,往往遇到這類場景:需要清除目標(biāo)圖像中比較小的噪聲區(qū),保留主要區(qū)域信息。
特此分享自己寫的一個(gè)簡單的清除小面積連通域函數(shù),邏輯比較簡單,給大家留出了足夠的發(fā)展空間,根據(jù)自身場景需求進(jìn)行調(diào)整。
原理可以簡單歸結(jié)為:搜索圖像的連通區(qū)輪廓->遍歷各個(gè)連通區(qū)->基于閾值刪除面積較小的連通區(qū)
運(yùn)行速度方面,我沒單獨(dú)測試過這個(gè)單元,大家如果試過之后太慢可以評(píng)論告訴我哦~
反正平常我工作跑那種2000*2000的圖像,這個(gè)函數(shù)的耗時(shí)幾乎忽略不計(jì)。。。
C++實(shí)現(xiàn)代碼
/** * @brief Clear_MicroConnected_Areas 清除微小面積連通區(qū)函數(shù) * @param src 輸入圖像矩陣 * @param dst 輸出結(jié)果 * @return min_area 設(shè)定的最小面積清除閾值 */ void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area) { // 備份復(fù)制 dst = src.clone(); std::vector<std::vector<cv::Point> > contours; // 創(chuàng)建輪廓容器 std::vector<cv::Vec4i> hierarchy; // 尋找輪廓的函數(shù) // 第四個(gè)參數(shù)CV_RETR_EXTERNAL,表示尋找最外圍輪廓 // 第五個(gè)參數(shù)CV_CHAIN_APPROX_NONE,表示保存物體邊界上所有連續(xù)的輪廓點(diǎn)到contours向量內(nèi) cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point()); if (!contours.empty() && !hierarchy.empty()) { std::vector<std::vector<cv::Point> >::const_iterator itc = contours.begin(); // 遍歷所有輪廓 while (itc != contours.end()) { // 定位當(dāng)前輪廓所在位置 cv::Rect rect = cv::boundingRect(cv::Mat(*itc)); // contourArea函數(shù)計(jì)算連通區(qū)面積 double area = contourArea(*itc); // 若面積小于設(shè)置的閾值 if (area < min_area) { // 遍歷輪廓所在位置所有像素點(diǎn) for (int i = rect.y; i < rect.y + rect.height; i++) { uchar *output_data = dst.ptr<uchar>(i); for (int j = rect.x; j < rect.x + rect.width; j++) { // 將連通區(qū)的值置0 if (output_data[j] == 255) { output_data[j] = 0; } } } } itc++; } } }
測試代碼
#include<iostream> #include<opencv2/opencv.hpp> using namespace std; using namespace cv; void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area); int main(void) { Mat A = Mat::zeros(500, 500, CV_8UC1); circle(A, Point2i(100, 100), 50, 255, -1); circle(A, Point2i(300, 400), 15, 255, -1); Mat B; Clear_MicroConnected_Areas(A, B, 1000); imshow("before:A", A); imshow("after:B", B); waitKey(0); system("pause"); return 0; } void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area) { // 備份復(fù)制 dst = src.clone(); std::vector<std::vector<cv::Point> > contours; // 創(chuàng)建輪廓容器 std::vector<cv::Vec4i> hierarchy; // 尋找輪廓的函數(shù) // 第四個(gè)參數(shù)CV_RETR_EXTERNAL,表示尋找最外圍輪廓 // 第五個(gè)參數(shù)CV_CHAIN_APPROX_NONE,表示保存物體邊界上所有連續(xù)的輪廓點(diǎn)到contours向量內(nèi) cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point()); if (!contours.empty() && !hierarchy.empty()) { std::vector<std::vector<cv::Point> >::const_iterator itc = contours.begin(); // 遍歷所有輪廓 while (itc != contours.end()) { // 定位當(dāng)前輪廓所在位置 cv::Rect rect = cv::boundingRect(cv::Mat(*itc)); // contourArea函數(shù)計(jì)算連通區(qū)面積 double area = contourArea(*itc); // 若面積小于設(shè)置的閾值 if (area < min_area) { // 遍歷輪廓所在位置所有像素點(diǎn) for (int i = rect.y; i < rect.y + rect.height; i++) { uchar *output_data = dst.ptr<uchar>(i); for (int j = rect.x; j < rect.x + rect.width; j++) { // 將連通區(qū)的值置0 if (output_data[j] == 255) { output_data[j] = 0; } } } } itc++; } } }
測試效果
圖1 處理前后圖
到此這篇關(guān)于OpenCV-清除小面積連通域的文章就介紹到這了,更多相關(guān)OpenCV-清除小面積連通域內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
8個(gè)實(shí)用的Python程序你知道幾個(gè)
這篇文章主要為大家詳細(xì)介紹了8個(gè)實(shí)用的Python程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助<BR>2022-02-02Python實(shí)現(xiàn)的擬合二元一次函數(shù)功能示例【基于scipy模塊】
這篇文章主要介紹了Python實(shí)現(xiàn)的擬合二元一次函數(shù)功能,結(jié)合實(shí)例形式分析了Python基于scipy模塊進(jìn)行二元一次函數(shù)擬合相關(guān)科學(xué)運(yùn)算操作實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-05-05Django模板標(biāo)簽{% for %}循環(huán),獲取制定條數(shù)據(jù)實(shí)例
這篇文章主要介紹了Django模板標(biāo)簽{% for %}循環(huán),獲取制定條數(shù)據(jù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-05-05Python list運(yùn)算操作代碼實(shí)例解析
這篇文章主要介紹了Python list運(yùn)算操作代碼實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01Python實(shí)現(xiàn)EXCEL表格的排序功能示例
這篇文章主要介紹了Python實(shí)現(xiàn)EXCEL表格的排序功能示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06Python獲取當(dāng)前時(shí)間日期的方法總結(jié)
在Python編程中,獲取當(dāng)前的日期和時(shí)間是一個(gè)常見的需求,它在許多應(yīng)用中都有重要作用,本文為大家詳細(xì)整理了一些Python中的常用方法,希望對(duì)大家有所幫助2024-01-01淺談Pytorch中的自動(dòng)求導(dǎo)函數(shù)backward()所需參數(shù)的含義
今天小編就為大家分享一篇淺談Pytorch中的自動(dòng)求導(dǎo)函數(shù)backward()所需參數(shù)的含義,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-02-02python實(shí)現(xiàn)AES算法及AES-CFB8加解密源碼
這篇文章主要為大家介紹了python實(shí)現(xiàn)AES算法及AES-CFB8加解密的源碼示例,有需要朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02