OPENCV图形计算面积、弧长API讲解(2)

一.threshold API 讲解

作用: 把图像进行二值化处理

在一个彩色图像中有许多像素值,例如设置阈值为100,大于100的像素变成100,小于的变成0或者其他值。其就是将多个像素点变成两个。

二值化操作作用:可以使图像中的数据量大大降低图像的复杂度,并且能够凸显出图像中的轮廓。便于对图片轮廓的获取等等

复制代码
CV_EXPORTS_W double threshold( InputArray src, 
                                OutputArray dst,
                                double thresh, 
                                double maxval, 
                                int type );

第一个参数: src源图像,可以是8位灰度图,也可以是32位的三通道图像
**第二个参数:**dst目标图像

第三个参数:thresh 阈值
第四个参数: maxval 二值图像中灰度最大值,maxval只能在THRESH_BINARYTHRESH_BINARY_INV 有用,但是其他选项也需要填这个值,不能空着。
第五个参数: type阈值操作类型,具体的阈值操作如下图:

1.THRESH_BINARY

**作用:**二值化阈值处理会将原始图像作为仅有的两个值图像

它针对的像素的处理方式是对于灰度值大于阈值thresh的像素点,将其灰度值设定为maxval最大值。而对于灰度值小于或等于阈值thresh的像素点,将其灰度值设定为0。

2.THRESH_BINARY_INV

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

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

3.THRESH_TRUNC

作用: 截断阈值化处理会把图像中大于阈值的像素点设定为阈值,小于或者等于该阈值的像素点保持不变。

比方说阈值设置成127,则说明对于像素超过127的像素点,而其像素值就被设置成127。而小于或者等于127的像素点,其数值保持不变。

4.THRESH_TOZERO

作用: 低阈值处理会对图像中小于或者等于阈值的像素点处理为0,大于阈值的像素点则保持不变。

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

5.THRESH_TOZERO_INV

作用:超阈值处理会对图像中大于阈值的像素点处理为0,小于或者等于该阈值的像素点保持不变。

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

6.THRESH_OTSU

作用: OTSU方法会遍历所有可能的阈值,从而找到一个最佳的阈值。

值得注意的是,在使用OTSU方法的时候需要把阈值设定为0。这个时候,threshold会自动寻找最优的值。

二.这两章的相关API综合应用案例

复制代码
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>

using namespace cv;
using namespace std;

int main() {
    // 1. 读取图像并预处理
    Mat img = imread("objects.jpg");
    if (img.empty()) {
        cerr << "Error: Image not found!" << endl;
        return -1;
    }
    
    Mat gray, binary;
    cvtColor(img, gray, COLOR_BGR2GRAY);//转成灰度图
    threshold(gray, binary, 128, 255, THRESH_BINARY);//二值化处理
    
    // 2. 查找轮廓
    vector<vector<Point>> contours;//固定模板
    vector<Vec4i> hierarchy;//可选择填写
    //RETR_EXTERNAL  外轮廓  CHAIN_APPROX_SIMPLE  原图输出
    findContours(binary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
 
    
    // 3. 处理每个轮廓
    for (size_t i = 0; i < contours.size(); i++) {
        const auto& cnt = contours[i];
        
        // 计算轮廓面积
        double area = contourArea(cnt);
        // 计算轮廓周长
        double perimeter = arcLength(cnt, true);
        
        // 紧凑度计算: $C = 4\pi \times \frac{A}{P^2}$
        double compactness = (area > 0) ? (4 * CV_PI * area) / (perimeter * perimeter) : 0;
        
        cout << "轮廓 " << i << " - 面积: " << area 
             << ", 周长: " << perimeter 
             << ", 紧凑度: " << compactness << endl;
        
        // 绘制水平外接矩形
        Rect bRect = boundingRect(cnt);
        rectangle(img, bRect, Scalar(0, 255, 0), 2);  // 绿色矩形
        
        // 绘制旋转矩形
        RotatedRect rRect = minAreaRect(cnt);
        Point2f vertices[4];
        rRect.points(vertices);
        for (int j = 0; j < 4; j++) {
            line(img, vertices[j], vertices[(j + 1) % 4], Scalar(0, 0, 255), 2);  // 红色线段
        }
        
        // 绘制面积和周长文本
        putText(img, format("A:%.1f", area), Point(bRect.x, bRect.y - 10),
                FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 0), 1);
        putText(img, format("P:%.1f", perimeter), Point(bRect.x, bRect.y - 30),
                FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 255), 1);
    }
    
    // 4. 显示结果
    imshow("轮廓分析结果", img);
    waitKey(0);
    return 0;
}

