使用了很久的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
#include
#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 > contour_vec;
vector 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;
}
执行结果:
从左到右分别是原图、单通道轮廓图、三通道彩色轮廓图。