opencv的一些函數(shù)——contours

一巷疼、輪廓檢測

image, contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])

findContours( InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point());

findContours( InputOutputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset=Point());

1、image:輸入圖像瓶佳。8-bit的單通道二值圖像桌粉,非零的像素都會被當(dāng)作1蒸绩。
2、contours:檢測到的輪廓铃肯。是一個向量患亿,向量的每個元素都是一個輪廓。因此押逼,這個向量的每個元素仍是一個向量步藕。vector<vector<Point> > contours;
3、hierarchy:各個輪廓的繼承關(guān)系挑格。hierarchy也是一個向量咙冗,長度和contours相等,每個元素和contours的元素對應(yīng)漂彤。hierarchy的每個元素是一個包含四個整型數(shù)的向量雾消。即:
vector<Vec4i> hierarchy; // Vec4i is a vector contains four number of int
hierarchy[i][0],hierarchy[i][1],hierarchy[i][2],hierarchy[i][3],分別表示的是第i條輪廓(contours[i])的下一條灾搏,前一條,包含的第一條輪廓(第一條子輪廓)和包含他的輪廓(父輪廓)立润。
4狂窑、mod: 檢測輪廓的方法。有四種方法范删。
5蕾域、method:表示一條輪廓的方法。
6到旦、offset:可選的偏移旨巷,就是簡單的平移,特別是在做了ROI步驟之后有用添忘。

檢測輪廓方法(mod):

—CV_RETR_EXTERNAL:只檢測外輪廓采呐。忽略輪廓內(nèi)部的洞。

—CV_RETR_LIST:檢測所有輪廓搁骑,但不建立繼承(包含)關(guān)系斧吐。

—CV_RETR_TREE:檢測所有輪廓,并且建立所有的繼承(包含)關(guān)系仲器。用CV_RETR_EXTERNAL和CV_RETR_LIST方法hierarchy變量是沒用的煤率,因為前者沒有包含關(guān)系,找到的都是外輪廓乏冀,后者僅僅是找到所有的輪廓但并不把包含關(guān)系區(qū)分蝶糯。用TREE這種檢測方法的時候我們的hierarchy這個參數(shù)才是有意義的。事實(shí)上辆沦,應(yīng)用前兩種方法的時候昼捍,我們就用findContours這個函數(shù)的第二種聲明了。

—CV_RETR_CCOMP:檢測所有輪廓肢扯,但是僅僅建立兩層包含關(guān)系妒茬。外輪廓放到頂層,外輪廓包含的第一層內(nèi)輪廓放到底層蔚晨,如果內(nèi)輪廓還包含輪廓乍钻,那就把這些內(nèi)輪廓放到頂層去。

表示一條輪廓的方法(method):

– CV_CHAIN_APPROX_NONE:把輪廓上所有的點(diǎn)存儲铭腕。

– CV_CHAIN_APPROX_SIMPLE:只存儲水平银择,垂直,對角直線的起始點(diǎn)谨履。對drawContours函數(shù)來說欢摄,這兩種方法沒有區(qū)別熬丧。

– CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS:實(shí)現(xiàn)的“Teh-Chin chain approximation algorithm.
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
  /// 找到輪廓
findContours( src, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

二笋粟、通過drawContours畫出連通域輪廓

void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )

函數(shù)參數(shù)詳解:

image表示目標(biāo)圖像怀挠,
contours表示輸入的輪廓組,每一組輪廓由點(diǎn)vector構(gòu)成害捕,
contourIdx指明畫第幾個輪廓绿淋,如果該參數(shù)為負(fù)值,則畫全部輪廓尝盼,
數(shù)color為輪廓的顏色吞滞,
thickness為輪廓的線寬,如果為負(fù)值或CV_FILLED表示填充輪廓內(nèi)部盾沫,
lineType為線型裁赠,
hierarchy為輪廓結(jié)構(gòu)信息,

