【Opencv4快速入门】轮廓检测findContours
发布时间
阅读量:
阅读量
7.2 轮廓检测findContours
- 7.2.1 轮廓查找findContours
- 7.2.2 轮廓绘制drawContours
图像轮廓是指图像中对象的边界,是图像目标的外部特征,这个特征对于图像分析、目标识别和理解更深层次的含义具有重要的作用。
7.2.1 轮廓查找findContours
图像的轮廓补单能够提供物体的边缘,而且能提供物体边缘之间的层次关系及拓扑关系。我们可以将图像轮廓发现简单理解为带有结构关系的边缘检测。例如如下图像,含有五个边缘:

我们为这五个边缘编号,分别为0,1,2,3,4,如下:

图中5个不联通的图像边缘,分别是0,1,2,3,4。其中0号轮廓的层级最高,其次是1,3,4号,是并列的层级。最后由于2号被1号包围,所以2号的层级最低。不同轮廓之间的层级关系可以用如下图来描述:

为了更好的表明轮廓之间的层级关系,通常使用四个参数cv::Vec4i来描述,这四个参数的含义依次为:
- 同层下一个子轮廓的索引(无下一个子轮廓则索引为-1)
- 同层上一个子轮廓的索引(无上一个子轮廓则索引为-1)
- 下一层顶一个子轮廓的索引(无则索引为-1)
- 上层父轮廓的索引(无父轮廓则索引为-1)
有了上述定义后,图中5个轮廓的关系便清楚了,
轮廓0:[-1, -1, 1, -1]
轮廓1:[3, -1, 2, 0]
轮廓2:[-1, -1, -1, 1]
轮廓3:[4, 1, -1, 0]
轮廓4:[-1, 3, -1, 0]
Opencv中的void findContours函数用于从二值化图像中寻找轮廓,并返回轮廓的层级关系。由于输入是二值化图像,所以图像要提前经过灰度化、滤波、二值化等操作生成二值化图像。
7.2.2 轮廓绘制drawContours
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char const *argv[]) {
cv::Mat img = cv::imread("image/README/1698488030768.png");
if (img.empty()) {
std::cout << "Please check the input image!" << std::endl;
return 0;
}
cv::imshow("src", img);
cv::Mat gray, binary;
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(gray, gray, cv::Size(3, 3), 4, 4);
cv::threshold(gray, binary, 170, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
// find and draw
std::vector<std::vector<cv::Point>> contours; // contours
std::vector<cv::Vec4i> hierarchy; // save the contours
cv::findContours(binary, contours, hierarchy, cv::RETR_TREE,
cv::CHAIN_APPROX_SIMPLE, cv::Point());
// blue green red yellow pink
cv::Scalar color_set[5] = {cv::Scalar(255, 0, 0), cv::Scalar(0, 255, 0),
cv::Scalar(0, 0, 255), cv::Scalar(0, 255, 255),
cv::Scalar(255, 0, 255)};
// draw
for (int i = 0; i < contours.size(); i++) {
cv::drawContours(img, contours, i, color_set[i % 5], 2);
}
// print
for (int i = 0; i < hierarchy.size(); i++) {
std::cout << hierarchy[i] << std::endl;
}
cv::imshow("results", img);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
最终效果如下:

全部评论 (0)
还没有任何评论哟~
