使用了很久的drawContours,繪製一個輪廓向量基本只會用一種方法,類似如下的方式,傻傻地一個一個繪製。
for(int i = 0; i < contour_vec.size(); i++)
{
drawContours(blkImg, contour_vec, i, Scalar(255), -1);
}
不知道什麼時候勾動了哪根神經,想研究一下該函數的參數,看看有沒有其他的神奇用法,深入代碼看了一眼,還真有點收穫。代碼裏面對該函數的說明如下:
重點是綠色框裏的內容,也就是說,繪製一個輪廓向量,只要在第三個參數處填個-1,一句話搞定,相見恨晚呀!
另外需要注意的是,我們平時習慣在黑色背景下繪製白色輪廓,或白色背景繪製黑色輪廓,如果背景圖像就是單通道灰度圖,那麼這個函數中的color也只能是單通道的,只取第0個分量的灰度值,設置三通道的顏色是無意義的,因爲背景圖像已經決定了只取一個通道的,因此如果創建了一個單通道的背景圖,繪製時卻設置了彩色,比如Scalar(255,255,0),那麼實際生效的只有第一個分量,等效於Scalar(255)。
當然,你如果創建的是一個多通道圖像,那麼繪製輪廓時也就可以用彩色線條了。看下面的例子:
#include <iostream>
#include <vector>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("dots.jpg");
Mat grayImg, binImg;
cvtColor(img, grayImg, COLOR_BGR2GRAY);
//大津法進行二值化
threshold(grayImg, binImg, 0, 255, CV_THRESH_OTSU);
imshow("binImg", binImg);
waitKey(0);
//提取二值化圖像中的輪廓數據
vector<vector<Point> > contour_vec;
vector<Vec4i> hierarchy;
findContours(binImg, contour_vec, hierarchy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE);
cout << "contours number: " << contour_vec.size() << endl;
// 以前常用的for循環繪製輪廓
/*Mat blkImg(binImg.size(), CV_8UC1, Scalar(0));
for(int i = 0; i < contour_vec.size(); i++)
{
drawContours(blkImg, contour_vec, i, Scalar(255), -1);
} */
//繪製單通道輪廓圖像,背景爲白色,輪廓線條用黑色
Mat blkImg(binImg.size(), CV_8UC1, Scalar(255));
drawContours(blkImg, contour_vec, -1, Scalar(0), 2);
imshow("blkImg", blkImg);
waitKey(0);
imwrite("blkImg.bmp", blkImg);
//繪製彩色輪廓圖像,背景顏色爲藍綠色,輪廓線條爲紅色
Mat colorImg(binImg.size(), CV_8UC3, Scalar(255, 255, 0));
drawContours(colorImg, contour_vec, -1, Scalar(0,0,255), 3);
imshow("colorImg", colorImg);
waitKey(0);
imwrite("colorImg.bmp", colorImg);
return 0;
}
執行結果:
從左到右分別是原圖、單通道輪廓圖、三通道彩色輪廓圖。