OpenCV(C++)学习笔记五:图像找轮廓、找边

目录

1、图像找轮廓和边简介

2、OpenCV中找轮廓找边用到的方法

2.1、重要的Opencv函数

2.1.1、cv::findContours(src, contours, hierarchy, retrivalMode, approxiMode, offSet);

2.1.2、cv::Canny(src, edges, lowThreshold, highThreshold, kernel_size, useL2Gradient);

2.2、例程中使用到的其他方法

2.2.1、cv::blur(src,blurImg,size,anchor,borderType);

2.2.2、cv::threshold(src,binaryImg, thresh, maxVal, threshType);

2.2.3、drawContours(drawing, contours, index, color, lineThickness, lineType, hierarchy, maxLevel);

3、代码和运行效果

3.1、示例代码

3.2、运行结果


1、图像找轮廓和边简介

进行图像处理任务时,图像内部形状的边缘信息往往包含了大量的细节,比如圆形,只要能找到圆形的轮廓我们就能判断出来这个形状是圆,而且能据此计算出圆心、半径、面积等其他感兴趣的数据。后续的尺寸测量、目标检测等任务中也常常会用到找轮廓、找边的算法。

2、OpenCV中找轮廓找边用到的方法

2.1、重要的Opencv函数

2.1.1、cv::findContours(src, contours, hierarchy, retrivalMode, approxiMode, offSet);

findContours参数列表

参数名说明
src灰度图像(8UC1),一般是二值化后的图像
contours用于存放找到的轮廓点
hierarchy用于存储轮廓之间的层次关系
retrivalMode轮廓提取方式,可以选择最外层或者多层轮廓等
approxiMode轮廓计算方式
offSet轮廓点偏移量

2.1.2、cv::Canny(src, edges, lowThreshold, highThreshold, kernel_size, useL2Gradient);

Canny参数列表

参数名说明
src灰度图像(8UC1)
edges用于保存边缘信息的图像,该处理后续使用的图像
lowThreshold低阈值,低于此值都不作为边界
highThreshold高阈值,高于此值都作为边界
kernel_size卷积核大小
useL2Gradient使用L2范数提高计算精度

2.2、例程中使用到的其他方法

2.2.1、cv::blur(src,blurImg,size,anchor,borderType);

blur参数列表

参数名说明
src输入图像
blurImg模糊操作后的效果图象
size卷积核大小
anchor锚点,一般都是卷积核中间对应的位置
borderType运算时边界补充值类型

2.2.2、cv::threshold(src,binaryImg, thresh, maxVal, threshType);

threshold参数

2.2.3、drawContours(drawing, contours, index, color, lineThickness, lineType, hierarchy, maxLevel);

drawContours参数

参数名说明
drawing要绘制轮廓点的图像
contours用来绘制轮廓的点集
index要绘制的点集(子集)的索引
color绘制轮廓的颜色
lineThickness绘制轮廓的线宽
lineType线的形式,默认8连通域
hierarchy轮廓之间的层次关系,一般由findContours方法提供
maxLevel绘图等级

3、代码和运行效果

3.1、示例代码

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;

