opencv findContours()轮廓特征分析大全(求面积、周长、几何矩、质心、凸包、最小外接矩形、最小外接三角形、最小外接椭圆等)

news/2024/10/17 22:16:06/

文章目录

  • 前言
  • 一、效果
  • 二、opencv对应函数介绍
    • 1.轮廓面积
    • 2.轮廓周长
    • 3.轮廓几何矩
    • 4.轮廓的最大外接矩形
    • 5.轮廓的凸包
    • 6.轮廓的最小外接矩形
    • 7.轮廓的最小外接三角形
    • 8.轮廓的最小外接椭圆
    • 9.轮廓的多边形逼近
    • 10.轮廓的最小外接圆
  • 三、完整代码

前言

二值化轮廓发现之后,下一步最主要的就是轮廓特征分析了,常见的特征有:
轮廓面积
轮廓周长
轮廓几何矩、质心
轮廓的最大外接矩形
轮廓的凸包
轮廓的最小外接矩形
轮廓的最小外接三角形
轮廓的最小外接椭圆
轮廓的多边形逼近
轮廓的最小外接圆

一、效果

轮廓几何矩的质心

在这里插入图片描述

轮廓的最大外接矩形

在这里插入图片描述

轮廓的凸包

在这里插入图片描述

轮廓的最小外接矩形

在这里插入图片描述

轮廓的最小外接三角形

在这里插入图片描述

轮廓的最小外接椭圆

在这里插入图片描述

轮廓的多边形逼近
在这里插入图片描述

轮廓的最小外接圆
在这里插入图片描述
轮廓面积和轮廓周长:
在这里插入图片描述

二、opencv对应函数介绍

1.轮廓面积

CV_EXPORTS_W double contourArea( InputArray contour, bool oriented = false );

2.轮廓周长

CV_EXPORTS_W double arcLength( InputArray curve, bool closed );

3.轮廓几何矩

CV_EXPORTS_W Moments moments( InputArray array, bool binaryImage = false );

4.轮廓的最大外接矩形

CV_EXPORTS_W Rect boundingRect( InputArray array );

5.轮廓的凸包

详细介绍可参考之前文章:https://blog.csdn.net/weixin_44901043/article/details/123242496?spm=1001.2014.3001.5502

CV_EXPORTS_W void convexHull( InputArray points, OutputArray hull,bool clockwise = false, bool returnPoints = true );

6.轮廓的最小外接矩形

CV_EXPORTS_W RotatedRect minAreaRect( InputArray points );

7.轮廓的最小外接三角形

CV_EXPORTS_W double minEnclosingTriangle( InputArray points, CV_OUT OutputArray triangle );

8.轮廓的最小外接椭圆

CV_EXPORTS_W RotatedRect fitEllipse( InputArray points );

9.轮廓的多边形逼近

CV_EXPORTS_W void approxPolyDP( InputArray curve,OutputArray approxCurve,double epsilon, bool closed );

10.轮廓的最小外接圆

CV_EXPORTS_W void minEnclosingCircle( InputArray points,CV_OUT Point2f& center, CV_OUT float& radius );

三、完整代码

