1、轮廓发现(或提取)
findContours(
InputOutputArray binImg, OutputArrayOfArrays contours,
OutputArray hierachy, int mode, int method, Point offset=Point()
)
参数解释:
第一个参数 binImg:输入8bit图像,0值像素值不变,非0的像素看成1;(变为二值图像)
第二个参数 contours:输出找到的轮廓对象
第三个参数 hierachy: 图像的拓扑结构
第四个参数 mode:轮廓返回的模式(RETR_TREE等)
CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略;
CV_RETR_LIST 检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系;
CV_RETR_CCOMP 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层;
CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。
第五个参数 method:发现方法(CHAIN_APPROX_SIMPLE等)
CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内;
CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留;
CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法;
第六个参数 offset://轮廓像素的位移(默认没有位移(0, 0)
2、轮廓绘制
drawContours(
InputOutputArray binImg, OutputArrayOfArrays contours,
Int contourIdx, const Scalar & color, int thickness, int lineType ,
InputArray hierarchy, int maxlevel, Point offset=Point()
)
参数解释:
第一个参数 binImg:输入图像
第二个参数 contours:找到的全部轮廓对象
第三个参数 contourIdx: 轮廓索引号
第四个参数 color:绘制颜色
第五个参数 thickness:绘制线宽
第六个参数 lineType:线的类型(默认8)
第七个参数 hierarchy:拓扑结构图
第八个参数 maxlevel:最大层数(0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓)
第九个参数 offset=Point():轮廓位移
3、代码实践
#include <opencv2/opencv.hpp>
#include<vector>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main()
{
Mat src_img, gray_img, dst_img;
int threshold_value = 100;
int threshold_max = 255;
RNG rang;
src_img = imread("D:\\03.jpg");
if (src_img.empty()){
return -1;
}
imshow("原图", src_img);
cvtColor(src_img, gray_img, CV_BGR2GRAY);
Mat canny_output;
Canny(gray_img, canny_output, threshold_value, threshold_max, 3, false);
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
findContours(canny_output, contours, hierachy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
dst_img = Mat::zeros(src_img.size(), CV_8UC3);
RNG rng(12345);
for (auto i = 0; i < contours.size(); ++i)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); //随机颜色
drawContours(dst_img, contours, i, color, 1, 8, hierachy, 0, Point(0, 0));
}
imshow("轮廓图", dst_img);
waitKey(0);
return 0;
}
加入二值化操作和形态学操作后代码如下:
#include <opencv2/opencv.hpp>
#include<vector>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main()
{
Mat src_img, gray_img, dst_img;
int threshold_value = 100;
int threshold_max = 255;
RNG rang;
src_img = imread("D:\\03.jpg");
if (src_img.empty()){
return -1;
}
imshow("原图", src_img);
cvtColor(src_img, gray_img, CV_BGR2GRAY);
#if 1
//可酌情加入
threshold(gray_img, gray_img, 200, 255, THRESH_BINARY|CV_THRESH_TRIANGLE);
imshow("二值化", gray_img);
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
erode(gray_img, gray_img, kernel, Point(-1, -1), 1);
dilate(gray_img, gray_img, kernel, Point(-1, -1), 1);
dilate(gray_img, gray_img, kernel, Point(-1, -1), 1);
imshow("膨胀", gray_img);
#endif
Mat canny_output;
Canny(gray_img, canny_output, threshold_value, threshold_max, 3, false);
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
findContours(canny_output, contours, hierachy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
dst_img = Mat::zeros(src_img.size(), CV_8UC3);
RNG rng(12345);
for (auto i = 0; i < contours.size(); ++i)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); //随机颜色
drawContours(dst_img, contours, i, color, 1, 8, hierachy, 0, Point(0, 0));
}
imshow("轮廓图", dst_img);
waitKey(0);
return 0;
}
4、参考
https://blog.youkuaiyun.com/weixin_41695564/article/details/80085012