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