void test_contours_feature(){cv::Mat src;src = cv::imread("D:\\QtProject\\Opencv_Example\\contours_feature\\contours_feature.png", cv::IMREAD_GRAYSCALE);if (src.empty()) {cout << "Cannot load image" << endl;return;}cv::imshow("src", src);cv::Mat binary;cv::threshold(src, binary, 150, 255, cv::THRESH_BINARY_INV);cv::Mat k55 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5), cv::Point(-1, -1));cv::morphologyEx(binary, binary, cv::MORPH_OPEN, k55, cv::Point(-1, -1), 1);cv::namedWindow("binary",cv::WINDOW_NORMAL);cv::imshow("binary", binary);std::vector<std::vector<cv::Point> > defectContours;std::vector<cv::Vec4i> hierarchyDefect;cv::findContours(binary, defectContours, hierarchyDefect, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);cv::Mat contours = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));cv::Mat drawCenterPos = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));cv::Mat drawRect = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));cv::Mat drawHull = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));cv::Mat drawRotateRect = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));cv::Mat drawMinEnclosingCircle = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));cv::Mat drawMinEnclosingTriangle = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));cv::Mat drawEllipse = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));std::vector<std::vector<cv::Point>> PolyDPs;cv::Mat drawPolyDP = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));std::vector<std::vector<cv::Point> > hull(defectContours.size());for (int i = 0; i < defectContours.size(); i++){//轮廓 白色cv::drawContours(contours, defectContours, i, cv::Scalar(255,255,255), 1);//求面积double fArea = cv::contourArea(defectContours[i]);qDebug()<<QStringLiteral("面积")<<fArea;//求周长double fLength = cv::arcLength(defectContours[i],true);qDebug()<<QStringLiteral("周长")<<fLength;//矩求质心 红色cv::Moments mu = cv::moments(defectContours[i]);cv::Point2d centerPos = cv::Point2d( mu.m10/mu.m00 , mu.m01/mu.m00);cv::circle(drawCenterPos, centerPos, 10, cv::Scalar(0, 0, 255));//最大外接矩形 蓝色cv::Rect rect = cv::boundingRect(defectContours[i]);cv::rectangle(drawRect, rect, cv::Scalar(255,0,0));//凸包 黄色cv::convexHull(cv::Mat(defectContours[i]), hull[i], false);cv::drawContours(drawHull, hull, i, cv::Scalar(0,255,255), 1);//最小外接矩形 青色cv::RotatedRect rotateRect = cv::minAreaRect(defectContours[i]);vector<cv::Point2f> boxPts(4);rotateRect.points(boxPts.data());for (int j = 0; j < 4; j++){cv::line(drawRotateRect, boxPts[j], boxPts[(j + 1) % 4], cv::Scalar(128, 128, 0), 1, 8);  //绘制最小外接矩形每条边}//最小外接圆 棕褐色cv::Point2f center;float fRadius = 0;cv::minEnclosingCircle(defectContours[i], center, fRadius);cv::circle(drawMinEnclosingCircle, center, fRadius, cv::Scalar(140,180,210),1);//最小外界三角形 粉色std::vector<cv::Point2f> points;cv::minEnclosingTriangle(defectContours[i], points);cv::line(drawMinEnclosingTriangle, points[0], points[1], cv::Scalar(193, 182, 255), 1, 8);  //绘制最小外接三角形每条边cv::line(drawMinEnclosingTriangle, points[2], points[1], cv::Scalar(193, 182, 255), 1, 8);  //绘制最小外接三角形每条边cv::line(drawMinEnclosingTriangle, points[2], points[0], cv::Scalar(193, 182, 255), 1, 8);  //绘制最小外接三角形每条边//椭圆 紫罗兰色cv::RotatedRect ellipse =  cv::fitEllipse(defectContours[i]);cv::ellipse(drawEllipse, ellipse, cv::Scalar(226,43,138));//多边形逼近 洋红色std::vector<cv::Point> PolyDP;//cv::Mat PolyDP ;cv::approxPolyDP(defectContours[i],PolyDP, 0.5, true);PolyDPs.push_back(PolyDP);//cv::drawContours(drawPolyDP, PolyDP, 0, cv::Scalar(23,56,234));//drawPolyDP += cv::Mat(PolyDP);}//画多边形逼近for(int j = 0; j < PolyDPs.size(); j++){cv::drawContours(drawPolyDP, PolyDPs, j, cv::Scalar(255,0,255),1);}drawCenterPos += contours;drawRect += contours;drawHull += contours;drawRotateRect += contours;drawMinEnclosingCircle += contours;drawMinEnclosingTriangle += contours;drawEllipse += contours;cv::namedWindow("contours",cv::WINDOW_NORMAL);cv::imshow("contours", contours);cv::namedWindow("drawRect",cv::WINDOW_NORMAL);cv::imshow("drawRect", drawRect);cv::namedWindow("drawHull",cv::WINDOW_NORMAL);cv::imshow("drawHull", drawHull);cv::namedWindow("drawRotateRect",cv::WINDOW_NORMAL);cv::imshow("drawRotateRect", drawRotateRect);cv::namedWindow("drawCenterPos",cv::WINDOW_NORMAL);cv::imshow("drawCenterPos", drawCenterPos);cv::namedWindow("drawMinEnclosingCircle",cv::WINDOW_NORMAL);cv::imshow("drawMinEnclosingCircle", drawMinEnclosingCircle);cv::namedWindow("drawMinEnclosingTriangle",cv::WINDOW_NORMAL);cv::imshow("drawMinEnclosingTriangle", drawMinEnclosingTriangle);cv::namedWindow("drawEllipse",cv::WINDOW_NORMAL);cv::imshow("drawEllipse", drawEllipse);cv::namedWindow("drawPolyDP",cv::WINDOW_NORMAL);cv::imshow("drawPolyDP", drawPolyDP);}

http://www.ppmy.cn/news/589311.html

相关文章

Keil 5安装激活教程

Keil 5安装激活教程 听语音 |浏览&#xff1a;10426|更新&#xff1a;2018-01-23 15:53 1 2 3 4 5 6 7 分步阅读 Keil 5安装激活教程 工具/原料 电脑 方法/步骤 首先打开keill安装包&#xff0c;双击文件&#xff0c;安装软件 根据提示&#xff0c;单击“Next”…

基于三菱PLC的饮料售货机控制系统设计

目 录 摘要 I Abstract II 1 绪论 1 1.1研究背景及意义 1 1.2自动售货机的简介 1 1.2.1自动售货机的发展历史 1 1.2.2自动售货机的定义 2 1.2.3自动售货机的组成以及分类 3 1.3自动售货机的研究现状 4 1.4课题研究内容 9 1.4.1 自动售货机的功能要求 9 1.4.2研究内容及方法 10…

柔索离散模型 Bushing衬套力 Simulink仿真

柔索离散模型 Simulink仿真 柔索建模方法Bushing模型Simulink仿真模型仿真源文件 柔索建模方法 目前针对柔索建模方法主要有以下几种&#xff1a; 有限元法&#xff1a;先建立柔索刚体模型&#xff0c;然后用有限元分析软件(如ANSYS)对刚体模型进行柔化&#xff0c;把处理后的…

k55.第十九章 K8s运维篇-集群升级 -- kubeadm v1.22 安装方式升级(一)

1.kubeadm 安装方式升级 升级k8s集群必须 先升级kubeadm版本到目的k8s版本,也就是说kubeadm是k8s升级的准升证。 1.1 升级准备 在k8s的所有master节点进行组件升级,将管理端服务kube-controller-manager、kube-apiserver、kube-scheduler、kube-proxy进行版本升级。 1.1.…

Keil MDK5使用

KEIL工程目标选项配置&#xff08;魔术棒&#xff09; 一、文件说明 MDK的编译过程及文件类型全解 Keil MDK本质上实现交叉编译链的功能&#xff0c;只是界面上采用eclipse IDE&#xff0c;从这个角度理解&#xff0c;MDK工程文件类型可以分为两类&#xff0c;工程本身的文件和…

KEIL 5 的点灯

1本节从调用固件库来点亮LED灯&#xff1b;使用的是指南者的板子&#xff0c;选择的KEIL&#xff15;编辑&#xff0c; 一&#xff0c;构建文件库并将相应的文件导入&#xff1b; 创建文件&#xff0c;加入相应的文件库 工程创建完毕&#xff0c;这里不会可以在网上下载一个工…

Redmi K50电竞版 评测

K50 电竞版搭载全新一代骁龙8 旗舰处理器&#xff0c;突破性采用热源分离布局和双区温控&#xff0c;结合双 VC、超大面积石墨等一系列豪华散热材料&#xff0c;造就最冷静骁龙8 旗舰。还延续了磁动力肩键设计&#xff0c;并全新升级 JBL 宽频四单元扬声器、最新一代 CyberEngi…

杭州最新公交线路一览(51-60)

K55武林小广场&#xff0d;武林小广场 上行站点&#xff1a;武林小广场、杭州大厦、中山北路口、艮山门、公交总公司、闸弄口新村、汽车东站、严家弄、景芳 五区、景芳二区、景芳亭、红菱新村、采荷新村、解放路秋涛路口、新城隧道东口、葵巷、浙二医院、官巷口、湖滨、胜利剧院…