您好,登錄后才能下訂單哦!
小編給大家分享一下OpenCV如何清除小面積連通域,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
使用OpenCV,往往遇到這類場景:需要清除目標圖像中比較小的噪聲區,保留主要區域信息。
特此分享自己寫的一個簡單的清除小面積連通域函數,邏輯比較簡單,給大家留出了足夠的發展空間,根據自身場景需求進行調整。
原理可以簡單歸結為:搜索圖像的連通區輪廓->遍歷各個連通區->基于閾值刪除面積較小的連通區
運行速度方面,我沒單獨測試過這個單元,大家如果試過之后太慢可以評論告訴我哦~
反正平常我工作跑那種2000*2000的圖像,這個函數的耗時幾乎忽略不計。。。
/** * @brief Clear_MicroConnected_Areas 清除微小面積連通區函數 * @param src 輸入圖像矩陣 * @param dst 輸出結果 * @return min_area 設定的最小面積清除閾值 */ void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area) { // 備份復制 dst = src.clone(); std::vector<std::vector<cv::Point> > contours; // 創建輪廓容器 std::vector<cv::Vec4i> hierarchy; // 尋找輪廓的函數 // 第四個參數CV_RETR_EXTERNAL,表示尋找最外圍輪廓 // 第五個參數CV_CHAIN_APPROX_NONE,表示保存物體邊界上所有連續的輪廓點到contours向量內 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()) { // 定位當前輪廓所在位置 cv::Rect rect = cv::boundingRect(cv::Mat(*itc)); // contourArea函數計算連通區面積 double area = contourArea(*itc); // 若面積小于設置的閾值 if (area < min_area) { // 遍歷輪廓所在位置所有像素點 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++) { // 將連通區的值置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) { // 備份復制 dst = src.clone(); std::vector<std::vector<cv::Point> > contours; // 創建輪廓容器 std::vector<cv::Vec4i> hierarchy; // 尋找輪廓的函數 // 第四個參數CV_RETR_EXTERNAL,表示尋找最外圍輪廓 // 第五個參數CV_CHAIN_APPROX_NONE,表示保存物體邊界上所有連續的輪廓點到contours向量內 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()) { // 定位當前輪廓所在位置 cv::Rect rect = cv::boundingRect(cv::Mat(*itc)); // contourArea函數計算連通區面積 double area = contourArea(*itc); // 若面積小于設置的閾值 if (area < min_area) { // 遍歷輪廓所在位置所有像素點 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++) { // 將連通區的值置0 if (output_data[j] == 255) { output_data[j] = 0; } } } } itc++; } } }
測試效果
以上是“OpenCV如何清除小面積連通域”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。