三.利用OPENCV的API计算轮廓面积

本次的代码例程,我们会结合之前学习的OPENCV轮廓检测和上一节课的面积API,来计算一个矩形的各种面积(包括轮廓面积、最小外接矩形面积、垂直边界面积)。

计算矩形面积的大体流程:

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

复制代码
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
  //step1
  Mat img =imread("QT.png");//读取QT这张图片
  //step2
  Mat gray;
  cvtColor(img,gray,COLOR_RGB2GRAY);//转成灰度图
  //step3
  Mat bin_img;
  //参数:原图,目标图,阈值,二直图最大灰度值,阈值操作类
  //THRESH_BINARY_INV:对于灰度值大于阈值的像素点,将其设置为0。
  //而对于灰度值小于或者等于阈值的像素点,将这部分的部分设置为maxval最大像素点
  threshold(gray,bin_img,150,255,THRESH_BINARY_INV);

  //step4  finContours寻找轮廓并获取轮廓数
  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]); //通过minAreaRect找到最小外接矩形 
    //将minAreaect获取的外接矩形的四个顶点传到pts
    minRect.points(pts);
    //用line与四个顶点在原始图像上画出外接矩形
    line(img,pts[0],pts[1],Scalar(0),3);//用line连接p[0]->p[1]
    line(img,pts[1],pts[2],Scalar(0),3);//用line连接p[1]->p[2]
    line(img,pts[2],pts[3],Scalar(0),3);//用line连接p[2]->p[3]
    line(img,pts[3],pts[0],Scalar(0),3);//用line连接p[3]->p[0]
    //计算外接矩形的面积
    int minArea=minRect.size.width*minRect.size.height;
    printf("minArea = %d\n", minArea);

    //垂直矩形面积计算
    Rect bArea = boundingRect(contours[i]);//调用boundingRect查找边界矩形
    //rectangle矩形画框
    rectangle(img, bArea, Scalar(255,255,0));
    int boundingArea = bArea.width * bArea.height;//计算边界矩形面积
    printf("boundingArea = %d\n", boundingArea);
    //图像本身面积计算
    double cArea = contourArea(contours[i]);//计算轮廓面积
    printf("contourArea = %lf\n", cArea);
    

  }
    imwrite("area.jpg", img);
return 0;
}

原图 处理后图

相关推荐
Ai尚研修-贾莲1 分钟前
最新Transformer模型及深度学习前沿技术应用
人工智能·深度学习·transformer·生成式模型·图神经网络·注意力机制·目标检测算法
weixin_4532536510 分钟前
机器学习----模型评价与优化
人工智能·机器学习
DeepSeek忠实粉丝22 分钟前
Deepseek篇--阿里QwQ-325b性能比肩Deepseek满血版
人工智能·程序员·llm
jndingxin22 分钟前
OpenCV CUDA模块图像变形------对图像进行 尺寸缩放(Resize)操作函数resize()
人工智能·opencv·计算机视觉
luofeiju25 分钟前
数字图像处理与OpenCV初探
c++·图像处理·python·opencv·计算机视觉
清醒的兰25 分钟前
OpenCV 多边形绘制与填充
图像处理·人工智能·opencv·计算机视觉
luozhonghua200027 分钟前
opencv opencv_contrib vs2020 源码安装
人工智能·opencv·计算机视觉
JC_You_Know28 分钟前
边缘计算一:现代前端架构演进图谱 —— 从 SPA 到边缘渲染
前端·人工智能·边缘计算
吴声子夜歌28 分钟前
OpenCV——图像金字塔
人工智能·opencv·计算机视觉
吴声子夜歌28 分钟前
OpenCV——图像基本操作(三)
人工智能·opencv·计算机视觉