opencv 5 图像轮廓与图像分割修复 2 使用多边形将轮廓包围

使用多边形将轮廓包围

返回外部矩阵边界(boundingRect()函数)

寻找最小包围矩形(minAreaRect()函数)

寻找最小包围圆形(minEnclosingCircle函数)


用椭圆拟合二维点集(fitEllipse()函数)

逼近多边形曲线(approxPolyDP()函数)

基础示例:创建包围轮廓的矩形边界

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;

//-----------------------------------【ShowHelpText( )函数】-----------------------------
//          描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{

    //输出欢迎信息和OpenCV版本

    printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);
    printf("\n\n  ----------------------------------------------------------------------------\n");

    //输出一些帮助信息
    printf("\n\n\n\t\t\t欢迎来到【矩形包围示例】示例程序~\n\n");
    printf("\n\n\t按键操作说明: \n\n"
        "\t\t键盘按键【ESC】、【Q】、【q】- 退出程序\n\n"
        "\t\t键盘按键任意键 - 重新生成随机点,并寻找最小面积的包围矩形\n");
}

int main()
{
    //改变console字体颜色
    system("color 1F");

    //显示帮助文字
    ShowHelpText();

    //初始化变量和随机值
    Mat image(600, 600, CV_8UC3);
    RNG& rng = theRNG();

    //循环,按下ESC,Q,q键程序退出,否则有键按下便一直更新
    while (1)
    {
        //参数初始化
        int count = rng.uniform(3, 103);//随机生成点的数量
        vector<Point> points;//点值

        //随机生成点坐标
        for (int i = 0; i < count; i++)
        {

            Point point;
            point.x = rng.uniform(image.cols / 4, image.cols * 3 / 4);
            point.y = rng.uniform(image.rows / 4, image.rows * 3 / 4);

            points.push_back(point);
        }

        //对给定的 2D 点集,寻找最小面积的包围矩形
        RotatedRect box = minAreaRect(Mat(points));
        Point2f vertex[4];
        box.points(vertex);

        //绘制出随机颜色的点
        image = Scalar::all(0);
        for (int i = 0; i < count; i++)
            circle(image, points[i], 3, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), FILLED, LINE_AA);

        //绘制出最小面积的包围矩形
        for (int i = 0; i < 4; i++)
            line(image, vertex[i], vertex[(i + 1) % 4], Scalar(100, 200, 211), 2, LINE_AA);

        //显示窗口
        imshow("矩形包围示例", image);

        //按下ESC,Q,或者q,程序退出
        char key = (char)waitKey();
        if (key == 27 || key == 'q' || key == 'Q') // 'ESC'
            break;
    }

    return 0;
}

基础示例:创建包围轮廓的圆形边界、

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;

//-----------------------------------【ShowHelpText( )函数】----------------------------------
//          描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{

    //输出欢迎信息和OpenCV版本

    printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION );
    printf("\n\n  ----------------------------------------------------------------------------\n");

    //输出一些帮助信息
    printf("\n\n\t\t\t欢迎来到【寻找最小面积的包围圆】示例程序~\n");
    printf("\n\n\t按键操作说明: \n\n"
        "\t\t键盘按键【ESC】、【Q】、【q】- 退出程序\n\n"
        "\t\t键盘按键任意键 - 重新生成随机点,并寻找最小面积的包围圆\n" );
}

int main(  )
{
    //改变console字体颜色
    system("color 1F"); 

    //显示帮助文字
    ShowHelpText();

    //初始化变量和随机值
    Mat image(600, 600, CV_8UC3);
    RNG& rng = theRNG();

    //循环,按下ESC,Q,q键程序退出,否则有键按下便一直更新
    while(1)
    {
        //参数初始化
        int count = rng.uniform(3, 103);//随机生成点的数量
        vector<Point> points;//点值

        //随机生成点坐标
        for(int  i = 0; i < count; i++ )
        {

            Point point;
            point.x = rng.uniform(image.cols/4, image.cols*3/4);
            point.y = rng.uniform(image.rows/4, image.rows*3/4);

            points.push_back(point);
        }

        //对给定的 2D 点集,寻找最小面积的包围圆
        Point2f center;
        float radius = 0;
        minEnclosingCircle(Mat(points), center, radius);

        //绘制出随机颜色的点
        image = Scalar::all(0);
        for( int i = 0; i < count; i++ )
            circle( image, points[i], 3, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), FILLED, LINE_AA );

        //绘制出最小面积的包围圆
        circle(image, center, cvRound(radius), Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 2, LINE_AA);//cvRound四舍五入

        //显示窗口
        imshow( "圆形包围示例", image );

        //按下ESC,Q,或者q,程序退出
        char key = (char)waitKey();
        if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
            break;
    }

    return 0;
}

