【opencv學習筆記】029 之輪廓發現——findContours函數、drawContours函數詳解

目錄

一、前言

二、輪廓發現

1、輪廓發現

2、發現輪廓API

3、繪製輪廓API

4、代碼展示

5、執行結果


一、前言

繼續更新有關於opencv的基礎博客,即將更新完畢,想想有點開心呢!

如果想看其他有關於OpenCV學習方法介紹、學習教程、代碼實戰、常見報錯及解決方案等相關內容,可以直接看我的OpenCV分類:

【OpenCV系列】:https://blog.csdn.net/shuiyixin/article/category/7581855

如果你想了解更多有關於計算機視覺、OpenCV、機器學習、深度學習等相關技術的內容,想與更多大佬一起溝通,那就掃描下方二維碼加入我們吧!

 

二、輪廓發現

1、輪廓發現

輪廓我想大家都知道是個啥玩意了。主要是這個輪廓發現,單從字面意思理解,我們也知道,就是我們要發現物體的輪廓。

那對於opencv計算機視覺來說,輪廓發現就是通過對圖像進行處理之後,提取物體的輪廓的操作。想要提取圖像的輪廓,我們就肯定要先找到圖像的邊緣。

在opencv中,我們想要獲得圖像的輪廓,分爲兩部分操作:

(1)發現輪廓

(2)繪製輪廓

 

2、發現輪廓API

接下來我們先講一下發現輪廓的API。

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

函數參數含義如下:

(1)InputArray類型的image,8位單通道圖像。非零像素被視爲1。零像素保持爲0,因此圖像被視爲二進制。

(2)OutputArrayOfArrays類型的contours,檢測到的輪廓。每個輪廓都存儲爲點的矢量。

(3)OutputArray類型的hierarchy,圖該的拓撲結構,可選,該輪廓發現算法正是基於圖像拓撲結構實現。

(4)int類型的mode,輪廓檢索模式,參見cv::RetrievalModes

(5)int類型的method,輪廓近似法,參加cv::ContourApproximationModes。

(6)Point類型的offset,每個輪廓點的偏移量。如果從圖像感興趣區域中提取輪廓,然後在整個圖像上下文中對其進行分析,這將非常有用。默認(0, 0)沒有位移。

在opencv中,有該函數的一個重載函數,兩個函數的區別在於是否有第三個參數:

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

這兩個函數的真正區別在於:

需不需要輸出hierarchy層次結構(可用於分析輪廓間關係,一般比較少用到)。

3、繪製輪廓API

接下來我們講一下繪製輪廓的API。

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

函數參數含義如下:

(1)InputArray類型的image,目標圖像。

(2)OutputArrayOfArrays類型的contours,所有輸入輪廓。每個輪廓都存儲爲點向量。

(3)int類型的courtolidx,表示要繪製的輪廓的參數。如果爲負數,則繪製所有輪廓。

(4)Scalar類型的color,輪廓的顏色。

(5)int類型的thickness,繪製輪廓線的厚度。如果爲負值(例如,thickness=CV_FILLED),則繪製輪廓內部。

(6)int類型的lineType,線連接性。

(7)InputArray類型的hierarchy,關於層次結構的可選信息。只有當您只想繪製一些輪廓時才需要它(請參見maxLevel)。

(8)int類型的maxLevel,線連接性。繪製輪廓的最大級別。如果爲0,則僅繪製指定的輪廓。如果爲1,則函數將繪製輪廓和所有嵌套輪廓。如果是2,則函數將繪製等高線、所有嵌套等高線、所有嵌套到嵌套等高線等。只有當存在可用的層次結構時才考慮此參數。

(9)Point類型的offset,可選輪廓移動參數。按指定的偏移量移動所有繪製的等高線。

 

4、代碼展示

我們進行輪廓發現,主要有如下幾步流程:

(1)輸入圖像轉爲灰度圖像cvtColor

(2)使用Canny進行邊緣提取,得到二值圖像

(3)使用findContours尋找輪廓

(4)使用drawContours繪製輪廓

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

Mat src, dst;
const char* input_win = "【輸入圖像】";
const char* output_win = "【輸出圖像】";
int threshold_value = 100;
int threshold_max = 255;
RNG rng;

void Demo_Contours(int, void*);

int main()
{
	src = imread("E:/個人/學習/編程/C++/CPlusPlusTestProgram/LearnOpenCV/image/girl2.png");
	if (!src.data)
	{
		cout << "could not load image !";
		return -1;
	}
	namedWindow(input_win, CV_WINDOW_AUTOSIZE);
	namedWindow(output_win, CV_WINDOW_AUTOSIZE);
	imshow(input_win, src);
	cvtColor(src, src, CV_BGR2GRAY);

	const char* trackbar_title = "Threshold Value:";
	createTrackbar(trackbar_title, output_win, &threshold_value, threshold_max, Demo_Contours);
	Demo_Contours(0, 0);

	waitKey(0);
	return 0;
}

void Demo_Contours(int, void*) {
	Mat canny_output;
	vector<vector<Point>> contours;
	vector<Vec4i> hierachy;
	Canny(src, canny_output, threshold_value, threshold_value * 2, 3, false);
	findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

	dst = Mat::zeros(src.size(), CV_8UC3);
	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(dst, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));
	}
	imshow(output_win, dst);
}

 

5、執行結果

原圖
輪廓獲取

 

輪廓獲取

大家也可以自己嘗試一下呀,一定要多做練習!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章