Mat contoursImage(im.rows,im.cols,CV_8U,Scalar(255));
for(int i=0;i<contours.size();i++){
   if(hierarchy[i][3]!=-1)
       drawContours(contoursImage,contours,i,Scalar(0),3);
}
int idx = 0;
    for( ; idx >= 0; idx = hierarchy[idx][0] )
    {
        Scalar color( rand()&255, rand()&255, rand()&255 );
        drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );
    }

三赴精、其他相關(guān)函數(shù)

1佩捞、獲取包圍對象的垂直矩陣

cv::Rect r0= cv::boundingRect(cv::Mat(contours[0]));
cv::rectangle(result,r0,cv::Scalar(0),2);

2、獲取包圍對象的最小圓

float radius;
Point2f center;
minEnclosingCircle(Mat(contours[1]), center, radius);
circle(result, Point(center), static_cast<int>(radius), Scalar(255), 2);

3蕾哟、獲取包圍對象的多邊形

std::vector<cv::Point> poly;
cv::approxPolyDP(cv::Mat(contours[2]),poly,
5, // accuracy of the approximation, 輪廓點(diǎn)之間最大距離數(shù)
true); // yes it is a closed shape
vector<Point>::const_iterator itp = poly.begin();
while (itp != (poly.end() - 1))
{
    line(result, *itp, *(itp + 1), Scalar(255), 2);
    ++itp;
}
vector<vector<Point>> contours_poly(contours.size());//用于存放折線點(diǎn)集
 
    for (int i = 0; i<contours.size(); i++)
    {
        approxPolyDP(Mat(contours[i]), contours_poly[i], 15, true);
        drawContours(dstImg, contours_poly, i, Scalar(0, 255, 255), 2, 8);  //繪制
    }

4一忱、獲得包圍對象的凸包
原理

std::vector<cv::Point> hull;
cv::convexHull(cv::Mat(contours[3]),hull); //clockwise:操作方向,當(dāng)標(biāo)識符為真時谭确,輸出凸包為順時針方向帘营,否則為逆時針方向。 
//returnPoints:操作標(biāo)識符逐哈,默認(rèn)值為true芬迄,此時返回各凸包的各個點(diǎn),否則返回凸包各點(diǎn)的指數(shù)鞠眉,當(dāng)輸出數(shù)組時std::vector時薯鼠,此標(biāo)識被忽略。
vector<Point>::const_iterator ith = hull.begin();
while (ith != (hull.end() - 1)){
    line(result, *ith, *(ith + 1), Scalar(255), 2);
    ++ith;
}
line(result, *ith, *(hull.begin()), Scalar(255), 2);
vector<vector<Point>>hull(contours.size());
for (int i = 0; i < contours.size(); i++){
      convexHull(Mat(contours[i]), hull[i], false);
 }
 //繪制輪廓和凸包
 Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++){
      Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
      drawContours(drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point());
 }

5械蹋、輪廓中的所有點(diǎn)
一個想法:先取得輪廓出皇,然后新建一個圖像,在新圖像上畫出輪廓以及填充的圖像哗戈,遍歷這幅圖像郊艘,如果有顏色就是在輪廓內(nèi)。
另一個方法1
另一個方法2

6唯咬、最小面積的外接矩形(可傾斜)
minAreaRect(InputArray points);

  /// 對每個找到的輪廓創(chuàng)建可傾斜的邊界框和橢圓
  vector<RotatedRect> minRect( contours.size() );
  vector<RotatedRect> minEllipse( contours.size() );
 
  for( int i = 0; i < contours.size(); i++ )
     { minRect[i] = minAreaRect( Mat(contours[i]) );
       if( contours[i].size() > 5 )
         { minEllipse[i] = fitEllipse( Mat(contours[i]) ); }
     }
 
  /// 繪出輪廓及其可傾斜的邊界框和邊界橢圓
  Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
  for( int i = 0; i< contours.size(); i++ )
     {
       Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
       // contour
       drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
       // ellipse
       ellipse( drawing, minEllipse[i], color, 2, 8 );
       // rotated rectangle
       Point2f rect_points[4];
       minRect[i].points( rect_points );
       for( int j = 0; j < 4; j++ )
          line( drawing, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );

7纱注、可傾斜橢圓(見上)
fitEllipse(InputArray points);
8胆胰、輪廓內(nèi)連通區(qū)域的面積和長度
double contourArea(InputArray contour, bool oriented=false )

InputArray contour:輸入的點(diǎn)狞贱,一般是圖像的輪廓點(diǎn)
bool oriented=false:表示某一個方向上輪廓的的面積值,順時針或者逆時針蜀涨,一般選擇默認(rèn)false

double arcLength(InputArray curve, bool closed)瞎嬉;

curve:輸入二維點(diǎn)集蝎毡,并用std::vector or Mat存儲;
closed:該標(biāo)志指明曲線是否封閉氧枣;

contourArea(contours[i]);
arcLength( contours[i], true );

9沐兵、判斷一個點(diǎn)是否在一個多邊形內(nèi)
pointPolygonTest
double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)

