0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

OpenCV4之图像的轮廓

OpenCV学堂 来源:OpenCV学堂 2024-01-02 12:24 次阅读

Part11. 图像的轮廓

在该系列第三篇文章中,曾经简单地介绍过轮廓和轮廓发现。

11.1 轮廓的基本概念

图像的轮廓是指图像中具有相同颜色灰度值的连续点的曲线。轮廓和边缘是有联系的,边缘是轮廓的基础,轮廓是边缘的连续集合。

轮廓和边缘的区别是:

轮廓是连续的,边缘可以是连续的,也可以是离散的。

轮廓是完整的,边缘可以是完整的,也可以是不完整的。

轮廓可以有各种形状,边缘通常是线性的。

21.2 轮廓发现和轮廓提取

轮廓发现是指在图像中找到所有可能的轮廓。

轮廓提取是指从图像中找到所有有效的轮廓和轮廓的具体信息

轮廓发现是轮廓提取的前提,轮廓提取在轮廓发现的基础上进一步提取轮廓的形状和位置信息等等。

下面的代码,经过一系列操作找到二值图像的有效轮廓后,获取这些轮廓的最小外接矩形,最后用线在原图中框出这些外接矩形,从而在原图中找到比较明显的苹果。

#include
#include"opencv2/imgproc.hpp"
#include"opencv2/highgui.hpp"

usingnamespacestd;
usingnamespacecv;

boolascendSort(vectora,vectorb)
{
returncontourArea(a)>contourArea(b);
}

intmain(intargc,char**argv){
Matsrc=imread(".../apple.jpg");
imshow("src",src);

Mathsv,edge;
cvtColor(src,hsv,cv::COLOR_BGR2HSV);//BGR转换到HSV色彩空间
imshow("hsv",hsv);

cv::Scalarlower_red(0,43,46);
cv::Scalarupper_red(10,255,255);//定义红色的HSV范围

Matmask;
inRange(hsv,lower_red,upper_red,mask);//通过inRange函数实现二值化
imshow("mask",mask);

Matkernel=getStructuringElement(MORPH_RECT,Size(15,15));
morphologyEx(mask,mask,MORPH_CLOSE,kernel);//形态学操作
morphologyEx(mask,mask,MORPH_OPEN,kernel);//形态学操作
imshow("morphology",mask);

vector>contours;
vectorhierarchy;

findContours(mask,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);
sort(contours.begin(),contours.end(),ascendSort);//ascendingsort

for(size_ti=0;i< contours.size(); i++) {
        double area = contourArea(contours[i]);

        if (area < 22000) {
            continue;
        }
        cout << "area = " << area << endl;
        RotatedRect rrt = minAreaRect(contours[i]);

        Point2f pt[4];
        rrt.points(pt);
        line(src, pt[0], pt[1], Scalar(255, 0, 0), 8, 8);
        line(src, pt[1], pt[2], Scalar(255, 0, 0), 8, 8);
        line(src, pt[2], pt[3], Scalar(255, 0, 0), 8, 8);
        line(src, pt[3], pt[0], Scalar(255, 0, 0), 8, 8);
    }

    imshow("result", src);

    waitKey(0);
    return 0;
}

展示原图

将原图转换成 HSV 类型,用于提取特定颜色。

hsv.png

通过 inRange 函数实现二值化。inRange 函数用于将图像中的像素值限制在指定的范围内,它会将满足条件的像素设置为 255,不满足条件的像素设置为 0,从而形成一个二值图像。

二值化.png

对二值图像进行一些形态学的操作,便于后续的轮廓分析。

形态学操作.png

通过 findContours() 函数进行轮廓发现。最后,筛选出有效的轮廓,并获取最小外接矩形,用线画出在原图上展示出来。

Part22. 轮廓特征的分类

图像的轮廓特征可以分为以下几类:

基础特征:面积、周长、质心、凸包、最小外接矩形等。这些特征可以直接从轮廓序列中计算得到。

矩特征:Hu 矩、中心矩、惯性矩等。这些特征可以用于描述轮廓的形状和大小。

