【OpenCV学习笔记】之图像轮廓特征与图像的矩 |
您所在的位置:网站首页 › 图像处理轮廓匹配 › 【OpenCV学习笔记】之图像轮廓特征与图像的矩 |
一、图像的轮廓(Contours of Image)
轮廓可以说是一个很好的图像目标的外部特征,这种特征对于我们进行图像分析,目标识别和理解等更深层次的处理都有很重要的意义。那么,怎么取提取轮廓呢? 轮廓提取的基本原理: (针对二值化的轮廓提取是这样的)对于一幅背景为白色、目标为黑色的二值图像,如果在图中找到一个黑色点,且它的8邻域(或4邻域)也均为黑色,则说明该点是目标的内部点,将其置为白色,视觉上就像内部被掏空一样;否则保持黑色不变,该点是目标的边界点。 这里顺带提下边缘检测,和轮廓提取的区别: 边缘检测主要是通过一些手段检测数字图像中明暗变化剧烈(即梯度变化比较大)像素点,偏向于图像中像素点的变化。如canny边缘检测,结果通常保存在和源图片一样尺寸和类型的边缘图中。 轮廓检测指检测图像中的对象边界,更偏向于关注上层语义对象。如OpenCV中的findContours()函数, 它会得到每一个轮廓并以点向量方式存储,除此也得到一个图像的拓扑信息,即一个轮廓的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓的索引编号。 1.1 发现与绘制轮廓在OpenCV里面利用findContours()函数和drawContours()函数实现这一功能。 API介绍: C++:void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point() )参数详解: 参数一: image,单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像; 参数二: contours是一个向量,并且是一个双重向量,向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。有多少轮廓,向量contours就有多少元素。 参数三: hierarchy也是一个向量,向量内每个元素保存了一个包含4个int整型的数组。向量hiararchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。hierarchy向量内每一个元素的4个int型变量——hierarchy[i][0] ~hierarchy[i][3],分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则hierarchy[i][0] ~hierarchy[i][3]的相应位被设置为 默认值-1。 参数四: int型的mode,定义轮廓的检索模式: 模式一:CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略 模式二:CV_RETR_LIST 检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1, 模式三:CV_RETR_CCOMP 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层 模式四:CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。 参数五: int型的method,定义轮廓的近似方法: 方式一:CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内 方式二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours 向量内,拐点与拐点之间直线段上的信息点不予保留 方式三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法 参数六: Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓 点上加上该偏移量,并且Point还可以是负值 drawContours( //InputOutputArray binImg, // 输出图像 //OutputArrayOfArrays contours,// 全部发现的轮廓对象 //Int contourIdx// 轮廓索引号 //const Scalar & color,// 绘制时候颜色 //int thickness,// 绘制线宽 //int lineType,// 线的类型LINE_8 //InputArray hierarchy,// 拓扑结构图 //int maxlevel,// 最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓 //Point offset = Point()// 轮廓位移,可选示例程序 //轮廓发现(find contour) //轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法。所以边缘提取的阈值选定会影响最终轮廓发现结果 //步骤:输入图像转为灰度图像cvtColor //使用Canny进行边缘提取,得到二值图像 //使用findContours寻找轮廓 //使用drawContours绘制轮廓 #include"stdafx.h" #include #include #include using namespace std; using namespace cv; Mat src, dst; char input[] = "gray image"; int threshold_value = 100; int threshold_max = 255; void find_contour_demo(int, void*); int main(int argc, char*argv) { src = imread("C:\\Users\\59235\\Desktop\\imag\\mixed_03.png"); if (!src.data) { printf("could not load image...\n"); return -1; } namedWindow(input, CV_WINDOW_AUTOSIZE); namedWindow("result", CV_WINDOW_AUTOSIZE); //输入图像转为灰度图像 cvtColor(src, src, CV_BGR2GRAY); imshow(input, src); const char*thresh = "threshold value"; createTrackbar(thresh, input, &threshold_value, threshold_max, find_contour_demo); find_contour_demo(0, 0); waitKey(0); return 0; } void find_contour_demo(int, void*) { //使用Canny进行边缘提取,得到二值图像 Canny(src, dst, threshold_value, threshold_value * 2, 3, false); imshow("canny detection", dst); //使用findContours寻找轮廓 vector contours; vector hierachy; findContours(dst, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); //findContours( //InputOutputArray binImg, // 输入图像,非0的像素被看成1,0的像素值保持不变,8-bit //OutputArrayOfArrays contours,// 全部发现的轮廓对象 //OutputArray, hierachy// 图该的拓扑结构,可选,该轮廓发现算法正是基于图像拓扑结构实现。 //int mode, // 轮廓返回的模式 //int method,// 发现方法 //Point offset = Point()// 轮廓像素的位移,默认(0, 0)没有位移) //使用drawContours绘制轮廓 Mat drawImage = Mat::zeros(src.size(), CV_8UC3); RNG rng(12345); for (int i = 0; i < contours.size(); i++) { Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); drawContours(drawImage, contours, i, color, 2, LINE_AA, hierachy, 0, Point(0, 0)); //drawContours( //InputOutputArray binImg, // 输出图像 //OutputArrayOfArrays contours,// 全部发现的轮廓对象 //Int contourIdx// 轮廓索引号 //const Scalar & color,// 绘制时候颜色 //int thickness,// 绘制线宽 //int lineType,// 线的类型LINE_8 //InputArray hierarchy,// 拓扑结构图 //int maxlevel,// 最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓 //Point offset = Point()// 轮廓位移,可选 } imshow("result", drawImage); return; }效果图: (灰度图) (canny边缘检测图) (绘制轮廓图) OpenCV提取轮廓之后,还可以进行许多操作: ArcLength() 计算轮廓长度 ContourArea() 计算轮廓区域的面积 BoundingRect() 轮廓的外包矩形 ConvexHull() 提取轮廓的凸包 IsContourConvex() 测试轮廓的凸性 MinAreaRect() 轮廓的最小外包矩形 MinEnclosingCircle() 轮廓的最小外包圆fitEllipse()用椭圆拟合二维点集approxPolyDP()逼近多边形曲线 二、图像的矩(Image Moments)矩的概念介绍 矩函数在图像分析中有着广泛的应用,如模式识别、目标分类、目标识别与方位估计、图像的编码与重构等。从一幅图像计算出来的矩集,不仅可以描述图像形状的全局特征,而且可以提供大量关于该图像不同的几何特征信息,如大小,位置、方向和形状等。图像矩这种描述能力广泛应用于各种图像处理、计算机视觉和机器人技术领域的目标识别与方位估计中。 一阶矩:与形状有关; 二阶矩:显示曲线围绕直线平均值的扩展程度; 三阶矩:关于平均值的对称性测量;由二阶矩和三阶矩可以导出7个不变矩。而不变矩是图像的统计特性,满足平移、伸缩、旋转均不变的不变性、在图像识别领域得到广泛的应用。 1 、空间矩/几何矩 空间矩的实质为面积或者质量。可以通过一阶矩计算质心/重心。 重心(中心centers): 2、中心矩 中心矩体现的是图像强度的最大和最小方向(中心矩可以构建图像的协方差矩阵),其只具有平移不变性,所以用中心矩做匹配效果不会很好。 3、归一化的中心矩 归一化后具有尺度不变性。 4、Hu矩 Hu矩由于具有尺度、旋转、平移不变性,可以用来做匹配。 cv::moments 计算生成数据: |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |