当前位置:网站首页>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;
}
边栏推荐
- It's different for rich people to buy a house
- Streaming end, server end, player end
- L'application à l'échelle de la normalisation mature des produits ai des compagnies maritimes, cimc, leader mondial de l'intelligence artificielle portuaire et maritime / intelligence artificielle des
- Shader basic UV operations, translation, rotation, scaling
- Getting started with webgl (2)
- 神经网络c语言中的指针是怎么回事
- After UE4 is packaged, mesh has no material problem
- C4D learning notes 3- animation - animation rendering process case
- Points for attention in porting gd32 F4 series programs to gd32 F3 series
- Numpy -- data cleaning
猜你喜欢
Keil5 does not support online simulation of STM32 F0 series
After UE4 is packaged, mesh has no material problem
Iterator and for of.. loop
深度之眼(六)——矩阵的逆(附:logistic模型一些想法)
Ue4/ue5 multi thread development attachment plug-in download address
融云斩获 2022 中国信创数字化办公门户卓越产品奖!
强化实时数据管理,英方软件助力医保平台安全建设
Streaming end, server end, player end
Three. JS introductory learning notes 11:three JS group composite object
Three. JS introductory learning notes 00: coordinate system, camera (temporarily understood)
随机推荐
How to deploy the super signature distribution platform system?
Bidding announcement: Panjin people's Hospital Panjin hospital database maintenance project
VS2005 strange breakpoint is invalid or member variable value cannot be viewed
Application example of infinite list [uigridview]
有钱人买房就是不一样
C4D learning notes 2- animation - timeline and time function
Use moviepy Editor clips videos and intercepts video clips in batches
航运船公司人工智能AI产品成熟化标准化规模应用,全球港航人工智能/集装箱人工智能领军者CIMC中集飞瞳,打造国际航运智能化标杆
Cocos makes Scrollview to realize the effect of zooming in the middle and zooming out on both sides
讲师征集令 | Apache SeaTunnel(Incubating) Meetup 分享嘉宾火热招募中!
C Alibaba cloud OSS file upload, download and other operations (unity is available)
Aerospace Hongtu information won the bid for the database system research and development project of a unit in Urumqi
航運船公司人工智能AI產品成熟化標准化規模應用,全球港航人工智能/集裝箱人工智能領軍者CIMC中集飛瞳,打造國際航運智能化標杆
山东老博会,2022中国智慧养老展会,智能化养老、适老科技展
Step by step monitoring platform ZABBIX
招标公告:盘锦市人民医院盘锦医院数据库维保项目
Shader_ Animation sequence frame
喜讯!科蓝SUNDB数据库与鸿数科技隐私数据保护管理软件完成兼容性适配
Create lib Library in keil and use lib Library
深度之眼(七)——矩阵的初等变换(附:数模一些模型的解释)