目錄
一、前言
繼續更新有關於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、執行結果
大家也可以自己嘗試一下呀,一定要多做練習!