前言
当我们通过阈值分割提取到图像中的目标物体后,我们就需要通过边缘检测来提取目标物体的轮廓,使用这两种方法基本能够确定物体的边缘或者前景。接下来,我们通常需要做的是拟合这些边缘的前景,如拟合出包含前景或者边缘像素点的最小外包矩形、圆、凸包等几何形状,为计算它们的面积或者模板匹配等操作打下坚实的基础。
注意:边缘和轮廓并不完全相同.
轮廓发现 ( find contour)
首先了解一下轮廓的定义。一个轮廓代表一系列的点(像素),这一系列的点构成一个有序的点集,所以可以把一个轮廓理解为一个有序的点集。
API 介绍
void findContours(InputOutputArray image,
OutputArrayOfArrays contours,
OutputArray hierarchy,
int mode,int method,
Point offset = Point());
轮廓绘制 ( draw contour)
API 介绍
void drawContours(InputOutputArray image,
InputArrayOfArrays contours,
int contourIdx,
const Scalar& color,
int thickness = 1,
int lineType = 8,
InputArray hierarchy = noArray(),
int maxLevel = INT_MAX,
Point offset = Point())
代码实现
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
Mat src_img, dst_img;
const string output_win = "找到的轮廓";
int threshold_value = 100;
int threshold_max = 255;
RNG rng;
void Demo_Contours(int, void*);
int main()
{
src_img = imread("tahiti.jpg");
imshow("image", src_img);
cvtColor(src_img, src_img, COLOR_BGR2GRAY);
Demo_Contours(0, 0);
waitKey(0);
return 0;
}
void Demo_Contours(int, void*)
{
Mat canny_output;
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
// Canny 边缘检测
Canny(src_img, canny_output, threshold_value, threshold_value * 2, 3, false);
// 轮廓发现
findContours(canny_output, contours, hierachy, RETR_TREE, 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, 2, 8, hierachy, 0, Point(0, 0));
}
imshow(output_win, dst_img);
}