几何特征:最小闭合圆、拟合椭圆等。这些特征可以用于描述轮廓的几何形状。

Part33. 轮廓的基础特征

33.1 面积、周长、最小外接矩形

轮廓面积 contourArea()

轮廓周长 arcLength()

轮廓外接矩形 boundingRect()

轮廓最小外接矩形 minAreaRect()

下面的例子获取图中回形针的轮廓,以及轮廓的面积、周长、最小外接矩形等。

#include
#include"opencv2/imgproc.hpp"
#include"opencv2/highgui.hpp"

usingnamespacestd;
usingnamespacecv;

boolascendSort(vectora,vectorb)
{
returncontourArea(a)>contourArea(b);
}

intmain(intargc,char**argv){
Matsrc=imread(".../paperclip.jpg");
imshow("src",src);

Matgray,thresh;
cvtColor(src,gray,cv::COLOR_BGR2GRAY);
imshow("gray",gray);

threshold(gray,thresh,0,255,THRESH_BINARY_INV|THRESH_OTSU);
imshow("thresh",thresh);

vector>contours;
vectorhierarchy;

findContours(thresh,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);
sort(contours.begin(),contours.end(),ascendSort);//ascendingsort

for(size_ti=0;i< contours.size(); i++) {
        double area = contourArea(contours[i]);
        double length = arcLength(contours[i],true);

        if (area < 1000) {
            continue;
        }
        cout << "area = " << area << ", length = " << length << endl;
        RotatedRect rrt = minAreaRect(contours[i]);// 获取最小外接矩形

        Point2f pt[4];
        rrt.points(pt);
        line(src, pt[0], pt[1], Scalar(255, 0, 0), 8, 8);
        line(src, pt[1], pt[2], Scalar(255, 0, 0), 8, 8);
        line(src, pt[2], pt[3], Scalar(255, 0, 0), 8, 8);
        line(src, pt[3], pt[0], Scalar(255, 0, 0), 8, 8);
        Point  center = rrt.center;
        circle(src, center, 2,Scalar(0, 0, 255), 8, 8); // 绘制最小外接矩形的中心点
    }

    imshow("result", src);

    waitKey(0);
    return 0;
}

执行结果:

area=101573,length=2461.71
area=41757.5,length=1256.08
area=41348,length=1152.56
area=39717.5,length=1616.13
area=37503,length=1230.47
area=36742.5,length=1037.21
area=4142,length=706.357

外接矩形是指可以包围轮廓所有点的矩形,而最小外接矩形是指包含轮廓中所有点的最小矩形。

下面的例子,获取图中最大轮廓的外接矩形和最小外接矩形,分别用黄色和蓝色表示。

#include"opencv2/imgproc.hpp"
#include"opencv2/highgui.hpp"

usingnamespacestd;
usingnamespacecv;

boolascendSort(vectora,vectorb)
{
returncontourArea(a)>contourArea(b);
}

intmain(intargc,char**argv){
Matsrc=imread(".../fruit.jpg");
imshow("src",src);

Matgray,thresh;
cvtColor(src,gray,cv::COLOR_BGR2GRAY);

threshold(gray,thresh,0,255,THRESH_BINARY|THRESH_OTSU);

vector>contours;
vectorhierarchy;
findContours(thresh,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);
sort(contours.begin(),contours.end(),ascendSort);//ascendingsort

RotatedRectrrt=minAreaRect(contours[0]);//获取最大轮廓的最小外接矩形

Point2fpt[4];
rrt.points(pt);
line(src,pt[0],pt[1],Scalar(255,0,0),8,8);
line(src,pt[1],pt[2],Scalar(255,0,0),8,8);
line(src,pt[2],pt[3],Scalar(255,0,0),8,8);
line(src,pt[3],pt[0],Scalar(255,0,0),8,8);

Rectrect=boundingRect(contours[0]);//获取最大轮廓的外接矩形
rectangle(src,rect,Scalar(0,255,255),8,8);//绘制外接矩形

imshow("result",src);

waitKey(0);
return0;
}

