news 2026/6/28 7:13:53

OPENCV——图像面积计算

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OPENCV——图像面积计算

一、图形面积、弧长计算的API介绍

前两节课我们已经把图形轮廓的检测、画框等功能讲解了一遍。那今天这节课我们主要结合轮廓检测的API去计算图形的面积,这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能,常用的API如contourAreaarcLengthminAreaRectboundingRectrectangleline等等。

1.1contourArea

contourArea主要的用途是计算轮廓的曲线面积,也就是去计算图像本身的面积,如上图。countArea就是计算白色区域的面积,计算的过程一般是用微积分等方式去计算。

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

第一个参数:contour指的是每一个轮廓的数据,也称之为轮廓的点,类型为vector<Point>,对应findContours输出的单条轮廓

第二个参数:oriented表示的是某一个方向上轮廓的面积值

返回值:计算后的轮廓面积

1.2arcLength

arcLength主要的用途是计算轮廓的周长,也就是图形形状本身的曲线弧度周长。如上图所述,arcLength计算的是每个点连接的长度,并计算出来。

CV_EXPORTS_W double arcLength( InputArray curve, bool closed );

第一个参数:curve轮廓曲线的2D像素点

第二个参数:closed轮廓或者曲线是否闭合标志,true表示闭合

返回值:计算后的轮廓周长

1.3minAreaRect

minAreaRect主要的用途是计算最小的外接矩形,最小外接矩形指的是找到一个矩形能够完全包裹所有的给定点,并且这个矩形是最小的。如上图:从上图我们可以看到8这个形状,被minAreaRect的矩形包围了。这个矩形包含了整个形状的所有点,更重要的这个矩形具有旋转功能,这个8实际上有倾斜的角度,而这个最小矩形也能够完美包含进来。

CV_EXPORTS_W RotatedRect minAreaRect( InputArray points );

第一个参数:points输入的二维点数,可以Mat类型也可以是std::vector的向量类型

返回值:RotatedRect的矩形对象,它表示的是一个轮廓的最小外接矩形,我们来看看RotatedRect结构体成员变量

center旋转矩形的质心

size旋转矩形的宽度和高度

angle顺时针的旋转角度。

RotatedRect矩形四个点的确定

RotatedRect中矩形四个点通常用Point2f来表示,其中p[0]点的确定是最关键的,p[0]的位置通常分为两种情况:

  1. 如果当前最小外接矩形没有与坐标轴平行,则Y坐标最大的为点p[0],如2,3,4三张图
  2. 如果当前最小矩形和坐标轴平行,则有两个Y坐标最大的点,如图1。

1.4boundingRect

boundingRect主要的用途是计算图形轮廓垂直边界的最小矩形,这个矩形必须要和图像是上下边界平行的。我们看上图:我们还是看8这个形状依然还是之前的位置,然后boundingRect产生的矩形对整个8进行垂直边界包围。

CV_EXPORTS_W Rect boundingRect( InputArray array );

第一个参数:array输入的灰度图像或者2D点集,数据类型为vector或者Mat矩阵数据
返回值:Rect的矩形对象,它表示的是物体轮廓的最大外接矩形。我们来看看Rect主要的成员变量

x矩形的x坐标轴

y矩形的y坐标轴

width矩形的宽度

height矩形的高度

对比项boundingRectminAreaRect
形状横平竖直,不能转可任意角度旋转
输出类型RectRotatedRect
包围面积通常更大(正框包斜物体会有空隙)更小(贴合更紧)
计算速度极快稍慢
能不能直接用 rectangle 画不能
适用快速定位、粗筛、正框标注精准测量、角度检测、斜框标注

1.5. rectangleAPI讲解

rectangle函数的作用是绘制矩形,是目标标注最常用的工具,它有两种表示形式

1.5.1.以两个顶点的方式画矩形

void rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0);

第一个参数:输入的矩阵图像数据

第二个参数:pt1是矩形的一个顶点,左上角的顶点

第三个参数:pt2矩形中与pt1相对的顶点,也就是两个点在对角线上,也就是右下角的顶点

第四个参数:Scalar颜色的标量

第五个参数:thickness线宽

第六个参数:lineType线的类型,默认是LINE_8就行,具体的类型如下图:

