opencv中查找并绘制图像的轮廓(理解+程序)

(一)查找轮廓
一个轮廓一般对应一系列的点,也就是图像中的一条曲线,在Opencv中可以用findContours()函数从二值图像中查找轮廓:
findContours()
C++:void findContours(IOArray image,OutputArray contours,OutputArray hierarchy,int mode,int method,Point offset=Point())
1.参数1输入图像,为二值图像,我们可以用threshold(),Canny(),adaptivethreshold()这些函数把灰度图像变成二值图像
2.参数2表示检测到的轮廓,每一个轮廓存储为一个点向量不是点的,既用point类型的vector来表示 这个是存储点的容器vector contours;put
二维点向量的定义:vector<vector> contours;这个就是对于点向量的定义方式
3.参数3,可以选的输出向量 OutputArray 包含图像的拓扑信息,作为轮廓数量的表示,包含了许多元素每个轮廓Contours对应了4个hierarchy元素hierarchy[i][0]–hierarchy[i][3]分别表示后一个轮廓,前一个轮廓,父轮廓,以及内嵌轮廓的索引编号
4.参数4,int类型的mode 轮廓检索模式有1. RETR_EXTERNAL 表示只检测最外层轮廓
2. RETR_LIST 表示提取所有的轮廓,并且放置在list中检测轮廓比建立等级
3. RETR_CCOMP 提取所有的轮廓,并且将其组织为双层结构
4. RETR_TREE 提取所有的轮廓,并重新建立网状的轮廓结构
5.参数5表示轮廓的近似方法,int类型的method为轮廓的近似方法取值有:1.CHAIN_APPROX_NONE 获取每个轮廓的每个像素相邻两个点的像素位置差不超过1个
2.CHAIN_APPROX_SIMPLE压缩水平方向和垂直方向,对角线方向,只保留该方向的终点坐标,例如一个矩形轮廓只需要4个点来保存轮廓的信息 3.。。
6.参数六,Point类型的的offset,每个轮廓点的可选偏移量,能偏移多少的问题

(二)绘制图像的轮廓
findContours函数经常和drawContours函数一起使用,用findContours函数找到的轮廓之后就用drawContours()函数进行绘制出来
绘制轮廓的函数:drawContours()函数绘制外部或者内部的轮廓
C++:void drawContours(IOput image,InputArrays contours,int contoursIdx,const Scalar& color,int thickness=1,int lineType=8,InputArray hierarchy=noArray(),int maxLevel=INT_Max,point offset=point())
1.参数1,目标图像,就是把轮廓绘制在该图像上,一般都是自定义一个Mat::zeros(srcImg.size(),CV_8UC3);定义一个黑窗口
2.参数2,所有的输入轮廓,每个轮廓存储为一个点向量,vertor<vector> contours
3.参数3,int类型的contoursIdx,轮廓绘制的指示变量,用于绘制所有的轮廓时,遍历每一个轮廓向量。
4.参数4,轮廓的颜色,颜色的定义方法
5.参数5,轮廓绘制时的线条宽度,就是画多宽的问题
6.参数6,int类型的lineType线条的类型,有4联通和8联通的xuanze
7.参数7,InputArray类型的hierarchy可选的结构层次信息
8.参数8,int类型的maxLevel表示绘制轮廓的最大等级。
9.参数9,point类型的offset,可选的轮廓偏移参数,偏移需要绘制的轮廓;
编写程序时先要进行轮廓的查找,在进行轮廓的绘制问题

程序设计:(1)简单的查找和绘制轮廓
/查找并绘制轮廓/
#include <opencv2\opencv.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
/vector<vector> contours;
Mat srcImg=imread(“1.jpg”);
Mat result(srcImg.size(),CV_8U,cv::Scalar(255));
drawContours(srcImg,contours,1,Scalar(0),3);
imshow(“画轮廓”,result);
/
Mat srcImg=imread(“1.jpg”,0);
imshow(“原始图像”,srcImg);
Mat dstImg=Mat::zeros(srcImg.rows,srcImg.cols,CV_8UC3);
srcImg=srcImg>119;
imshow(“取阈值之后的原始图像”,srcImg);
//定义轮廓和层次结构
vector<vector> contours;
vector hierarchy;
findContours(srcImg,contours,hierarchy,RETR_CCOMP,CHAIN_APPROX_SIMPLE);//找轮廓
//遍历所有顶层的轮廓,以随机的颜色绘制出每个连接组件的颜色
int index=0;
for(;index >= 0;index = hierarchy[index][0])
{
Scalar color(rand()&255,rand()&255,rand()&255);//定义随机颜色的变量,就是产生随机颜色
drawContours(dstImg,contours,index,color,CV_FILLED,8,hierarchy);//遍历每一个轮廓,并且绘制轮廓。
}
imshow(“轮廓图”,dstImg);
waitKey(0);
return 0;
}
(2)参数可以调节的查找并绘制
Mat srcImg,grayImg,cannyImg;
int thresh=3,threshMax=250;
vector<vector> contours;
vector hierarchy;
void text()
{
printf("\n\n 欢迎使用opencv版本 “CV_VERSION);
printf(”\n 这个程序是查找并绘制轮廓的程序");
printf("\n在这个程序中会用到两个函数:findContours()查找轮廓,drawContours()函数进行绘制轮廓");
printf("\n操作说明 :滑动条改变阈值,键盘按任意键退出程序");
}
void on_Trackbar(int,void*)
{
Canny(grayImg,cannyImg,thresh,thresh*2,3);//阈值用于控制提取边界二值图像的深度就是边界的阈值深度
findContours(cannyImg,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point(0,0));
Mat drawing=Mat::zeros(cannyImg.size(),CV_8UC3);
for(int i=0;i<contours.size();i++)
{
Scalar color(rand() & 255,rand() & 255,rand() & 255);//=Scalar color=Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255))
drawContours(drawing,contours,i,color,2,8,hierarchy,0,Point());
}
imshow(“显示轮廓”,drawing);//寻找轮廓和绘制轮廓是一体的只要有寻找轮廓就会有绘制轮廓 最主要的是contours这个函数的利用
}
int main()
{
text();
srcImg=imread(“4.jpg”);
if(!srcImg.data){
printf(“载入图片出错”);
return false;
}
namedWindow(“显示轮廓”);
cvtColor(srcImg,grayImg,CV_BGR2GRAY);
blur(grayImg,grayImg,Size(3,3));
imshow(“原图片”,srcImg);
imshow(“灰度图片”,grayImg);
createTrackbar(“阈值”,“显示轮廓”,&thresh,threshMax,on_Trackbar);//在创建滑动条之前一定要创建一个空的窗口
on_Trackbar(0,0);
waitKey(0);
return 0;
}
//滑动条来调节阈值来提取相应的轮廓的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值