学习OpenCV 13 轮廓

本文详细介绍了如何使用OpenCV进行轮廓查找,包括Contour Finding、Contour Hierarchies及其四元数组解析,以及如何通过cv::findContours()函数找到并绘制轮廓。同时探讨了轮廓层次结构在图像处理中的应用。
摘要由CSDN通过智能技术生成

学习OpenCV 13 轮廓

Canny之类的边缘检测算法可以根据像素间差异检测出轮廓边界的像素,但它并没有将轮廓作为一个整体进行处理。而我们的任务就是要将这些边缘像素合成轮廓。

轮廓查找Contour Finding

一个轮廓对应一系列点,这些点以一定方式表示图像中的一条曲线。有多种方式可以表示一条曲线,在OpenCV中,轮廓用标准模板库(STL)向量vector<>表示,向量中每个值都包含轮廓上下一个点的位置信息,用一系列二维顶点(vector<cv::Point>或vector<cv::Point2f>)表示轮廓是最常见的方式,但不限于此。

cv::findContours()从二值图像(binary image)中计算轮廓,它处理的图像可以是从cv::Canny()函数得到的有边缘像素的图像,或是从cv::threshold()及cv::adaptiveThreshold()函数得到的图像。

轮廓层次Contour Hierarchies

下图分别是一张输入cv::findContours()函数的测试图像(左图)。图中有五块颜色区域(A,B,C,D,E),共有9条轮廓。每条轮廓都有一组输出列表表示(右上角图—轮廓参数)。也可以选择生成一组层次表达(右下角图—层次参数)。在右下角图中(轮廓树),节点表示一条轮廓,根据每个点在层次队列中的四元数组索引,连接都做了相应标记。

轮廓层次列表中四元数组

OpenCV用数组(通常vector)表示轮廓树,其中每个值都代表一条特定轮廓。在该数组中,每个值都包含一个四整数组,即层次列表中的每个节点都由四个整数组成,每个数都代表在层次列表中与当前节点有特定关系的另一个节点。

轮廓层次列表中四元素数组中每个元素含义
索引Index含义Meaning
0同级下一条轮廓Next Contour
1同级前一条轮廓Previous Contour
2下级的第一个子节点First Child
3上级的父节点Parent

 

 

 

 

 

 

而当节点间不存在这种关系时,数组中相应元素设为-1,如根节点的3号元素的值将设为-1,因为根节点没有父节点。

使用cv::findContours()查找轮廓

void cv::findContours(
    cv::InputArray             image,              //输入8位单通道二值图像
    cv::OutputArrayOfArrays    contours,           //输出轮廓数组
    cv::OutputArray            hierarchy,          //(可选项)输出轮廓树结构
    int                        mode,               //轮廓提取方式,有4种
    int                        method,             //轮廓如何被表达
    cv::point                  offset=cv::Point()  //(可选项)偏移
)

void cv::findContours(
    cv::InputArray             image,              //输入8位单通道二值图像
    cv::OutputArrayOfArrays    contours,           //输出轮廓数组
    int                        mode,               //轮廓提取方式,有4种
    int                        method,             //轮廓如何被表达
    cv::point                  offset=cv::Point()  //(可选项)偏移
)

第一个参数输入图像必须是8位单通道二值图像。

第二个参数是输出轮廓数组,在一个轮廓vector中,contours[i]是一条轮廓,contours[i][j]是contours[i]中的一个点。

参数hierarchy是可选项,输出轮廓的树结构。这一输出为一个数组,每个轮廓对应数组中一个值,每个值都是上面的四元数组。

参数mode告诉OpenCV轮廓提取方式,mode有4种:

  1. cv::RETR_EXTERNAL 只检索最外层轮廓。
  2. cv::RETR_LIST 检索所有轮廓并保存到表中。
  3. cv::RETR_CCOMP 检索所有轮廓并组织成双层结构。
  4. cv::RETR_TREE 检索所有轮廓并重新建立网状轮廓结构。

绘制轮廓Drawing Contours

void cv::drawContours(
    cv::InputOutputArray    image,                //待绘制轮廓的图像
    cv::InputArrayOfArrays  contours,             //要绘制的轮廓
    int                     contourIdx,           //正数则对应轮廓被绘制,负则所有轮廓被绘制
    const cv::Scalar&       color,                //轮廓颜色
    int                     thickness=1,          //轮廓粗细
    int                     lineType=8,           //轮廓的线种类
    cv::InputArray          hierarchy=noArray(),  //层次
    int                     maxLevel=INT_MAX,     //层次深度
    cv::Point               offset=cv::Point()    //偏移
)

绘制轮廓实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

Mat g_gray, g_binary;//灰度图像,二值图像
int g_thresh = 100;//阈值

void on_trackbar(int, void*) {
	threshold(g_gray, g_binary, g_thresh, 255, THRESH_BINARY);
	vector<vector<Point>>contours;
	findContours(g_binary, contours, noArray(), RETR_LIST, CHAIN_APPROX_SIMPLE);
	g_binary = Scalar::all(0);

	drawContours(g_binary, contours, -1, Scalar::all(255));
	imshow("Coutours", g_binary);
}

int main(int argc, char**argv) {
	Mat src = imread("D://somephotos//test.jpg");
	namedWindow("Resource", 1);
	imshow("Resource", src);
	cvtColor(src, g_gray, COLOR_BGR2GRAY);
	namedWindow("Contours", 1);

	createTrackbar("Threshold", "Contours", &g_thresh, 255, on_trackbar);
	on_trackbar(0, 0);

	waitKey();

	return 0;
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值