当前位置:网站首页>47_Opencv中的轮廓查找 cv::findContours()
47_Opencv中的轮廓查找 cv::findContours()
2022-07-07 13:51:00 【sinat_41752325】
一个轮廓对应一系列点,这些点以某种方式表示图像中的一条曲线。OpenCV中,轮廓用标准模板库向量vector<>表示,最常见的是用一系列二维顶点(vector<cv::Point>或vector<cv::Point2f>表示。
函数cv::findContours()从二维图像中计算轮廓,它处理的图像可以是从cv::Canny()函数得到的有边缘像素的图像,或是从cv::threshold()及cv::adaptiveThreshold()函数得到的图像。
1. 查找轮廓 cv::findContours
cv::findContours()函数原型:
void cv::findContours(
cv::InputOutputArray image, // input binary 8-bit single channel
cv::InputOutputArrayOfArrays contours, // vector of vectors or points
cv::OutputArray hierarchy, // (optional) topology information
int mode, // contour retrieval mode
int method, // approximation method
cv::Point offset = cv::Point() // (optional) offset every point
);
void cv::findContours(
cv::InputOutputArray image, // input binary 8-bit single channel
cv::OutputArrayOfArrays contours, // vector of vectors or pointd
int mode, // contour retrieval mode
int method, // approximation method
cv::Point offset = cv::Point() // (optional) offset every point;
);
参数image是输入图像,必须是8位单通道图像,应该被转化成二值的。cv::findContours()函数会改变该参数,所以如果该图像将来还有用,应该复制之后再传给cv::findContours()。
参数contours是一组数组,多数情况下是一个或多个标准模板库vector。该参数是找到的轮廓。例如在一个轮廓vector中,contours[i]是一条轮廓,而contours[i][j]是轮廓contours[i]上的一个点。
参数hierarchy是可选项,如果给出了该参数,hierarchy 将输出所有轮廓的树结构。这个参数是一个数组,每条轮廓对应数组中的一个值。数组中的每个值都是一个四元数组,每个元素代表一个与当前结点有特定链接的结点,每个元素代表的含义如下:
索引 | 含义 |
0 | 同级的下一条轮廓 |
1 | 同级的前一条轮廓 |
2 | 下级的第一个子结点 |
3 | 上级的父节点 |
参数mode表示期望的轮廓提取方式,有4种:
- cv::RETR_EXTERNAL:只检索最外层轮廓,并且该轮廓不与其他轮廓连接。
- cv::RETR_LIST:检索所有轮廓并保存到表中。
- cv::RETR_CCOMP:检索所有的轮廓,并将他们组织成双层结构。
- cv::RETR_TREE:检索所有轮廓并重新建立网状轮廓结构。
参数method表示轮廓如何表达,可选择的方式有:
- cv::CHAIN_APPROX_NONE:将轮廓编码中的所有点转换为点,这个操作会产生大量的点,每个点都将成为前一个点的8个邻点之一,不会减少返回的点数。
- cv::CHAIN_APPROX_SIMPLE:压缩水平、垂直、斜的部分,只保留最后一个点,许多特殊情况下,这一操作将大大减少返回的点数。极端例子是,对于一个沿着x-y方向的矩形,只返回4个点。
- cv::CHAIN_SPPROX_TC89_L1 or cv::CHAIN_APPROX_TC89_KCOS:使用Teh-chin链逼近算法中的一个。Teh-Chin算法是一种更复杂且计算密集型的算法,用于减少返回的点数。运行T-C不需要额外的参数。
参数offset是可选项,如果给出这个参数,返回的轮廓中所有的点会根据参数值发生偏移。通常用于两种情况下:一当希望从兴趣区域中提取的轮廓用原图坐标系表达时,二当希望从原图中提取的轮廓用图像子区域坐标系表达时。
2. 绘制轮廓 cv::drawContours
查找完轮廓后最常用的功能是在屏幕上绘制检测到的轮廓,可以使用函数cv::drawContours()函数完成。函数原型:
void cv::drawContours(
cv::InputOutputArray image, // will draw on input image
cv::InputArrayOfArrays contours, // vector of vectors or pointd
int contourIdx, // contour to draw (-1 is all)
const cv::Scalar &color, // color for contours
int thickness = 1, // thickness for contour lines
int lineType = 8, // connectedness ('4' or '8')
cv::InputArray hierarchy = cv::noArray(), // optional from find contours
int maxLevel = INT_MAX, // max descent in hierarchy
cv::Point offset = cv::Point() // (optional) offset all points
);
参数image,待绘制轮廓的图像。
参数contour是要绘制的轮廓,该参数的类型与cv::findContours()的输出contour相同,是储存在列表中的点。
参数contourIdx用于告诉cv::drawContours()需要绘制的是contours参数中的某一条轮廓还是全部轮廓,如果是一个正数,则对应的轮廓将被绘制,如果为负数,所有轮廓都将被绘制。
参数color、thickness、lineType的功能与其他用于绘制的函数中的对应参数功能相同,分别表示绘制的颜色,绘制的线的粗细,绘制线的类型(四联通/八连通/AA线)。
参数hierarchy对应cv::findContours()函数输出的层次。参数hierarchy和参数maxLevel共同起作用。maxLevel限制将在图上绘制的轮廓层次深度,maxLevel=0表示只绘制第0层的轮廓,设为其他非0正数,表示绘制最高层以下相同数量层级的轮廓。如果希望在连接成分时只显示最外层轮廓,很有帮助。
参数offset可选,当轮廓坐标系被转换成执行坐标系或其他局部坐标系的时候,这个特性很有用。
使用VS2010+opencv2.4.9时,32位测试时总是会崩溃,提示堆被破坏,并且函数得到的轮廓也有问题,用64位不会崩溃,得到的轮廓也是对的。
3. 使用实例:查找轮廓并逐条绘制
#include <opencv.hpp>
#include <algorithm>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
struct AreaCmp{
AreaCmp(const vector<float>& _areas):areas(&_areas){}
bool operator()(int a,int b) const {return (*areas)[a] > (*areas)[b];}
const vector<float>* areas;
};
int main(int argc, char *argv[])
{
Mat img,img_edge,img_color;
img = cv::imread(argv[1],cv::IMREAD_GRAYSCALE);
if(img.empty())
{
std::cout << "Load image fail," << argv[1] << std::endl;
getc(stdin);
return -1;
}
cv::threshold(img,img_edge,128,255,cv::THRESH_BINARY);
cv::namedWindow("Image after threshold",cv::WINDOW_NORMAL);
cv::imshow("Image after threshold",img_edge);
cv::vector< cv::vector<cv::Point> > contours;
vector<cv::Vec4i> hierarchy;
// 查找轮廓
cv::findContours(img_edge,contours,hierarchy,cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE);
cout << "\nTotal contours detected:" << contours.size() << endl;
vector<int> sortIdx(contours.size());
vector<float> areas(contours.size());
for(int n=0;n<(int)contours.size();n++)
{
sortIdx[n] = n;
areas[n] = contourArea(contours[n],false); // 计算轮廓面积
}
// sort contours so that largest contours go first
std::sort(sortIdx.begin(),sortIdx.end(),AreaCmp(areas));
for(int n=0;n<(int)sortIdx.size();n++)
{
int idx = sortIdx[n];
cv::cvtColor(img,img_color,cv::COLOR_GRAY2BGR);
// 绘制轮廓
cv::drawContours(img_color,contours,idx,cv::Scalar(0,0,255),2,8,hierarchy,0); // 逐条绘制轮廓
cout << "Contour #" << idx << ": area=" << areas[idx] << ", nvertices=" << contours[idx].size() << endl;
cv::namedWindow(argv[0],cv::WINDOW_NORMAL);
cv::imshow(argv[0],img_color);
int k;
if((k = cv::waitKey()&255) == 27)
break;
}
std::cout << "Finished all contours\n" ;
getc(stdin);
return 0;
}
边栏推荐
- Keil5 does not support online simulation of STM32 F0 series
- Introduction to pyGame games
- Using eating in cocos Creator
- Unity的三种单例模式(饿汉,懒汉,MonoBehaviour)
- Particle effect for ugui
- C Alibaba cloud OSS file upload, download and other operations (unity is available)
- nodejs package. JSON version number ^ and~
- U3D_ Infinite Bessel curve
- Cocos uses custom material to display problems
- How to deploy the super signature distribution platform system?
猜你喜欢
JS array foreach source code parsing
LeetCode2_ Add two numbers
Wireless sensor networks -- ZigBee and 6LoWPAN
[wechat applet] Chapter (5): basic API interface of wechat applet
深度之眼(七)——矩阵的初等变换(附:数模一些模型的解释)
Application example of infinite list [uigridview]
OpenGL's distinction and understanding of VAO, VBO and EBO
Vite path alias @ configuration
How to create Apple Developer personal account P8 certificate
Three. JS introductory learning notes 05: external model import -c4d into JSON file for web pages
随机推荐
webgl_ Enter the three-dimensional world (1)
The significance of XOR in embedded C language
Three. JS introductory learning notes 07: external model import -c4d to JSON file for web pages -fbx import
Apache Doris just "graduated": why should we pay attention to this kind of SQL data warehouse?
Matlab experience summary
Use moviepy Editor clips videos and intercepts video clips in batches
Postman generate timestamp, future timestamp
OpenGL's distinction and understanding of VAO, VBO and EBO
SPI master rx time out中断
持续创作,还得靠它!
Unity3D_ Class fishing project, bullet rebound effect is achieved
Numpy -- data cleaning
SysOM 案例解析:消失的内存都去哪了 !| 龙蜥技术
一个普通人除了去工厂上班赚钱,还能干什么工作?
尤雨溪,来了!
Syntaxhighlight highlights the right scroll bar
Enterprise log analysis system elk
numpy--疫情数据分析案例
Three. JS introductory learning notes 11:three JS group composite object
Cocos creator collision and collision callback do not take effect