日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV学习(二十一) :计算图像连通分量:connectedComponents(),connectedComponentsWithStats()

發布時間:2024/7/23 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV学习(二十一) :计算图像连通分量:connectedComponents(),connectedComponentsWithStats() 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OpenCV學習(二十一) :計算圖像連通分量:connectedComponents(),connectedComponentsWithStats()

1、connectedComponents()函數

Connected Components即連通體算法用id標注圖中每個連通體,將連通體中序號最小的頂點的id作為連通體的id。如果在圖G中,任意2個頂點之間都存在路徑,那么稱G為連通圖,否則稱該圖為非連通圖,則其中的極大連通子圖稱為連通體,如下圖所示,該圖中有兩個連通體:

計算二值圖像中為圖像的連通分量標注(標記)

int cv::connectedComponents( cv::InputArrayn image, // 輸入8位單通道(二進制) cv::OutputArray labels, // 輸出標簽圖 int connectivity = 8, // 4-或8-連接組件 int ltype = CV_32S // 輸出標簽類型 (CV_32S or CV_16U));

2、connectedComponentsWithStats()函數

這是一個重載的成員函數,它與上述函數的不同之處在于它只接受什么參數。
注意0的區域標識的是background,而centroids則對應的是中心點,而label則對應于表示是當前像素是第幾個輪廓

int cv::connectedComponentsWithStats ( cv::InputArrayn image, // 輸入8位單通道(二進制) cv::OutputArray labels, // 輸出標簽地圖 cv::OutputArray stats, // 統計量的Nx5矩陣(CV_32S):分別對應各個輪廓的包圍框的起始點坐標x,y,// 各個輪廓的包圍框的 width,height和面積:// [x0, y0, width0, height0, area0;// ... ; x(N-1), y(N-1), width(N-1),// height(N-1), area(N-1)] cv::OutputArray centroids, // Nx2 CV_64F中心矩陣:// [ cx0, cy0; ... ; cx(N-1), cy(N-1)] int connectivity = 8, // 4-或8-連接組件 int ltype = CV_32S // 輸出標簽類型 (CV_32S or CV_16U) );

3、示例:

#include <opencv2/opencv.hpp>using namespace cv; using namespace std;int main() {Mat src =imread("F:/C++/2. OPENCV 3.1.0/TEST/test5.PNG",1);if(!src.data ) { printf("讀取圖片錯誤,請確定目錄下是否有imread函數指定圖片存在~! \n"); return false; }imshow( "image", src );// 轉灰度Mat src_gray;cvtColor( src, src_gray, CV_BGR2GRAY );cv::Mat img_edge, labels, img_color, stats,centroids;// 二值化cv::threshold(src_gray, img_edge, 125, 255, cv::THRESH_BINARY);cv::imshow("Image before threshold", img_edge);// 白色代表有數據,黑色代表沒有數據,所以圖像輸入之前要轉換成”黑底白圖“bitwise_not(img_edge,img_edge); // 該函數計算輸入數組的逐元素逐位反轉:cv::imshow("Image after threshold", img_edge);// 計算連通分量// labels 輸出標簽圖// stats Nx5矩陣(CV_32S): 分別對應各個輪廓的x,y,width,height和面積int nccomps = cv::connectedComponentsWithStats ( img_edge, labels, stats, centroids);cout << "檢測到總連接組件: " << nccomps << endl;vector<cv::Vec3b> colors(nccomps+1);colors[0] = Vec3b(0,0,0); // 背景像素保持黑色。for( int i = 1; i < nccomps; i++ ) // 為每個標簽設置顏色{colors[i] = Vec3b(rand()%256, rand()%256, rand()%256);if( stats.at<int>(i, cv::CC_STAT_AREA) < 200 ) // 面積小于200 的colors[i] = Vec3b(0,0,0); // 小區域也被涂成黑色}//img_color = Mat::zeros(src.size(), CV_8UC3);for( int y = 0; y < img_color.rows; y++ )for( int x = 0; x < img_color.cols; x++ ){int label = labels.at<int>(y, x); // 獲得每個 輪廓圖標簽CV_Assert(0 <= label && label <= nccomps);img_color.at<cv::Vec3b>(y, x) = colors[label];}cv::imshow("Labeled map", img_color);waitKey(0);return 0; }

結果:



分析:
1、看輸出參數stats:Nx5矩陣(CV_32S),其中第1 2 6 個的面積小于200:

2、labels 標簽圖中:

4、通過findContours(),drawContours()函數計算連通量

在以前,常用的方法是”是先調用 cv::findContours() 函數(傳入cv::RETR_CCOMP 標志),隨后在得到的連通區域上循環調用 cv::drawContours() “
示例:

#include <opencv2/opencv.hpp>using namespace cv; using namespace std;// 尋找最大的輪廓、按面積排序 函數 vector<vector<Point>> connection_sort(Mat src) {vector<vector<Point>>contours;findContours(src.clone(),contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);//由于給大的區域著色會覆蓋小的區域,所以首先進行排序操作//冒泡排序算法,由小到大排序vector<Point> vptmp;for(size_t i=1;i<contours.size();i++){for(size_t j=contours.size()-1;j>=i;j--){if (contourArea(contours[j]) < contourArea(contours[j-1])){vptmp = contours[j-1];contours[j-1] = contours[j];contours[j] = vptmp;}}}// 繪制 輪廓Mat draw = Mat::zeros(src.size(),CV_8UC3);for( int index = 0; index < contours.size(); index ++ ) // 繪制所有內外輪廓{Scalar color( rand()&255, rand()&255, rand()&255 );drawContours( draw, contours, index, color, 1, LINE_8 ); //CV_FILLED -1// 添加標記char text[100];sprintf(text, "%d", index+1);RotatedRect box = minAreaRect(contours.at(index)); // 獲取中心putText(draw, text, box.center, FONT_HERSHEY_SIMPLEX, 0.5, cvScalar(0,0,255),1.5);}imshow("contours_sort_drawing",draw);return contours; // 返回排序后的 輪廓集 }// 尋找并繪制出彩色聯通區域 vector<Point> FindBigestContour(Mat src,int& imax, int& imaxcontour) { // imax = 0; //代表最大輪廓的序號 // imaxcontour = -1; //代表最大輪廓的大小vector<vector<Point>>contours,contour_max;findContours(src.clone(),contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);for (int i=0;i<contours.size();i++) // 遍歷每個輪廓點集{int itmp = contourArea(contours[i]);// 計算每個輪廓點集面積if (imaxcontour < itmp ){imax = i;imaxcontour = itmp;}}// 顯示 最大輪廓Mat draw = Mat::zeros(src.size(),CV_8UC3);drawContours( draw, contours, imax, Scalar(0,255,0), 1, LINE_8 );imshow( "Contours_Max", draw );return contours[imax]; }int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);Mat src =imread("F:/C++/2. OPENCV 3.1.0/TEST/test3.PNG",1);if(!src.data ) { printf("讀取圖片錯誤,請確定目錄下是否有imread函數指定圖片存在~! \n"); return false; }imshow( "image", src );// 轉灰度Mat src_gray;cvtColor( src, src_gray, CV_BGR2GRAY );src_gray = src_gray >1;imshow( "src_gray", src_gray );// 獲得 新排序后輪廓、顯示vector<vector<Point>> contours_sort;contours_sort = connection_sort(src_gray); // 繪制最大輪廓// 顯示 最大輪廓int imax=0,imax_area=0;vector<vector<Point>>contour_max;contour_max.push_back( FindBigestContour(src_gray,imax,imax_area)); // 獲得最大輪廓點集printf(" %d 輪廓為面積最大輪廓=%d (面積)",imax,imax_area);waitKey(0);return a.exec(); }

結果:

總結

以上是生活随笔為你收集整理的OpenCV学习(二十一) :计算图像连通分量:connectedComponents(),connectedComponentsWithStats()的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。