OpenCV实现绘制轮廓外接矩形

 更新时间:2022年12月29日 14:02:28   作者:黑色の铅笔  
这篇文章主要为大家详细介绍了OpenCV实现绘制轮廓外接矩形的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

1.寻找轮廓

api

void cv::findContours( InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point()

各个参数详解如下:

Image表示输入图像,必须是二值图像,二值图像可以threshold输出、Canny输出、inRange输出、自适应阈值输出等。

Contours获取的轮廓,每个轮廓是一系列的点集合

Hierarchy轮廓的层次信息,每个轮廓有四个相关信息,分别是同层下一个、前一个、第一个子节点、父节点

mode 表示轮廓寻找时候的拓扑结构返回 -RETR_EXTERNAL表示只返回最外层轮廓 -RETR_TREE表示返回轮廓树结构

  • CV_RETR_EXTERNAL:只检测外轮廓。忽略轮廓内部的洞
  • CV_RETR_LIST:检测所有轮廓,但不建立继承(包含)关系
  • CV_RETR_TREE:检测所有轮廓,并且建立所有的继承(包含)关系。也就是说用CV_RETR_EXTERNAL和CV_RETR_LIST方法的时候hierarchy这个变量是没用的,因为前者没有包含关系,找到的都是外轮廓,后者仅仅是找到所哟的轮廓但并不把包含关系区分。用TREE这种检测方法的时候我们的hierarchy这个参数才是有意义的
  • CV_RETR_CCOMP:检测所有轮廓,但是仅仅建立两层包含关系。外轮廓放到顶层,外轮廓包含的第一层内轮廓放到底层,如果内轮廓还包含轮廓,那就把这些内轮廓放到顶层去。

Method表示轮廓点集合取得是基于什么算法,常见的是基于CHAIN_APPROX_SIMPLE链式编码方法

注意,如果图像底色是白色,则检测最外层的轮廓为图像边框

2.绘制轮廓外接矩形

绘制外接矩形包括两种:

绘制最大外接矩形

(Rect cv::boundingRect( InputArray points ))

其中,输入参数points为一系列点的集合(findContours中contours中的一个元素),对轮廓来说就是该轮廓的点集 返回结果是一个矩形,x, y, w, h

绘制最小外接矩形

RotatedRect cv::minAreaRect( InputArray points )

其中,输入参数points为一系列点的集合(findContours中contours中的一个元素) ,对轮廓来说就是该轮廓的点集 返回结果是一个旋转矩形,包含下面的信息: - 矩形中心位置 - 矩形的宽高 - 旋转角度。

3.代码

EdgeDetection.h

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

using namespace std;
using namespace cv;


class EdgeDetection
{
    cv::Mat m_img;
    cv::Mat m_canny;
public:
    EdgeDetection(cv::Mat iamge);
    bool cannyProcess(unsigned int downThreshold,unsigned int upThreshold);
    bool getContours();

    ~EdgeDetection();
};

EdgeDetection.cpp

#include "EdgeDetection.h"

EdgeDetection::EdgeDetection(cv::Mat image)
{
    m_img = image;
}

bool EdgeDetection::cannyProcess(unsigned int downThreshold, unsigned int upThreshold)
{
    bool ret=true;

    if (m_img.empty())
    {
        ret = false;
    }

    cv::Canny(m_img, m_canny, downThreshold, upThreshold);
    cv::imshow("Canny", m_canny);

    return ret;
}

bool EdgeDetection::getContours()
{
    bool ret = true;
    if (m_canny.empty())
    {
        ret = false;
    }

    cv::Mat k = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3), cv::Point(-1, -1));
    cv::dilate(m_canny, m_canny, k);
    imshow("dilate", m_canny);

    // 轮廓发现与绘制
    vector<vector<cv::Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(m_canny, contours, cv::RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());

    for (size_t i = 0; i < contours.size();++i)
    {
        // 最大外接轮廓
        cv::Rect rect = cv::boundingRect(contours[i]);
        cv::rectangle(m_img,rect,cv::Scalar(0,255,0),2,LINE_8);


        // 最小外接轮廓
        RotatedRect rrt = minAreaRect(contours[i]);
        Point2f pts[4];
        rrt.points(pts);
        // 绘制旋转矩形与中心位置
        for (int i = 0; i < 4; i++) {
            line(m_img, pts[i % 4], pts[(i + 1) % 4], Scalar(0, 0, 255), 2, 8, 0);
        }
        Point2f cpt = rrt.center;
        circle(m_img, cpt, 2, Scalar(255, 0, 0), 2, 8, 0);
    }





    imshow("contours", m_img);
    return ret;
}