综合示例程序:使用多边形包围轮廓

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;

//-----------------------------------【宏定义部分】--------------------------------------------
//  描述:定义一些辅助宏
//------------------------------------------------------------------------------------------------
#define WINDOW_NAME1 "【原始图窗口】"        //为窗口标题定义的宏
#define WINDOW_NAME2 "【效果图窗口】"        //为窗口标题定义的宏 

//-----------------------------------【全局变量声明部分】--------------------------------------
//  描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage;
Mat g_grayImage;
int g_nThresh = 50;//阈值
int g_nMaxThresh = 255;//阈值最大值
RNG g_rng(12345);//随机数生成器

//-----------------------------------【全局函数声明部分】--------------------------------------
//   描述:全局函数的声明
//-----------------------------------------------------------------------------------------------
void on_ContoursChange(int, void*);
static void ShowHelpText();

//-----------------------------------【main( )函数】--------------------------------------------
//   描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main()
{
    //【0】改变console字体颜色
    system("color 1F");

    //【0】显示欢迎和帮助文字
    ShowHelpText();

    //【1】载入3通道的原图像
    g_srcImage = imread("1.jpg", 1);
    if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }

    //【2】得到原图的灰度图像并进行平滑
    cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
    blur(g_grayImage, g_grayImage, Size(3, 3));

    //【3】创建原始图窗口并显示
    namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
    imshow(WINDOW_NAME1, g_srcImage);

    //【4】设置滚动条并调用一次回调函数
    createTrackbar(" 阈值:", WINDOW_NAME1, &g_nThresh, g_nMaxThresh, on_ContoursChange);
    on_ContoursChange(0, 0);

    waitKey(0);

    return(0);
}

//----------------------------【on_ContoursChange( )函数】---------------------------------
//      描述:回调函数
//-------------------------------------------------------------------------------------------------
void on_ContoursChange(int, void*)
{
    //定义一些参数
    Mat threshold_output;
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    // 使用Threshold检测边缘
    threshold(g_grayImage, threshold_output, g_nThresh, 255, THRESH_BINARY);

    // 找出轮廓
    findContours(threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

    // 多边形逼近轮廓 + 获取矩形和圆形边界框
    vector<vector<Point> > contours_poly(contours.size());
    vector<Rect> boundRect(contours.size());
    vector<Point2f>center(contours.size());
    vector<float>radius(contours.size());

    //一个循环,遍历所有部分,进行本程序最核心的操作
    for (unsigned int i = 0; i < contours.size(); i++)
    {
        approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);//用指定精度逼近多边形曲线
        boundRect[i] = boundingRect(Mat(contours_poly[i]));//计算点集的最外面(up-right)矩形边界
        minEnclosingCircle(contours_poly[i], center[i], radius[i]);//对给定的 2D点集,寻找最小面积的包围圆形
    }

    // 绘制多边形轮廓 + 包围的矩形框 + 圆形框
    Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3);
    for (int unsigned i = 0; i < contours.size(); i++)
    {
        Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));//随机设置颜色
        drawContours(drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point());//绘制轮廓
        rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);//绘制矩形
        circle(drawing, center[i], (int)radius[i], color, 2, 8, 0);//绘制圆
    }

    // 显示效果图窗口
    namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);
    imshow(WINDOW_NAME2, drawing);
}

//-----------------------------------【ShowHelpText( )函数】----------------------------------
//      描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
    //输出欢迎信息和OpenCV版本

    printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);
    printf("\n\n  ----------------------------------------------------------------------------\n");

    //输出一些帮助信息
    printf("\n\n\n\t欢迎来到【创建包围轮廓的矩形和圆形边界框】示例程序~\n\n");
    printf("\n\n\t按键操作说明: \n\n"
        "\t\t键盘按键【ESC】- 退出程序\n\n"
        "\t\t滑动滚动条 - 改变阈值\n\n");
}

原文地址:https://www.cnblogs.com/xingkongcanghai/p/11197111.html

时间: 2024-10-01 06:40:20

opencv 5 图像轮廓与图像分割修复 2 使用多边形将轮廓包围的相关文章

OpenCV提取图像轮廓总结