第七个参数:shift坐标的小数点位,默认为0就可以

适合手动指定坐标画框的场景

1.5.2.Rect的方式画矩形

void cv::rectangle(InputOutputArray img, Rect rec, const Scalar & color, int thickness = 1,int lineType = LINE_8, int shift = 0)

第一个参数:输入的矩阵图像数据

第二个参数:Rect的结构体,我们来看看这个Rect的重要成员变量

x:矩形的x坐标轴

y矩形的y坐标轴

width矩形的宽度

height矩形的高度

第三个参数:Scalar颜色的标量

第四个参数:thickness线宽,默认是1

第五个参数:lineType线的类型,默认是LINE_8就行,line的类型如下:

第六个参数:shift坐标点的小数点位数

核心特点

  • 只能画正的,画不了歪的矩形
  • 用法简单,一行代码搞定
  • 线宽填-1就变成实心填充矩形

1.6. lineAPI讲解

line函数的主要作用是通过两个点绘制直线,给两个点,在图片上连一条直线,是最基础、最灵活的绘制工具,什么方向的线都能画。

CV_EXPORTS_W void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,int thickness = 1, int lineType = LINE_8, int shift = 0);

第一个参数:输入的矩阵图像数据

第二个参数:pt1是线的起始坐标,也就是图上x1坐标和y1坐标
第三个参数:pt2是线的终点坐标,也就是图上x2坐标和y2坐标

第四个参数:Scalar是颜色标量,绘制直线的颜色
第五个参数:thickness它是线的粗细程度,默认为1

第六个参数:lineType线的类型,默认是LINE_8就行,具体的类型

第七个参数:shift坐标点的小数点位数

核心特点

  • 灵活度拉满,任意角度、任意长度的线都能画
  • 单条只能画一段,画矩形 / 多边形要循环调用 4 次 / N 次

典型场景

  • 画旋转矩形(minAreaRect算出四个点,循环连四条线)
  • 画多边形、辅助标注线、尺寸线
  • 所有rectangle画不了的斜框,都靠它来画

1.7threshold

threshold主要用途是把图像进行二值化处理,二值化操作可以使图像中的数据量大大降低图像的复杂度,并且能够凸显出图像中的轮廓。

double threshold( InputArray src, OutputArray dst, double thresh, double maxval, int type );

参数逐个拆解

  1. src:输入图像,必须是单通道 8 位灰度图,不能直接传彩色图
  2. dst:输出二值图,和输入图尺寸一致,最终只有 0(纯黑)和 maxval(纯白)两种像素值
  3. thresh:阈值,也就是那条 “亮度分界线”,取值范围 0~255
  4. maxval:像素满足条件时被赋予的最大值,固定填 255 就行,对应纯白色
  5. type:阈值处理规则,决定了 “大于阈值怎么变、小于阈值怎么变”,是核心参数
  6. 返回值:实际生效的阈值;用自动阈值算法时会返回计算出的最优值,普通固定阈值就返回你传入的 thresh

第五个参数:type阈值操作类型,具体的阈值操作如下图:

THRESH_BINARY二值化阈值处理会将原始图像作为仅有的两个值图像,它针对的像素的处理方式是对于灰度值大于阈值thresh的像素点,将其灰度值设定为maxval最大值。而对于灰度值小于或等于阈值thresh的像素点,将其灰度值设定为0。

THRESH_BINARY_INV反二值化阈值处理也会将原始图像作为仅有的两个值图像,但是它处理的方式和THRESH_BINARY不一样,

它的特点是:对于灰度值大于阈值的像素点,将其设置为0。而对于灰度值小于或者等于阈值的像素点,将这部分的部分设置为maxval最大像素点。

THRESH_TRUNC截断阈值化处理会把图像中大于阈值的像素点设定为阈值,小于或者等于该阈值的像素点保持不变。比方说阈值设置成127,则说明对于像素超过127的像素点,而其像素值就被设置成127。而小于或者等于127的像素点,其数值保持不变。

THRESH_TOZERO_INV超阈值处理会对图像中大于阈值的像素点处理为0,小于或者等于该阈值的像素点保持不变。比方说阈值的值设定为127,若当前像素点大于127则把像素点处理为0;若当前像素点小于或者等于阈值的像素点,那么该像素点保持不变

