OpenCV實現(xiàn)輪廓的發(fā)現(xiàn)
前言:
當我們通過閾值分割提取到圖像中的目標物體后,我們就需要通過邊緣檢測來提取目標物體的輪廓,使用這兩種方法基本能夠確定物體的邊緣或者前景。接下來,我們通常需要做的是擬合這些邊緣的前景,如擬合出包含前景或者邊緣像素點的最小外包矩形、圓、凸包等幾何形狀,為計算它們的面積或者模板匹配等操作打下堅實的基礎。
一、查找、繪制輪廓
首先了解一下輪廓的定義。一個輪廓代表一系列的點(像素),這一系列的點構成一個有序的點集,所以可以把一個輪廓理解為一個有序的點集。
1.1 findContour()函數(shù)
在OpenCV中,提供了一個函數(shù)返回或者輸出一個有序的點集或者有序的點集的集合(指多個有序的點集),函數(shù)findContour是從二值圖像中來計算輪廓的,它可以使用Canny()函數(shù)處理的圖像,因為這樣的圖像含有邊緣像素;也可以使用threshold()或者adaptiveThreshold()處理后的圖像,其邊緣隱含在正負區(qū)域的交界處。這個函數(shù)的聲明如下:
void findContours(InputOutputArray image,OutputArrayOfArrays contours,OutputArray hierarchy,int mode,int method,Point offset = Point());
其參數(shù)解釋如下:
(1)image:單通道圖像矩陣,可以是灰度圖,但更常用的是二值圖像,一般是經過Canny、拉普拉斯等邊緣檢測算子處理過的二值圖像;
(2)contours:vector<vector<Point>>類型,是一個向量,并且是一個雙重向量,向量內每個元素保存了一組由連續(xù)的Point點構成的點的集合的向量,每一組Point點集就是一個輪廓。有多少輪廓,向量contours就有多少元素。
(3)hierarchy:vector<Vec4i> 類型, Vec4i是Vec<int,4>的別名,即容器內每一個元素都是一個包含了4個int型變量的向量,所以從定義上看,hierarchy也是一個向量,向量內每個元素保存了一個包含4個int整型的數(shù)組。向量hiararchy內的元素和輪廓向量contours內的元素是一一對應的,向量的容量相同。hierarchy向量內每一個元素的4個int型變量——hierarchy[i][0] ~hierarchy[i][3],分別表示第i個輪廓的后一個輪廓、前一個輪廓、父輪廓、內嵌輪廓的索引編號。如果當前輪廓沒有對應的后一個輪廓、前一個輪廓、父輪廓或內嵌輪廓的話,則hierarchy[i][0] ~hierarchy[i][3]的相應位被設置為默認值-1。
(4)mode:int類型的,定義輪廓的檢索模式:
取值一:CV_RETR_EXTERNAL只檢測最外圍輪廓,包含在外圍輪廓內的內圍輪廓被忽略;
取值二:CV_RETR_LIST 檢測所有的輪廓,包括內圍、外圍輪廓,但是檢測到的輪廓不建立等級關系,彼此之間獨立,沒有等級關系,這就意味著這個檢索模式下不存在父輪廓或內嵌輪廓,所以hierarchy向量內所有元素的第3、第4個分量都會被置為-1,具體下文會講到;
取值三:CV_RETR_CCOMP 檢測所有的輪廓,但所有輪廓只建立兩個等級關系,外圍為頂層,若外圍內的內圍輪廓還包含了其他的輪廓信息,則內圍內的所有輪廓均歸屬于頂層;
取值四:CV_RETR_TREE, 檢測所有輪廓,所有輪廓建立一個等級樹結構。外層輪廓包含內層輪廓,內層輪廓還可以繼續(xù)包含內嵌輪廓。
(5) method:int類型,定義輪廓的近似方法:
取值一:CV_CHAIN_APPROX_NONE 保存物體邊界上所有連續(xù)的輪廓點到contours向量內;
取值二:CV_CHAIN_APPROX_SIMPLE 僅保存輪廓的拐點信息,把所有輪廓拐點處的點保存入contours向量內,拐點與拐點之間直線段上的信息點不予保留;
取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法;
(6) Point:偏移量,所有的輪廓信息相對于原始圖像對應點的偏移量,相當于在每一個檢測出的輪廓點上加上該偏移量,并且Point還可以是負值。
注意事項:
顯然,從函數(shù)名可以看出“尋找輪廓”的意思。我們可以通過邊緣檢測算法得到邊緣二值圖或者前景二值圖,二值圖的邊緣像素或者前景像素就可以被看出是由多個輪廓(點集)組成的。函數(shù)findContours的作用就是將二值圖的邊緣像素或者前景像素拆分成多個輪廓,便于分開討論每一個輪廓,其中參數(shù)image代表一張二值圖,contours代表輸出的多個輪廓。對于該函數(shù)的C++API,對一個輪廓的描述用vector<Point>,那么多個輪廓(多個點集)如何表示呢?即參數(shù)contours是什么數(shù)據結構呢?在C++API中,用vector<vector<Point>>描述多個輪廓,即將多個輪廓存在一個vector中。
1.2 drawContours()函數(shù)
OpenCV中也提供了一個函數(shù)來繪制findContours所找到的多個輪廓,其函數(shù)聲明如下:
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ù)解釋如下:
(1)image: 代表輸入的圖像矩陣,將輪廓畫在該圖上;
(2)contours:是得到的一系列點的集合,代表多個輪廓;
(3)contourIdx:是一個索引,代表繪制contours中的第幾個輪廓;
(4) color:被填充的顏色,單色可以設置為Scalar(255)等;
(5)thickness: 所畫Contour的線條粗細,如果該參數(shù)值小于0,則表示填充整個輪廓內的區(qū)域;
(6)lineType: 線的連通性;
(7)hierarchy:可選層次信息結構,這里面是findContours所的到的基于Contours的層級信息;
(8)maxLevel: 繪制輪廓的最大等級。如果等級為0,繪制單獨的輪廓。如果為1,繪制輪廓及在其后的相同的級別下輪廓。如果值為2,所有的輪廓。如果等級為2,繪制所有同級輪廓及所有低一級輪廓,諸此種種。如果值為負數(shù),函數(shù)不繪制同級輪廓,但會升序繪制直到級別為abs(max_level)-1的子輪廓
(9)offset:照給出的偏移量移動每一個輪廓點坐標.當輪廓是從某些感興趣區(qū)域(ROI)中提取的然后需要在運算中考慮ROI偏移量時,將會用到這個參數(shù)。
二、 演示代碼
實例步驟
- 轉灰度
- canny得到二值圖像
- findcontours尋找輪廓
- drawcontours畫輪廓
我們編寫演示代碼如下:
#include<opencv2\opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
Mat src1, src2,gray_img, dst;
int value = 100;
int max_value = 255;
void demo(int, void*);
int main()
{
//發(fā)現(xiàn)輪廓--> cvtcolor-->canny得到二值圖像-->findcontours(尋找輪廓)-->drawcontous()
src1 = imread("C:\\Users\\馬迎偉\\Desktop\\yuan1.jpg");
//src2 = imread("C:\\Users\\馬迎偉\\Desktop\\heibao1.png");
if (src1.empty())
{
printf("cannot load!!\n");
system("pause");
return -1;
}
namedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input",src1);
namedWindow("output", CV_WINDOW_AUTOSIZE);
cvtColor(src1,gray_img,CV_BGR2GRAY);
createTrackbar("creattrackbar","output",&value,max_value,demo);
demo(0, 0);
waitKey(0);
return 0;
}
void demo(int, void*)
{
//將圖像表現(xiàn)在src3上
Mat src3 = Mat::zeros(src1.size(),CV_8UC3);
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
Canny(gray_img,src2,value,value*2,3,false );
findContours(src2,contours,RETR_TREE,CHAIN_APPROX_SIMPLE,Point(0,0));
RNG rng(12345);
for (size_t i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
drawContours(src3, contours, i,color,1,LINE_AA,hierarchy,0,Point(0,0));
}
imshow("output",src3);
}
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
深入剖析設計模式中的組合模式應用及在C++中的實現(xiàn)
這篇文章主要介紹了設計模式中的組合模式應用及在C++中的實現(xiàn),組合模式可以清晰地反映出遞歸構建樹狀的組合結構,需要的朋友可以參考下2016-03-03
Cocos2d-x UI開發(fā)之CCControlSlider控件類使用實例
這篇文章主要介紹了Cocos2d-x UI開發(fā)之CCControlSlider控件類使用實例,本文代碼中包含大量注釋講解了CCControlSlider控件類的使用,需要的朋友可以參考下2014-09-09
詳細對比C語言中的chmod()函數(shù)和fchmod()函數(shù)
這篇文章主要介紹了C語言中的chmod()函數(shù)和fchmod()函數(shù)的詳細對比,兩個都是用于修改文件權限但是請注意實際使用上的差異,需要的朋友可以參考下2015-09-09
Linux網絡編程之基于UDP實現(xiàn)可靠的文件傳輸示例
這篇文章主要介紹了Linux網絡編程之基于UDP實現(xiàn)可靠的文件傳輸示例,是很實用的技巧,需要的朋友可以參考下2014-08-08
c語言實現(xiàn)數(shù)組循環(huán)左移m位
這篇文章主要介紹了c語言實現(xiàn)數(shù)組循環(huán)左移m位,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
Android App仿微信界面切換時Tab圖標變色效果的制作方法
這篇文章主要介紹了Android App仿微信界面切換時Tab圖標變色效果的制作方法,重點講解了圖標的繪制技巧,需要的朋友可以參考下2016-04-04