OpenCV函数 cvFindContours提取轮廓 :点击打开链接  点击打开链接 点击打开链接 点击打开链接 提取元素的轮廓及形状描述子 点击打开链接 提取轮廓的点坐标 轮廓提取后,它是用关键点组成的,下面提取出这些关键点. 1.先输出所有关键点的个数cout<<"elements"<<contour->total<<endl; 2.for(int i=0;i<contour->total;++i) { CvPoint* p

[家里蹲大学数学杂志]第054期图像分割中的无边缘活动轮廓模型

$\bf 摘要$: 本文给出了王大凯等编的<图像处理中的偏微分方程方法>第 4.4 节的详细论述. $\bf 关键词$: 图像分割; 活动轮廓模型; matlab 编程 1 模型的建立 在图像中, 对象与背景的区别有时表现为平均灰度的明显不同. 由于这类图像既没有明显的边缘 ($\sev{\n I}$ 大), 也缺乏明显的纹理 (texture, 灰度变化有一定的规律, 并形成一定的 patten), 故测地线活动轮廓 (geodesic active contour, GAC, 或 snak

图像分割之(五)活动轮廓模型之Snake模型简介

在"图像分割之(一)概述"中咱们简单了解了目前主流的图像分割方法.下面咱们主要学习下基于能量泛函的分割方法.这里学习下Snake模型简单的知识,Level Set(水平集)模型会在后面的博文中说到. 基于能量泛函的分割方法: 该类方法主要指的是活动轮廓模型(active contour model)以及在其基础上发展出来的算法,其基本思想是使用连续曲线来表达目标边缘,并定义一个能量泛函使得其自变量包括边缘曲线,因此分割过程就转变为求解能量泛函的最小值的过程,一般可通过求解函数对应的欧拉

opencv对图像进行边缘及角点检测

opencv对图像进行边缘及角点检测 先看结果: 代码: // ConsoleApplication1_812.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "opencv2/opencv.hpp" class Imagedetector{ public: Imagedetector():threshold(-1) ,cross(5

OpenCV中图像的结构和区别

在OpenCV中,现在有很多种结构类型可以用来表示图像,它们之间有区别又有联系,现在记录一下它们之间的区别和相似之处,以便后面查看. 其中类型有: 1. Iplimage,2. Mat,3.CvMat, 4.CVArr: 其中: 1. IplImage: 较老版本的图像存储类型,在2.0之前使用: 2. CvArr: 也是较老的一种存储结构,是一种抽象的基类. 3. CvMat: 矩阵结构. 4. Mat:  新版本中使用的,推荐使用,是一个图像容器,基本上讲 Mat 是一个类,由两个数据部分组

用opencv读取图像鼠标点的像素,更正一个Bug

作者:skyseraph 出处:http://www.cnblogs.com/skyseraph/ 以下代码在网上流传很广. 不过,调试运行之后发现,功能是正确的,但是内存很快就耗尽,导致死机.经过查找,加上: cvReleaseImage(&img1);    //释放源图像占用的内存 这一行是我(szliug)加的,否则内存很快就会耗尽,会死机的. 之后运行正常. /*===============================================// 功能:OpenCV Ut

实验2014062701:opencv对图像的点操作

#include<Windows.h>#include<cv.h>#include<highgui.h>#include <cxcore.h>int main(){    IplImage* img = cvLoadImage("1.jpg");    IplImage* dst = cvCreateImage(cvGetSize(img),img->depth,1);    cvNamedWindow("GRAY&quo

OpenCV中图像算术操作与逻辑操作

OpenCV中图像算术操作与逻辑操作 在图像处理中有两类最重要的基础操作分别是图像点操作与块操作,简单点说图像点操作就是图像每个像素点的相关逻辑与几何运算.块操作最常见就是基于卷积算子的各种操作.实现各种不同的功能.今天小编就跟大家一起学习OpenCV中图像点操作相关的函数与应用场景.常见算术运算包括加.减.乘.除,逻辑运算包括与.或.非.异或.准备工作: 选择两张大小一致的图像如下.加载成功以后显示如下: 加法操作结果如下: 减法操作结果如下: 乘法操作结果如下: 除法操作结果如下: 权重加法

【opencv】图像细化

[opencv]图像细化 [opencv]图像细化 2014-02-17 21:03 5404人阅读 评论(14) 收藏 举报  分类: opencv(1)  版权声明:本文为博主原创文章,未经博主允许不得转载. 在我们进行图像处理的时候,有可能需要对图像进行细化,提取出图像的骨架信息,进行更加有效的分析. 图像细化(Image Thinning),一般指二值图像的骨架化(Image Skeletonization) 的一种操作运算. 所谓的细化就是经过一层层的剥离,从原来的图中去掉一些点,但仍