OpenCV實現(xiàn)圖像連通域
圖像的連通域是指圖像中具有相同像素值并且位置相鄰的像素組成的區(qū)域,連通域分析是指在圖像中尋找出彼此互相獨立的連通域并將其標(biāo)記出來。
一般情況下,一個連通域內(nèi)只包含一個像素值,因此為了防止像素值波動對提取不同連通域的影響,連通域分析常處理的是二值化后的圖像。
4-鄰域和8-鄰域:
常用的圖像鄰域分析法有兩遍掃描法和種子填充法。兩遍掃描法會遍歷兩次圖像,第一次遍歷圖像時會給每一個非0像素賦予一個數(shù)字標(biāo)簽,當(dāng)某個像素的上方和左側(cè)鄰域內(nèi)的像素已經(jīng)有數(shù)字標(biāo)簽時,取兩者中的最小值作為當(dāng)前像素的標(biāo)簽,否則賦予當(dāng)前像素一個新的數(shù)字標(biāo)簽。第一次遍歷圖像的時候同一個連通域可能會被賦予一個或者多個不同的標(biāo)簽。
種子填充法源于計算機圖像學(xué),常用于對某些圖形進行填充。該方法首先將所有非0像素放到一個集合中,之后在集合中隨機選出一個像素作為種子像素,根據(jù)鄰域關(guān)系不斷擴充種子像素所在的連通域,并在集合中刪除掉擴充出的像素,直到種子像素所在的連通域無法擴充,之后再從集合中隨機選取一個像素作為新的種子像素,重復(fù)上述過程直到集合中沒有像素。
CV_EXPORTS_AS(connectedComponentsWithAlgorithm) int connectedComponents(InputArray image, OutputArray labels, int connectivity, int ltype, int ccltype);
- image:待標(biāo)記不同連通域的單通道圖像,數(shù)據(jù)類型必須為CV_8U。
- labels:標(biāo)記不同連通域后的輸出圖像,與輸入圖像具有相同的尺寸。
- connectivity:標(biāo)記連通域時使用的鄰域種類,4表示4-鄰域,8表示8-鄰域。
- ltype:輸出圖像的數(shù)據(jù)類型,目前支持CV_32S和CV_16U兩種數(shù)據(jù)類型。
- ccltype:標(biāo)記連通域時使用的算法類型標(biāo)志,可以選擇的參數(shù)及含義在表中給出
該函數(shù)用于計算二值圖像中連通域的個數(shù),并在圖像中將不同的連通域用不同的數(shù)字標(biāo)簽標(biāo)記出,其中標(biāo)簽0表示圖像中的背景區(qū)域,同時函數(shù)具有一個int類型的返回數(shù)據(jù),用于表示圖像中連通域的數(shù)目。函數(shù)的第一個參數(shù)是待標(biāo)記連通域的輸入圖像,函數(shù)要求輸入圖像必須是數(shù)據(jù)類型為CV_8U的單通道灰度圖像,而且最好是經(jīng)過二值化的二值圖像。函數(shù)第二個參數(shù)是標(biāo)記連通域后的輸出圖像,圖像尺寸與第一個參數(shù)的輸入圖像尺寸相同,圖像的數(shù)據(jù)類型與函數(shù)的第四個參數(shù)相關(guān)。函數(shù)第三個參數(shù)是統(tǒng)計連通域時選擇的鄰域種類,函數(shù)支持兩種鄰域,分別用4表示4-鄰域,8表示8-鄰域。函數(shù)第四個參數(shù)為輸出圖像的數(shù)據(jù)類型,可以選擇的參數(shù)為CV_32S和CV_16U兩種。函數(shù)的最后一個參數(shù)是標(biāo)記連通域時使用算法的標(biāo)志,可以選擇的參數(shù)及含義在表給出,目前只支持Grana(BBDT)和Wu(SAUF)兩種算法。
OpenCV 還給出了簡單的函數(shù)形式
int connectedComponents(InputArray image, OutputArray labels, int connectivity = 8, int ltype = CV_32S);
- image:待標(biāo)記不同連通域的圖像單通道,數(shù)據(jù)類型必須為CV_8U。
- labels:標(biāo)記不同連通域后的輸出圖像,與輸入圖像具有相同的尺寸。
- connectivity:標(biāo)記連通域時使用的鄰域種類,4表示4-鄰域,8表示8-鄰域,默認參數(shù)為8。
- ltype:輸出圖像的數(shù)據(jù)類型,目前支持CV_32S和CV_16U兩種數(shù)據(jù)類型,默認參數(shù)為CV_32S。
該函數(shù)原型只有四個參數(shù),前兩個參數(shù)分別表示輸入圖像和輸出圖像,第三個參數(shù)表示統(tǒng)計連通域時選擇的鄰域種類,分別用4表示4-鄰域,8表示8-鄰域,參數(shù)的默認值為8。最后一個參數(shù)表示輸出圖像的數(shù)據(jù)類型,可以選擇的參數(shù)為CV_32S和CV_16U兩種,參數(shù)的默認值為CV_32S。該函數(shù)原型有兩個參數(shù)具有默認值,在使用時最少只需要兩個參數(shù),極大的方便了函數(shù)的調(diào)用。
進一步統(tǒng)計每個連通域的中心位置、矩形區(qū)域大小、區(qū)域面積等信息
復(fù)雜的
CV_EXPORTS_AS(connectedComponentsWithStatsWithAlgorithm) int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats, OutputArray centroids, int connectivity, int ltype, int ccltype);
- image:待標(biāo)記不同連通域的單通道圖像,數(shù)據(jù)類型必須為CV_8U。
- labels:標(biāo)記不同連通域后的輸出圖像,與輸入圖像具有相同的尺寸。
- stats:含有不同連通域統(tǒng)計信息的矩陣,矩陣的數(shù)據(jù)類型為CV_32S。矩陣中第i行是標(biāo)簽為i的連通域的統(tǒng)計特性,存儲的統(tǒng)計信息種類在表6-4中給出。
- centroids:每個連通域的質(zhì)心坐標(biāo),數(shù)據(jù)類型為CV_64F。
- connectivity:標(biāo)記連通域時使用的鄰域種類,4表示4-鄰域,8表示8-鄰域。
- ltype:輸出圖像的數(shù)據(jù)類型,目前支持CV_32S和CV_16U兩種數(shù)據(jù)類型。
- ccltype:標(biāo)記連通域使用的算法類型標(biāo)志,可以選擇的參數(shù)及含義在表中給出。
該函數(shù)能夠在圖像中不同連通域標(biāo)記標(biāo)簽的同時統(tǒng)計每個連通域的中心位置、矩形區(qū)域大小、區(qū)域面積等信息。函數(shù)的前兩個參數(shù)含義與connectedComponents()函數(shù)的前兩個參數(shù)含義一致,都是輸入圖像和輸出圖像。函數(shù)的第三個參數(shù)為每個連通域統(tǒng)計信息矩陣,如果圖像中有N個連通域,那么該參數(shù)輸出的矩陣尺寸為N×5,矩陣中每一行分別保存每個連通域的統(tǒng)計特性,詳細的統(tǒng)計特性在表中給出,如果想讀取包含第i個連通域的邊界框的水平長度,可以通過stats.at(i, CC_STAT_WIDTH)或者stats.at(i, 0)進行讀取。函數(shù)的第四個參數(shù)為每個連通域質(zhì)心的坐標(biāo),如果圖像中有N個連通域,那么該參數(shù)輸出的矩陣尺寸為N×2,矩陣中每一行分別保存每個連通域質(zhì)心的x坐標(biāo)和y坐標(biāo),可以通過centroids.at(i, 0)和 centroids.at(i, 1) 分別讀取第i個連通域質(zhì)心的x坐標(biāo)和y坐標(biāo)。函數(shù)第五個參數(shù)是統(tǒng)計連通域時選擇的鄰域種類,函數(shù)支持兩種鄰域,分別用4表示4-鄰域,8表示8-鄰域。函數(shù)第六個參數(shù)為輸出圖像的數(shù)據(jù)類型,可以選擇的參數(shù)為CV_32S和CV_16U兩種。函數(shù)的最后一個參數(shù)是標(biāo)記連通域使用的算法,可以選擇的參數(shù)在上表給出,目前只支持Grana(BBDT)和Wu(SAUF)兩種算法。
簡單的
int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats, OutputArray centroids, int connectivity = 8, int ltype = CV_32S);
- image:待標(biāo)記不同連通域的單通道圖像,數(shù)據(jù)類型必須為CV_8U。
- labels:標(biāo)記不同連通域后的輸出圖像,與輸入圖像具有相同的尺寸。
- stats:不同連通域的統(tǒng)計信息矩陣,矩陣的數(shù)據(jù)類型為CV_32S。矩陣中第i行是標(biāo)簽為i的連通域的統(tǒng)計特性,存儲的統(tǒng)計信息種類在表6-4中給出。
- centroids:每個連通域的質(zhì)心坐標(biāo),數(shù)據(jù)類型為CV_64F。
- connectivity:標(biāo)記連通域時使用的鄰域種類,4表示4-鄰域,8表示8-鄰域,默認參數(shù)值為8。
- ltype:輸出圖像的數(shù)據(jù)類型,目前只支持CV_32S和CV_16U這兩種數(shù)據(jù)類型,默認參數(shù)值為CV_32S。
該函數(shù)原型只有六個參數(shù),前兩個參數(shù)分別表示輸入圖像和輸出圖像,第三個參數(shù)表示每個連通域的統(tǒng)計信息,第四個參數(shù)表示每個連通域的質(zhì)心位置。后兩個參數(shù)分別表示統(tǒng)計連通域時選擇的鄰域種類,分別用4表示4-鄰域,8表示8-鄰域,參數(shù)的默認值為8。最后一個參數(shù)表示輸出圖像的數(shù)據(jù)類型,可以選擇的參數(shù)為CV_32S和CV_16U兩種,參數(shù)的默認值為CV_32S。該函數(shù)原型有兩個參數(shù)具有默認值,在使用時最少只需要四個參數(shù),極大的方便了函數(shù)的調(diào)用。
簡單示例
// // Created by smallflyfly on 2021/6/16. // #include "opencv2/opencv.hpp" #include "opencv2/highgui.hpp" #include <iostream> using namespace std; using namespace cv; int main() { Mat im = imread("rice.jfif"); Mat gray; cvtColor(im, gray, CV_BGR2GRAY); // resize(im, im, Size(0, 0), 0.5, 0.5); imshow("im", im); Mat im1; threshold(gray, im1, 125, 255, THRESH_BINARY); imshow("im1", im1); // waitKey(0); RNG rng(10010); Mat out; int num = connectedComponents(im1, out, 8, CV_16U); vector<Vec3b> colors; for (int i=0; i<num; i++) { // 使用均勻分布的隨機確定顏色 Vec3b vec = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256)); colors.push_back(vec); } Mat result = Mat::zeros(im.size(), im.type()); for (int i = 0; i < im.rows; ++i) { for (int j = 0; j < im.cols; ++j) { int label = out.at<uint16_t>(i, j); if (label == 0) { continue; } result.at<Vec3b>(i, j) = colors[label]; } } imshow("result", result); Mat labels, stats, centroids; int count = connectedComponentsWithStats(im1, labels, stats, centroids, 8); cout << count << endl; for (int i = 1; i < count; ++i) { int x = centroids.at<double>(i, 0); int y = centroids.at<double>(i, 1); cout << x << " " << y << endl; circle(im, Point(x, y), 2, Scalar(0, 0, 255), -1); int xmin = stats.at<int>(i, CC_STAT_LEFT); int ymin = stats.at<int>(i, CC_STAT_TOP); int w = stats.at<int>(i, CC_STAT_WIDTH); int h = stats.at<int>(i, CC_STAT_HEIGHT); Rect rect(xmin, ymin, w, h); rectangle(im, rect, Scalar(0, 255, 255), 2); putText(im, to_string(i), Point(x+5, y), FONT_HERSHEY_SCRIPT_SIMPLEX, 1, Scalar(0, 0, 255), 2); } imshow("im", im); waitKey(0); destroyAllWindows(); return 0; }
簡單雙色圖效果比較明顯 百度圖片搜的
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解C語言用malloc函數(shù)申請二維動態(tài)數(shù)組的實例
這篇文章主要介紹了詳解C語言用malloc函數(shù)申請二維動態(tài)數(shù)組的實例的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-10-10C++實現(xiàn)LeetCode(160.求兩個鏈表的交點)
這篇文章主要介紹了C++實現(xiàn)LeetCode(160.求兩個鏈表的交點),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07Qt?加載?libjpeg?庫出現(xiàn)“長跳轉(zhuǎn)已經(jīng)運行”錯誤問題解決
這篇文章主要介紹了Qt?加載?libjpeg?庫出現(xiàn)“長跳轉(zhuǎn)已經(jīng)運行”錯誤,本文給大家分享完美解決方案,需要的朋友可以參考下2023-04-04