EdgeDetection::~EdgeDetection()
{
}

main.cpp

#include"EdgeDetection.h"
using namespace std;
using namespace cv;



int main(int argc, char* argv[])
{
    Mat src = imread("rect.jpg");
    if (src.empty())
    {
        cout << "image is empty" << endl;
        return -1;
    }

    imshow("input", src);

    EdgeDetection ed(src);

    ed.cannyProcess(80,160);
    ed.getContours();

    waitKey(0);
    return 0;
}

原图

canny

目标图

到此这篇关于OpenCV实现绘制轮廓外接矩形的文章就介绍到这了,更多相关OpenCV轮廓外接矩形内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++中的策略模式浅析

    C++中的策略模式浅析

    策略模式属于C++设计模式中行为模式之一,该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。本文将通过示例详细讲解这一模式,需要的可以参考一下
    2023-02-02
  • c++中c_str()的用法示例

    c++中c_str()的用法示例

    这篇文章主要介绍了c++中c_str()的用法示例,帮助大家更好的理解和学习C++,感兴趣的朋友可以了解下
    2020-09-09
  • C语言中的线程信号控制详解

    C语言中的线程信号控制详解

    这篇文章主要通过一些示例为大家详细介绍一下C语言中的线程信号控制,文中的示例代码讲解详细,对我们深入了解C语言有一定的帮助,感兴趣的可以学习一下
    2023-02-02
  • Opencv实现边缘检测与轮廓发现及绘制轮廓方法详解

    Opencv实现边缘检测与轮廓发现及绘制轮廓方法详解

    这篇文章主要介绍了Opencv实现边缘检测与轮廓发现及绘制轮廓方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12
  • C语言运算符及其优先级汇总表口诀

    C语言运算符及其优先级汇总表口诀

    由于C语言的运算符优先级与C++的不完全一样(主要是增加了几个运算符),所以这个口诀不能完全实用于C++.但是应该能够兼容,大家可以比较一下他们的区别应该就能够很快掌握C++的优先级的
    2013-07-07
  • 浮点数在计算机中存储方式是怎样的

    浮点数在计算机中存储方式是怎样的

    这篇文章介绍了浮点数在计算机中是如何存储的,讲解的比较详细,有需要的朋友可以参考一下。
    2016-06-06
  • C++/Qt遍历多维数组的3种方式示例

    C++/Qt遍历多维数组的3种方式示例

    一维数组对于存储和处理一组数据很有用,但有时候,有必要使用多维数组,下面这篇文章主要给大家介绍了关于C++/Qt遍历多维数组的3种方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • 基于C++字符串替换函数的使用详解

    基于C++字符串替换函数的使用详解

    本篇文章是对C++字符串替换函数的使用进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C语言中将日期和时间以字符串格式输出的方法

    C语言中将日期和时间以字符串格式输出的方法

    这篇文章主要介绍了C语言中将日期和时间以字符串格式输出的方法,分别是ctime()函数和asctime()函数,注意参数区别,需要的朋友可以参考下
    2015-08-08
  • c++判断文件是否存在的方法汇总

    c++判断文件是否存在的方法汇总

    这篇文章主要介绍了c++判断文件是否存在的方法汇总,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08

最新评论