OpenCV實(shí)現(xiàn)圖像連通域
圖像的連通域是指圖像中具有相同像素值并且位置相鄰的像素組成的區(qū)域,連通域分析是指在圖像中尋找出彼此互相獨(dú)立的連通域并將其標(biāo)記出來(lái)。
一般情況下,一個(gè)連通域內(nèi)只包含一個(gè)像素值,因此為了防止像素值波動(dòng)對(duì)提取不同連通域的影響,連通域分析常處理的是二值化后的圖像。
4-鄰域和8-鄰域:
常用的圖像鄰域分析法有兩遍掃描法和種子填充法。兩遍掃描法會(huì)遍歷兩次圖像,第一次遍歷圖像時(shí)會(huì)給每一個(gè)非0像素賦予一個(gè)數(shù)字標(biāo)簽,當(dāng)某個(gè)像素的上方和左側(cè)鄰域內(nèi)的像素已經(jīng)有數(shù)字標(biāo)簽時(shí),取兩者中的最小值作為當(dāng)前像素的標(biāo)簽,否則賦予當(dāng)前像素一個(gè)新的數(shù)字標(biāo)簽。第一次遍歷圖像的時(shí)候同一個(gè)連通域可能會(huì)被賦予一個(gè)或者多個(gè)不同的標(biāo)簽。
種子填充法源于計(jì)算機(jī)圖像學(xué),常用于對(duì)某些圖形進(jìn)行填充。該方法首先將所有非0像素放到一個(gè)集合中,之后在集合中隨機(jī)選出一個(gè)像素作為種子像素,根據(jù)鄰域關(guān)系不斷擴(kuò)充種子像素所在的連通域,并在集合中刪除掉擴(kuò)充出的像素,直到種子像素所在的連通域無(wú)法擴(kuò)充,之后再?gòu)募现须S機(jī)選取一個(gè)像素作為新的種子像素,重復(fù)上述過(guò)程直到集合中沒(méi)有像素。
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)記連通域時(shí)使用的鄰域種類,4表示4-鄰域,8表示8-鄰域。
- ltype:輸出圖像的數(shù)據(jù)類型,目前支持CV_32S和CV_16U兩種數(shù)據(jù)類型。
- ccltype:標(biāo)記連通域時(shí)使用的算法類型標(biāo)志,可以選擇的參數(shù)及含義在表中給出
該函數(shù)用于計(jì)算二值圖像中連通域的個(gè)數(shù),并在圖像中將不同的連通域用不同的數(shù)字標(biāo)簽標(biāo)記出,其中標(biāo)簽0表示圖像中的背景區(qū)域,同時(shí)函數(shù)具有一個(gè)int類型的返回?cái)?shù)據(jù),用于表示圖像中連通域的數(shù)目。函數(shù)的第一個(gè)參數(shù)是待標(biāo)記連通域的輸入圖像,函數(shù)要求輸入圖像必須是數(shù)據(jù)類型為CV_8U的單通道灰度圖像,而且最好是經(jīng)過(guò)二值化的二值圖像。函數(shù)第二個(gè)參數(shù)是標(biāo)記連通域后的輸出圖像,圖像尺寸與第一個(gè)參數(shù)的輸入圖像尺寸相同,圖像的數(shù)據(jù)類型與函數(shù)的第四個(gè)參數(shù)相關(guān)。函數(shù)第三個(gè)參數(shù)是統(tǒng)計(jì)連通域時(shí)選擇的鄰域種類,函數(shù)支持兩種鄰域,分別用4表示4-鄰域,8表示8-鄰域。函數(shù)第四個(gè)參數(shù)為輸出圖像的數(shù)據(jù)類型,可以選擇的參數(shù)為CV_32S和CV_16U兩種。函數(shù)的最后一個(gè)參數(shù)是標(biāo)記連通域時(shí)使用算法的標(biāo)志,可以選擇的參數(shù)及含義在表給出,目前只支持Grana(BBDT)和Wu(SAUF)兩種算法。
OpenCV 還給出了簡(jiǎn)單的函數(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)記連通域時(shí)使用的鄰域種類,4表示4-鄰域,8表示8-鄰域,默認(rèn)參數(shù)為8。
- ltype:輸出圖像的數(shù)據(jù)類型,目前支持CV_32S和CV_16U兩種數(shù)據(jù)類型,默認(rèn)參數(shù)為CV_32S。
該函數(shù)原型只有四個(gè)參數(shù),前兩個(gè)參數(shù)分別表示輸入圖像和輸出圖像,第三個(gè)參數(shù)表示統(tǒng)計(jì)連通域時(shí)選擇的鄰域種類,分別用4表示4-鄰域,8表示8-鄰域,參數(shù)的默認(rèn)值為8。最后一個(gè)參數(shù)表示輸出圖像的數(shù)據(jù)類型,可以選擇的參數(shù)為CV_32S和CV_16U兩種,參數(shù)的默認(rèn)值為CV_32S。該函數(shù)原型有兩個(gè)參數(shù)具有默認(rèn)值,在使用時(shí)最少只需要兩個(gè)參數(shù),極大的方便了函數(shù)的調(diào)用。
進(jìn)一步統(tǒng)計(jì)每個(gè)連通域的中心位置、矩形區(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)計(jì)信息的矩陣,矩陣的數(shù)據(jù)類型為CV_32S。矩陣中第i行是標(biāo)簽為i的連通域的統(tǒng)計(jì)特性,存儲(chǔ)的統(tǒng)計(jì)信息種類在表6-4中給出。
- centroids:每個(gè)連通域的質(zhì)心坐標(biāo),數(shù)據(jù)類型為CV_64F。
- connectivity:標(biāo)記連通域時(shí)使用的鄰域種類,4表示4-鄰域,8表示8-鄰域。
- ltype:輸出圖像的數(shù)據(jù)類型,目前支持CV_32S和CV_16U兩種數(shù)據(jù)類型。
- ccltype:標(biāo)記連通域使用的算法類型標(biāo)志,可以選擇的參數(shù)及含義在表中給出。
該函數(shù)能夠在圖像中不同連通域標(biāo)記標(biāo)簽的同時(shí)統(tǒng)計(jì)每個(gè)連通域的中心位置、矩形區(qū)域大小、區(qū)域面積等信息。函數(shù)的前兩個(gè)參數(shù)含義與connectedComponents()函數(shù)的前兩個(gè)參數(shù)含義一致,都是輸入圖像和輸出圖像。函數(shù)的第三個(gè)參數(shù)為每個(gè)連通域統(tǒng)計(jì)信息矩陣,如果圖像中有N個(gè)連通域,那么該參數(shù)輸出的矩陣尺寸為N×5,矩陣中每一行分別保存每個(gè)連通域的統(tǒng)計(jì)特性,詳細(xì)的統(tǒng)計(jì)特性在表中給出,如果想讀取包含第i個(gè)連通域的邊界框的水平長(zhǎng)度,可以通過(guò)stats.at(i, CC_STAT_WIDTH)或者stats.at(i, 0)進(jìn)行讀取。函數(shù)的第四個(gè)參數(shù)為每個(gè)連通域質(zhì)心的坐標(biāo),如果圖像中有N個(gè)連通域,那么該參數(shù)輸出的矩陣尺寸為N×2,矩陣中每一行分別保存每個(gè)連通域質(zhì)心的x坐標(biāo)和y坐標(biāo),可以通過(guò)centroids.at(i, 0)和 centroids.at(i, 1) 分別讀取第i個(gè)連通域質(zhì)心的x坐標(biāo)和y坐標(biāo)。函數(shù)第五個(gè)參數(shù)是統(tǒng)計(jì)連通域時(shí)選擇的鄰域種類,函數(shù)支持兩種鄰域,分別用4表示4-鄰域,8表示8-鄰域。函數(shù)第六個(gè)參數(shù)為輸出圖像的數(shù)據(jù)類型,可以選擇的參數(shù)為CV_32S和CV_16U兩種。函數(shù)的最后一個(gè)參數(shù)是標(biāo)記連通域使用的算法,可以選擇的參數(shù)在上表給出,目前只支持Grana(BBDT)和Wu(SAUF)兩種算法。
簡(jiǎn)單的
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)計(jì)信息矩陣,矩陣的數(shù)據(jù)類型為CV_32S。矩陣中第i行是標(biāo)簽為i的連通域的統(tǒng)計(jì)特性,存儲(chǔ)的統(tǒng)計(jì)信息種類在表6-4中給出。
- centroids:每個(gè)連通域的質(zhì)心坐標(biāo),數(shù)據(jù)類型為CV_64F。
- connectivity:標(biāo)記連通域時(shí)使用的鄰域種類,4表示4-鄰域,8表示8-鄰域,默認(rèn)參數(shù)值為8。
- ltype:輸出圖像的數(shù)據(jù)類型,目前只支持CV_32S和CV_16U這兩種數(shù)據(jù)類型,默認(rèn)參數(shù)值為CV_32S。
該函數(shù)原型只有六個(gè)參數(shù),前兩個(gè)參數(shù)分別表示輸入圖像和輸出圖像,第三個(gè)參數(shù)表示每個(gè)連通域的統(tǒng)計(jì)信息,第四個(gè)參數(shù)表示每個(gè)連通域的質(zhì)心位置。后兩個(gè)參數(shù)分別表示統(tǒng)計(jì)連通域時(shí)選擇的鄰域種類,分別用4表示4-鄰域,8表示8-鄰域,參數(shù)的默認(rèn)值為8。最后一個(gè)參數(shù)表示輸出圖像的數(shù)據(jù)類型,可以選擇的參數(shù)為CV_32S和CV_16U兩種,參數(shù)的默認(rèn)值為CV_32S。該函數(shù)原型有兩個(gè)參數(shù)具有默認(rèn)值,在使用時(shí)最少只需要四個(gè)參數(shù),極大的方便了函數(shù)的調(diào)用。
簡(jiǎn)單示例
// // 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++) { // 使用均勻分布的隨機(jī)確定顏色 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; }
簡(jiǎn)單雙色圖效果比較明顯 百度圖片搜的
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++實(shí)現(xiàn)兩個(gè)有序數(shù)組的合并
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)兩個(gè)有序數(shù)組的合并,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02詳解C語(yǔ)言用malloc函數(shù)申請(qǐng)二維動(dòng)態(tài)數(shù)組的實(shí)例
這篇文章主要介紹了詳解C語(yǔ)言用malloc函數(shù)申請(qǐng)二維動(dòng)態(tài)數(shù)組的實(shí)例的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-10-10C++實(shí)現(xiàn)LeetCode(160.求兩個(gè)鏈表的交點(diǎn))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(160.求兩個(gè)鏈表的交點(diǎn)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07Qt?加載?libjpeg?庫(kù)出現(xiàn)“長(zhǎng)跳轉(zhuǎn)已經(jīng)運(yùn)行”錯(cuò)誤問(wèn)題解決
這篇文章主要介紹了Qt?加載?libjpeg?庫(kù)出現(xiàn)“長(zhǎng)跳轉(zhuǎn)已經(jīng)運(yùn)行”錯(cuò)誤,本文給大家分享完美解決方案,需要的朋友可以參考下2023-04-04