用于測試一個點(diǎn)是否在多邊形中
當(dāng)measureDist設(shè)置為true時,若返回值為正便监,表示點(diǎn)在多邊形內(nèi)部扎谎,返回值為負(fù),表示在多邊形外部烧董,返回值為0毁靶,表示在多邊形上。
當(dāng)measureDist設(shè)置為false時逊移,若返回值為+1老充,表示點(diǎn)在多邊形內(nèi)部,返回值為-1螟左,表示在多邊形外部啡浊,返回值為0,表示在多邊形上胶背。

10巷嚣、比較兩個形狀的相似性
原理:OpenCV提供的一個根據(jù)計算比較兩張圖像Hu不變距的函數(shù),函數(shù)返回值代表相似度大小钳吟,完全相同的圖像返回值是0廷粒,返回值最大是1。這可以用在在一堆照片中搜索出兩張相同或相同程度最大的圖像红且。
double cvMatchShapes(const void * object1, const void * object2, int method, double parameter = 0);

第一個參數(shù)是待匹配的物體1坝茎,第二個是待匹配的物體2
第三個參數(shù)method有三種輸入:
CV_CONTOURS_MATCH_I1
CV_CONTOURS_MATCH_I2
CV_CONTOURS_MATCH_I3
即三種不同的判定物體相似的方法

double ffff=matchShapes(contours[0], contours[0], CV_CONTOURS_MATCH_I3,1.0); //也可以輸入灰度圖
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市暇番,隨后出現(xiàn)的幾起案子嗤放,更是在濱河造成了極大的恐慌,老刑警劉巖壁酬,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件次酌,死亡現(xiàn)場離奇詭異,居然都是意外死亡舆乔,警方通過查閱死者的電腦和手機(jī)岳服,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來希俩,“玉大人吊宋,你說我怎么就攤上這事⊙瘴洌” “怎么了璃搜?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵文兑,是天一觀的道長。 經(jīng)常有香客問我腺劣,道長,這世上最難降的妖魔是什么因块? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任拯坟,我火速辦了婚禮絮短,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己鸿脓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布寇甸。 她就那樣靜靜地躺著极阅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雁佳。 梳的紋絲不亂的頭發(fā)上脐帝,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天,我揣著相機(jī)與錄音糖权,去河邊找鬼堵腹。 笑死,一個胖子當(dāng)著我的面吹牛星澳,可吹牛的內(nèi)容都是我干的疚顷。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼禁偎,長吁一口氣:“原來是場噩夢啊……” “哼腿堤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起如暖,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤笆檀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后盒至,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體误债,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年妄迁,在試婚紗的時候發(fā)現(xiàn)自己被綠了寝蹈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡登淘,死狀恐怖箫老,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情黔州,我是刑警寧澤耍鬓,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布阔籽,位于F島的核電站,受9級特大地震影響牲蜀,放射性物質(zhì)發(fā)生泄漏笆制。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一涣达、第九天 我趴在偏房一處隱蔽的房頂上張望在辆。 院中可真熱鬧,春花似錦度苔、人聲如沸匆篓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸦概。三九已至,卻和暖如春甩骏,著一層夾襖步出監(jiān)牢的瞬間窗市,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工饮笛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谨设,地道東北人。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓缎浇,卻偏偏與公主長得像扎拣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子素跺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容