OpenCV中findContours輪廓提取一個邊緣只對應的一個輪廓

OpenCV中findContours輪廓提取一個邊緣只對應的一個輪廓

OpenCV中findContours輪廓提取一個邊緣只對應的一個輪廓


眾所周知,影象查詢輪廓可以用findContours函式解決,但是不知道大家發現一個問題沒有,有時候輸入影象,得到的結果會出現影象中一條邊緣有查詢到兩個輪廓。當然只提取最外輪廓是不會出現重複情況,但設定提取所有輪廓會出現兩個輪廓,對於利用得到的輪廓進一步處理帶來不必要的麻煩。現在網上很多講解findContours()函式都是講解引數的,當真的用到這個函式會發現跟自己的結果並不如意。下面我就以我有限的感悟談一下如何利用findContours()得到一條邊緣得到對應的一個輪廓,當然不會去修改這個函式的程式碼。

findContours()函式引數講解

  • 輸入image;
  • 輸出contours,是二維向量的Point。如:vector< vector>contours;
  • hierarchy;每個輪廓的資訊,後面要用到這些重要資訊。
  • mode;輪廓檢索模式,網上很多引數說明。
  • method;輪廓的近似辦法。
  • offset;我沒用過,直接預設引數。

提取一個邊緣只對應的一個輪廓

這裡說一下mode這個引數。
RETR_EXTERNAL:表示只檢測最外層輪廓,意思是影象中獨立的個體只檢測最外層輪廓,包含在裡面的輪廓不會提取出來。
RETR_LIST:提取所有輪廓,並放置在list中,不建立等級關係。意思就是提取出來的輪廓之間是沒有聯絡的。
RETR_CCOMP:提取所有輪廓,並且將其組織為雙邊結構。意思就是第一層為它的外圍輪廓,第二層為內圍輪廓,利用這個引數可以篩選出來一個獨立邊緣只對應一個輪廓。
RETR_TREE:提取所有輪廓,並且重新建立網狀輪廓結構。它體現出來的輪廓聯絡很緊密,比如說一個輪廓在另外一個輪廓的裡面,輪廓裡面又包含輪廓。
對了,在引數method中有個識別符號–CV_CHAIN_CODE,是生成Freeman碼的,但是OpenCV提供的C 介面好像不好提取,還沒有深究,C介面的程式碼我有,網上蕩的,在百度知道搜的,那不缺大神哦。

前面講了那麼多,進入正題吧。其實所有的輪廓關係在引數hierarchy中體現,大家可以除錯看看那裡面的值。hierarchy[i][0]–hierarchy[i][3]依次表示輪廓的後一個輪廓、前一個輪廓、父輪廓、內嵌輪廓,如果沒有對應項,設定為-1。
我們要得到一個邊緣只對應的一個輪廓,需要在mode引數設定為RETR_CCOMP,表示雙層結構,利用hierarchy中的資訊篩選出輪廓。
如下圖,其實只有四個輪廓,但查詢出來了七個輪廓。
這裡寫圖片描述

hierarchy資訊中對應的 值

元素
hierarchy[ 0]2,-1,1,-1
hierarchy[ 1]-1,-1,-1,0
hierarchy[ 2]4,0,3,-1
hierarchy[ 3]-1,-1,-1,2
hierarchy[ 4]6,2,5,-1
hierarchy[ 5]-1,-1,-1,4
hierarchy[ 6]-1,4,-1,-1

由上表可以發現,每個hierarchy[i][0]對應的值指示下一個輪廓,注意,這裡下一個輪廓指的是另外的輪廓,不是同一個邊緣的另外一個輪廓。所以我們利用這個資訊可以篩選出一個邊緣的一條輪廓,分別是0->2->4->6四條輪廓。
貼一下程式碼:

vector<int>Index;
for(int i=0;i<contours.size();)
{
int next=hierarchy[i][0];
Index.push_back(i);
i=next;
if(i==-1)
break;
}

輸出的結果Index為(0,2,4,6)。

總結

需要用得到的輪廓做下一步處理可以使用這個方法免去多餘的運算。其實也不算是方法,也就是自己一點點感悟吧,畢竟我自己也是學習者,還有很多不懂得地方。希望我這點感悟對您有所幫助,寫的不對的地方還望見諒,謝謝!