THRESH_TOZERO低阈值处理会对图像中小于或者等于阈值的像素点处理为0,大于阈值的像素点则保持不变。比方说当前阈值设定为127,若当前像素点小于或者等于127则把像素点处理为0;若当前像素点大于127则保持像素点不变。

THRESH_OTSUOTSU方法会遍历所有可能的阈值,从而找到一个最佳的阈值。值得注意的是,在使用OTSU方法的时候需要把阈值设定为0。这个时候,threshold会自动寻找最优的值。

二、计算矩形面积

2.1 流程

计算矩形的面积,我们一般要分以下几个比较重要的步骤,分别是:读取图片、把图形进行灰度处理、对灰度图像进行二值处理、调用findContours去查找二值图片形状的轮廓、循环轮廓数量并且调用contourArea计算每个轮廓的曲线面积、然后再计算最小外接矩形面积(minAreaRect)、边界垂直矩形面积的计算(boundingRect)。如下图所示:

2.2 代码

#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; int main() { Mat src = imread("ten.png"); Mat gray, bin_img; cvtColor(src, gray, COLOR_RGB2GRAY); threshold(gray, bin_img, 150, 255, THRESH_BINARY_INV); vector<vector<Point>> contours; findContours(bin_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); Point2f pts[4]; for(int i = 0; i < contours.size(); i++) { RotatedRect minRect = minAreaRect(contours[i]); minRect.points(pts); line(src, pts[0], pts[1], Scalar(0), 3); line(src, pts[1], pts[2], Scalar(0), 3); line(src, pts[2], pts[3], Scalar(0), 3); line(src, pts[3], pts[0], Scalar(0), 3); int minArea = minRect.size.width * minRect.size.height; printf("minArea = %d\n", minArea); Rect bRect = boundingRect(contours[i]); int boundingArea = bRect.width * bRect.height; rectangle(src, bRect, Scalar(255, 255, 0)); printf("boundingArea = %d\n", boundingArea); double cArea = contourArea(contours[i]); printf("contourArea = %lf\n", cArea); } imwrite("Area.jpg",src); return 0; }

1.调用OPENCV读取需要计算的图片

Mat src = imread("ten.png");

第一步,调用imread读取我们需要处理的图片,这里我们选择的图片是10这个图片。

注意这里选择的图片要是白底黑字的,才能对应上下面的二值化操作,核心原则,到findcontours之前图片的目标区域要是白色的,因为findcontours天生只找白色区域的轮廓。

2.对图片进行灰度操作

Mat gray, bin_img; cvtColor(src, gray, COLOR_RGB2GRAY);

读取完图片之后,使用cvtColor把三通道的彩色图像转换成单通道(COLOR_RGB2GRAY)的灰度图。

3.对灰度图进行二值操作

threshold(gray, bin_img, 150, 255, THRESH_BINARY_INV);

灰度完成后,我们需要通过OPENCV的APIthreshold对图像进行二值操作,这样就可以得到更加精确的图像便于识别和计算。这里的阈值我们填写150,最大的阈值填写的是255,阈值处理类型填的是THRESH_BINARY_INV(背景为黑色,数字为白色,这样更利于我们计算数字的面积)。当像素值超过150之后像素全部为0,否则像素值是maxVal也就是255.

4.查找二值图像中的所有轮廓

vector<vector<Point>> contours; findContours(bin_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);

调用findContours去查找整个二值图像的轮廓,由于我们读取的图片没有嵌套的轮廓,所以我们选择RETR_EXTERNAL的模式只查找外部轮廓,轮廓的近似方法是CV_CHAIN_APPROX_NONE来保存边界上所有连续的轮廓点。

5. 循环轮廓数量来计算图像轮廓的最小外接矩形的面积