int main()
{
    //读取图像
    //cv::Mat src = cv::imread("C:\\Users\\111\\Desktop\\IMG_20240731_222630.jpg",cv::IMREAD_GRAYSCALE);// cv::IMREAD_GRAYSCALE:读取图像的灰度图

    //创建测试灰度图
    cv::Mat src = cv::Mat::zeros(400, 400, CV_8UC1);// 创建一个空白的黑色图像,大小为400x400,类型为8位无符号整型(即灰度图)
    cv::Point center = cv::Point(200, 200);// 将要绘制圆的圆心
    int radius = 100;// 设置圆的半径  
    cv::Scalar colorSrc = cv::Scalar(255, 255, 255);// 设置绘图颜色(这里是白色)
    int thickness = -1;// 绘制线的宽度,默认是1,这里设置-1表示填充整个圆内部
    cv::LineTypes lineTypeSrc = cv::LINE_8;// 线的形式,默认8连通域
    int shift = 0;// 调整中心点坐标和半径值中的小数位数,默认是0:不调整,随数字增大,圆的中心坐标值减小,半径减小
    cv::circle(src, center, radius, colorSrc, thickness, lineTypeSrc,shift);// 绘制一个白色的圆 =cv::circle(src, center, radius, colorSrc, thickness)

    // 显示图像  
    cv::namedWindow("Img", cv::WINDOW_NORMAL);// cv::WINDOW_NORMAL:可调整大小或者用来将图像由全屏显示切换为常规大小
    cv::imshow("Img", src);
    cv::waitKey();

    //图像模糊
    cv::Mat blurImg;
    cv::Size size = cv::Size(5,5);// 卷积核大小,越大模糊效果越明显,可以横向和纵向设置不同值
    cv::Point anchor = cv::Point(-1,-1);// 卷积运算后结果作为哪个位置的值,默认(-1,-1)表示卷积核中心位置
    cv::BorderTypes borderType = cv::BORDER_DEFAULT;// 图像边缘的点计算卷积时需拓展边缘外的点,该值决定补充点像素值规律,默认以边缘为对称轴补充图像内的像素
    cv::blur(src,blurImg,size,anchor,borderType);// =cv::blur(src,blurImg,size)

    //图像二值化
    cv::Mat binaryImg;
    double thresh = 150;// 阈值,以该值为分界线,高于该值的像素值都设为maxVal,低于此值都设为0
    double maxVal = 255;// 最大像素值,高于阈值的像素值设为此值
    cv::ThresholdTypes threshType = cv::THRESH_BINARY;// 阈值分割的操作方式,全局阈值、自动阈值、三角阈值等
    cv::threshold(blurImg,binaryImg, thresh, maxVal, threshType);// 根据阈值分割方式选择可以选择使用或不适用返回值

    //找轮廓
    vector<vector<cv::Point>> contours;// 用于接收轮廓点数据,注意是二维数组,根据实际情况选择使用全部或部分数据
    vector<cv::Vec4i> hierarchy; // 用于存储轮廓之间的层次关系,如果不需要可以忽略
    cv::RetrievalModes retrivalMode = cv::RETR_EXTERNAL;// 轮廓提取方式,根据需要选择最外层或者多层轮廓
    cv::ContourApproximationModes approxiMode = cv::CHAIN_APPROX_SIMPLE;// 轮廓计算方式,如果你需要轮廓的精确表示,可以使用CHAIN_APPROX_NONE
    cv::Point offSet = cv::Point();// 偏移量,计算的点会根据该点进行偏移,默认不偏移
    cv::findContours(binaryImg, contours, hierarchy, retrivalMode, approxiMode, offSet);// =cv::findContours(binaryImg, contours, retrivalMode, approxiMode)

    //绘制轮廓
    cv::Mat drawing = cv::Mat::zeros(src.size(), CV_8UC1); // 创建一个与原图同样大小的黑色画布,保持8UC1(灰度图)
    cv::Scalar color = cv::Scalar(255, 255, 255); // 白色
    int lineThickness = 1;// 线宽,默认值1
    cv::LineTypes lineType = cv::LINE_8;// 线的形式,默认8连通域
    int maxLevel = 0;// 绘图等级,越大绘的越多
    for (int i = 0; i < contours.size(); i++) {
        cv::drawContours(drawing, contours, i, color, lineThickness, lineType, hierarchy, maxLevel);//绘制第i组轮廓点
    }// 如果绘制全部轮廓点:drawContours(drawing, contours, -1, color);
    cv::namedWindow("Contours", cv::WINDOW_NORMAL);
    cv::imshow("Contours", drawing);
    cv::waitKey();

    // canny算子找边
    cv::Mat edges;
    double lowThreshold = 50;// 低阈值,低于此值都不作为边界
    double highThreshold = 150;// 高阈值,高于此值都作为边界;高低阈值之间看是否相连
    int kernel_size = 3;// 卷积核大小,sobel矩阵大小,默认3
    bool useL2Gradient = false;// 是否需要使用L2范数提高梯度计算精度,默认false
    cv::Canny(src, edges, lowThreshold, highThreshold, kernel_size, useL2Gradient);// =cv::Canny(src, edges, lowThreshold, highThreshold)
    cv::namedWindow("Edges", cv::WINDOW_NORMAL);
    cv::imshow("Edges", edges);
    cv::waitKey();
}

3.2、运行结果

图像从左到右依次是原图,轮廓图,边缘图

从运行结果来看,其实找轮廓和直接canny找边效果差不多,但是找轮廓方法使用更广泛,毕竟可以直接拿到轮廓点数据,而且操作方式方法更多,运用更灵活。

  • 8
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值