通过上述例子可以看到,最小外接矩形能够更精确地描述轮廓的形状和大小。

外接矩形和最小外接矩形有各自的使用场景,例如在对象检测中,可以使用外接矩形来粗略定位物体,而使用最小外接矩形来精确定位物体。

43.2 凸包

凸包(Convex Hull)是计算几何(图形学)中的概念。在一个实数向量空间 V 中,对于给定集合 X,所有包含 X 的凸集的交集 S 被称为 X 的 凸包。

在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。

平面的一个子集 S 被称为是“凸”的,当且仅当对于任意两点 p,s ∈S,线段 ps 都完全属于S。

一个点集 P 的凸包CH(P),就是包含 P 的最小凸集——即包含P的所有凸集的交。

凸包的性质:

凸包是凸集。

凸包的周长是最小的。

凸包的面积是最小的。

凸包的质心是所有点的质心的均值。

OpenCV 提供了 convexHull() 函数寻找轮廓的凸包以及 isContourConvex() 函数用于判断轮廓是否为凸轮廓。凸轮廓是指所有内角都小于或等于 180 度的轮廓。

#include
#include"opencv2/imgproc.hpp"
#include"opencv2/highgui.hpp"

usingnamespacestd;
usingnamespacecv;

intmain(intargc,char**argv){
Matsrc=imread(".../hand.jpg");
imshow("src",src);

Matgray,thresh;
cvtColor(src,gray,cv::COLOR_BGR2GRAY);

threshold(gray,thresh,0,255,THRESH_BINARY_INV|THRESH_OTSU);
imshow("thresh",thresh);

Matmask;
Matkernel=getStructuringElement(MORPH_RECT,Size(31,31));
morphologyEx(thresh,mask,MORPH_CLOSE,kernel);//形态学操作
imshow("morphology",mask);

vector>contours;
vectorhierarchy;

findContours(mask,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);

vector>hull(contours.size());

Matdrawing=Mat::zeros(mask.size(),CV_8UC3);
for(size_ti=0;i< contours.size(); i++) {
        double area = contourArea(contours[i]);
        if (area < 100) {
            continue;
        }

        convexHull(contours[i], hull[i], false);
        bool isHull = isContourConvex(contours[i]);
        cout << "isHull = " << isHull << endl;
        drawContours(drawing, contours, i, Scalar(0, 0, 255), 8, 8);
        drawContours(drawing, hull, i, Scalar(255, 0, 0), 8, 8);
        drawContours(src, hull, i, Scalar(255, 0, 0), 8, 8);
    }

    imshow("result",src);
    imshow("drawing",drawing);

    waitKey(0);
    return 0;
}

执行结果:

isHull=0
isHull=0

Part44. 总结

轮廓的基础特征是计算机视觉中的重要工具,这些特征可以应用于对象检测、形状识别、测量等各种应用场景。后续还会介绍更多的轮廓特征。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 图像
    +关注

    关注

    2

    文章

    1063

    浏览量

    40042
  • 代码
    +关注

    关注

    30

    文章

    4556

    浏览量

    66805
  • OpenCV
    +关注

    关注

    29

    文章

    611

    浏览量

    40789

原文标题:OpenCV4之图像的轮廓和轮廓的基础特征