Point2f pts[4]; for(int i = 0; i < contours.size(); i++) { RotatedRect minRect = minAreaRect(contours[i]); minRect.points(pts); line(src, pts[0], pts[1], Scalar(0), 3); line(src, pts[1], pts[2], Scalar(0), 3); line(src, pts[2], pts[3], Scalar(0), 3); line(src, pts[3], pts[0], Scalar(0), 3); int minArea = minRect.size.width * minRect.size.height; printf("minArea = %d\n", minArea);

这部分代码就是通过循环轮廓数量来计算最小外接矩形,需要调用minAreaRect来查找查找出整个二值图像的最小矩形,并且用line函数画矩形(如下图1),从图1可以看到四个顶点(顶点用Point2f表示)p[0]、p[1]、p[2]、p[3]都分别以p[0]->p[1]、p[1]->p[2]、p[2]->p[3]、p[3]->p[0]的顺序连接起来变成矩形 。最小矩形面积的计算 = 最小外接矩形的长度 * 最小外接矩形的高度,代码就是int minArea= minRect.size.width * minRect.size.height

6.循环轮廓数量来计算图像轮廓的最小垂直矩形面积

Rect bRect = boundingRect(contours[i]); int boundingArea = bRect.width * bRect.height; rectangle(src, bRect, Scalar(255, 255, 0)); printf("boundingArea = %d\n", boundingArea);

这部分代码就是通过循环轮廓数量来计算最小垂直矩形,需要调用boundingRect来查找查找出整个二值图像的最小垂直矩形,并且用rectangle把矩形框出来。最小垂直矩形面积的计算 = 最小垂直矩形的长度 * 最小垂直矩形的高度,代码就是int boundingArea= rect.width * rect.height

7. 循环轮廓数量来计算图像轮廓的面积

double cArea = contourArea(contours[i]); printf("contourArea = %lf\n", cArea);

这部分代码就是通过循环轮廓数量来计算轮廓的面积,通过contourArea来计算轮廓的面积。

输出的结果:

输出的结果有两个,第一个是10这个数字用最小外接矩形、最小垂直矩形并输出area.jpg,如左图。右图是输出边界垂直矩形面积(boundingArea)、最小外接矩形面积(minArea)、轮廓面积(contourArea)等信息。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/28 7:11:51

非色散红外(NDIR)气体探测器:适用场景、成本逻辑与选型指南

非色散红外&#xff08;NDIR&#xff09;气体探测器&#xff1a;适用场景、成本逻辑与选型指南在工业气体安全防护体系中&#xff0c;传感技术路线的选型直接决定了检测系统的长期可靠性与防护有效性。当前主流可燃气体检测技术中&#xff0c;非色散红外吸收式&#xff08;NDIR…

作者头像 李华
网站建设 2026/6/28 7:02:49

如何在.NET生态中构建高效的3D模型格式转换管道

如何在.NET生态中构建高效的3D模型格式转换管道 【免费下载链接】helix-toolkit Helix Toolkit is a collection of 3D components for .NET. 项目地址: https://gitcode.com/gh_mirrors/he/helix-toolkit 你是否曾为不同3D建模软件之间的格式兼容性而头疼&#xff1f;当…

作者头像 李华
网站建设 2026/6/28 7:01:11

业内爆料:小批量混批采购五大陷阱,避开供应商供货套路

我是阿九&#xff0c;一名专注于工业供应链数字化与降本策略的技术博主。如果你是企业设备维保工程师、中小制造工厂的采购负责人&#xff0c;或是非标自动化设备的项目经理&#xff0c;你一定遇到过这样的死结&#xff1a;生产线上急缺几个小众规格的轴承或密封圈&#xff0c;…

作者头像 李华
网站建设 2026/6/28 7:00:59

告别空白图标!QuickLookVideo让Mac Finder视频预览功能全面升级

告别空白图标&#xff01;QuickLookVideo让Mac Finder视频预览功能全面升级 【免费下载链接】QuickLookVideo This package allows macOS Finder to display thumbnails, static QuickLook previews, cover art and metadata for most types of video files. 项目地址: https…

作者头像 李华
网站建设 2026/6/28 6:56:29

5分钟极速上手:Ryujinx Switch模拟器终极使用指南

5分钟极速上手&#xff1a;Ryujinx Switch模拟器终极使用指南 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx 想在电脑上畅玩Switch游戏吗&#xff1f;Ryujinx这款用C#编写的开源任天堂…

作者头像 李华
网站建设 2026/6/28 6:51:54

GHelper深度解析:华硕笔记本的轻量化性能调校革命

GHelper深度解析&#xff1a;华硕笔记本的轻量化性能调校革命 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, Expert…

作者头像 李华