文章出处:【微信号:CVSCHOOL,微信公众号:OpenCV学堂】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    OpenCV4.8 CUDA编程代码教程

    OpenCV4支持通过GPU实现CUDA加速执行,实现对OpenCV图像处理程序的加速运行,当前支持加速的模块包括如下。
    的头像 发表于 12-05 09:56 453次阅读
    <b class='flag-5'>OpenCV</b>4.8 CUDA编程代码教程

    小编带你玩转OpenCV跳一跳小程序

    了干货满满的“小编带你玩转OpenCV跳一跳主题教程” . 在凡哥的公司网站上会陆续更新。 需要完整教程的同学也可加入学习交流群群:561213221。实际上,我们做的这个稳定的跳一跳图像识别程序,用到
    发表于 03-01 14:16

    鲁班猫0 -安装opencv

    ON OPENCV_GENERATE_PKGCONFIG 因为opencv4默认不生成.pc文件,所以加上这句用于生成opencv4.pc文件,支持pkg-config功能。opencv4
    发表于 04-09 13:29

    CMake在Linux 6.1.1-1.0.0中搜索包opencv损坏了吗?

    ] 但是这个文件不存在。 并尝试使用图像 imx-image-full 的 SDK,我收到以下错误: sysroots/armv8a-poky-linux/usr/lib/cmake/opencv4
    发表于 05-09 11:32

    基于轮廓图像检索

    基于轮廓图像检索:提出了一种针对多纹理图像的基于轮廓和纹理分割的检索策略.首先提取一幅图像中各个纹理基元的
    发表于 10-31 09:03 12次下载

    创建包围轮廓的矩形边界初级图像混合_《OpenCV3编程入门》书本配套源代码

    OpenCV3编程入门》书本配套源代码:创建包围轮廓的矩形边界初级图像混合
    发表于 06-06 15:39 1次下载

    轮廓查找基础_《OpenCV3编程入门》书本配套源代码

    OpenCV3编程入门》书本配套源代码:轮廓查找基础
    发表于 06-06 15:39 4次下载

    轮廓查找基础_OpenCV3编程入门-源码例程

    OpenCV3编程入门-源码例程全集-轮廓查找基础,感兴趣的小伙伴们可以瞧一瞧。
    发表于 09-18 16:55 0次下载

    opencv轮廓提取原理与代码的实现

    在检测物体的轮廓时,我们通常会使用到opencv中的findcontour和drawcontour,比较常用而且效果不错。那么findcontour是基于什么原理来实现轮廓的提取呢?在目标识别中我们
    发表于 12-04 16:29 3.1w次阅读

    opencv用序列存储轮廓

    轮廓到底是什么?一个轮廓一般对应一系列的点,也就是图像中的一条曲线.表示的方法可能根据不同情况而有所不同.
    的头像 发表于 02-02 17:25 4006次阅读
    <b class='flag-5'>opencv</b>用序列存储<b class='flag-5'>轮廓</b>

    如何才能提取二值图像中的最大轮廓OpenCV程序免费下载

      本文档的主要内容详细介绍的是如何才能提取二值图像中的最大轮廓OpenCV程序免费下载。
    发表于 10-10 16:49 3次下载
    如何才能提取二值<b class='flag-5'>图像</b>中的最大<b class='flag-5'>轮廓</b><b class='flag-5'>OpenCV</b>程序免费下载

    基于opencv4和Yolo-Fastest,实现PC和单片机通信,控制步进电机捕获目标

    效果视频 基于opencv4和yolo,实现PC和单片机通信,控制步进电机捕获目标
    发表于 11-23 17:36 15次下载
    基于<b class='flag-5'>opencv4</b>和Yolo-Fastest,实现PC和单片机通信,控制步进电机捕获目标

    如何在Raspberry Pi 3上安装OpenCV4

    今天我们将学习如何在 Raspberry Pi 3 上安装 OpenCV4 库,以便我们可以将其用于计算机视觉应用程序。这将允许 OpenCV 在像 Pi 这样的便携式设备上运行,从而打开许多可能性的大门。所以让我们开始吧
    的头像 发表于 09-08 16:09 1370次阅读
    如何在Raspberry Pi 3上安装<b class='flag-5'>OpenCV4</b>库

    学习OpenCV4的系统化路线图

    OpenCV4发布测试版本开始,作者就一直关注!根据自己近十年图像处理OpenCV开发相关工作经验,花了七个月的时间,针对OpenCV4、精心选择
    的头像 发表于 07-05 11:30 370次阅读
    学习<b class='flag-5'>OpenCV4</b>的系统化路线图

    OpenCV二值图像分析

    二值图像分析最常见的一个主要方式就是轮廓发现与轮廓分析,其中轮廓发现的目的是为轮廓分析做准备,经过轮廓
    的头像 发表于 10-20 12:25 353次阅读