【opencv】示例-delaunay2.cpp 生成随机点集,并对这些点进行Delaunay三角剖分和Voronoi图的构建...

objectivec 复制代码
// 包含OpenCV图像处理头文件
#include <opencv2/imgproc.hpp>
// 包含OpenCV高层GUI(图形用户界面)操作的头文件
#include <opencv2/highgui.hpp>
// 包含标准输入输出头文件
#include <iostream>


// 使用命名空间cv避免每次都要加cv::
using namespace cv;
// 使用命名空间std避免每次都要加std::
using namespace std;


// 帮助信息函数声明,用于显示程序使用方法
static void help(char** argv)
{
    // 打印帮助信息:程序使用说明、如何停止程序等
    cout << "\nThis program demonstrates iterative construction of\n"
            "delaunay triangulation and voronoi tessellation.\n"
            "It draws a random set of points in an image and then delaunay triangulates them.\n"
            "Usage: \n";
    cout << argv[0];
    cout << "\n\nThis program builds the triangulation interactively, you may stop this process by\n"
            "hitting any key.\n";
}


// 绘制Delaunay点,辅助函数
static void draw_subdiv_point( Mat& img, Point2f fp, Scalar color )
{
    // 在图像中画一个以fp为中心,大小为3的实心圆,颜色为color
    circle( img, fp, 3, color, FILLED, LINE_8, 0 );
}


// 绘制Delaunay三角剖分的辅助函数
static void draw_subdiv( Mat& img, Subdiv2D& subdiv, Scalar delaunay_color )
{
#if 1
    vector<Vec6f> triangleList;
    // 获取Delaunay三角剖分后的三角形列表
    subdiv.getTriangleList(triangleList);
    vector<Point> pt(3);


    // 遍历每个三角形
    for( size_t i = 0; i < triangleList.size(); i++ )
    {
        Vec6f t = triangleList[i];
        // 将Vec6f转换为Point,并绘制三角形的三条边
        pt[0] = Point(cvRound(t[0]), cvRound(t[1]));
        pt[1] = Point(cvRound(t[2]), cvRound(t[3]));
        pt[2] = Point(cvRound(t[4]), cvRound(t[5]));
        line(img, pt[0], pt[1], delaunay_color, 1, LINE_AA, 0);
        line(img, pt[1], pt[2], delaunay_color, 1, LINE_AA, 0);
        line(img, pt[2], pt[0], delaunay_color, 1, LINE_AA, 0);
    }
#else
    // Else分支的代码没有启用,以下为备选的绘制Delaunay边的方式
    vector<Vec4f> edgeList;
    subdiv.getEdgeList(edgeList);
    for( size_t i = 0; i < edgeList.size(); i++ )
    {
        Vec4f e = edgeList[i];
        Point pt0 = Point(cvRound(e[0]), cvRound(e[1]));
        Point pt1 = Point(cvRound(e[2]), cvRound(e[3]));
        line(img, pt0, pt1, delaunay_color, 1, LINE_AA, 0);
    }
#endif
}


// 定位点并绘制相关联的三角形的辅助函数
static void locate_point( Mat& img, Subdiv2D& subdiv, Point2f fp, Scalar active_color )
{
    int e0=0, vertex=0;


    // 定位点在剖分中的位置
    subdiv.locate(fp, e0, vertex);


    // 如果点位于某个三角形内或边上
    if( e0 > 0 )
    {
        int e = e0;
        do
        {
            Point2f org, dst;
            // 获取当前边的原点和目标点,并绘制边
            if( subdiv.edgeOrg(e, &org) > 0 && subdiv.edgeDst(e, &dst) > 0 )
                line( img, org, dst, active_color, 3, LINE_AA, 0 );


            // 获取下一条边
            e = subdiv.getEdge(e, Subdiv2D::NEXT_AROUND_LEFT);
        }
        // 遍历完所有与点fp相关的边
        while( e != e0 );
    }


    // 绘制点fp
    draw_subdiv_point( img, fp, active_color );
}


// 绘制Voronoi图的辅助函数
static void paint_voronoi( Mat& img, Subdiv2D& subdiv )
{
    // Voronoi图的各个面
    vector<vector<Point2f> > facets;
    // 对应每个Voronoi面的中心点
    vector<Point2f> centers;
    subdiv.getVoronoiFacetList(vector<int>(), facets, centers);


    vector<Point> ifacet;
    vector<vector<Point> > ifacets(1);


    // 遍历所有的Voronoi面
    for( size_t i = 0; i < facets.size(); i++ )
    {
        ifacet.resize(facets[i].size());
        for( size_t j = 0; j < facets[i].size(); j++ )
            ifacet[j] = facets[i][j];


        // 随机生成颜色
        Scalar color;
        color[0] = rand() & 255;
        color[1] = rand() & 255;
        color[2] = rand() & 255;
        // 填充Voronoi面
        fillConvexPoly(img, ifacet, color, 8, 0);


        // 绘制Voronoi面的边界
        ifacets[0] = ifacet;
        polylines(img, ifacets, true, Scalar(), 1, LINE_AA, 0);
        // 绘制Voronoi中心
        circle(img, centers[i], 3, Scalar(), FILLED, LINE_AA, 0);
    }
}


// 主函数
int main( int argc, char** argv )
{
    // 解析命令行参数,尤其是检测是否有"help"参数
    cv::CommandLineParser parser(argc, argv, "{help h||}");
    if (parser.has("help"))
    {
        // 如果有"help"参数,则显示帮助信息并退出程序
        help(argv);
        return 0;
    }


    // 设置活跃面颜色和Delaunay边颜色
    Scalar active_facet_color(0, 0, 255), delaunay_color(255,255,255);
    // 设置图像的显示区域为600x600大小
    Rect rect(0, 0, 600, 600);


    // 初始化Subdiv2D对象,它是用于Delaunay三角剖分的
    Subdiv2D subdiv(rect);
    // 创建一个与显示区域大小相同的图像
    Mat img(rect.size(), CV_8UC3);


    // 设置图像的背景色为黑色
    img = Scalar::all(0);
    // 窗口名称
    string win = "Delaunay Demo";
    // 显示窗口
    imshow(win, img);


    // 随机生成200个点,并进行三角剖分
    for( int i = 0; i < 200; i++ )
    {
        // 在范围内随机生成一个点
        Point2f fp( (float)(rand()%(rect.width-10)+5),
                    (float)(rand()%(rect.height-10)+5));


        // 定位点,并绘制相关联的三角形
        locate_point( img, subdiv, fp, active_facet_color );
        imshow( win, img );


        // 如果检测到按键,则停止循环
        if( waitKey( 100 ) >= 0 )
            break;


        // 将生成的点插入到三角剖分中
        subdiv.insert(fp);


        // 重绘图像和三角剖分
        img = Scalar::all(0);
        draw_subdiv( img, subdiv, delaunay_color );
        imshow( win, img );


        // 如果检测到按键,则停止循环
        if( waitKey( 100 ) >= 0 )
            break;
    }


    // 绘制最终的Voronoi图
    img = Scalar::all(0);
    paint_voronoi( img, subdiv );
    imshow( win, img );


    // 等待用户按键
    waitKey(0);


    // 程序正常结束
    return 0;
}

该代码的功能是演示如何在图像中生成随机点集,并对这些点进行Delaunay三角剖分和Voronoi图的构建。它逐步显示了Delaunay三角剖分的构建过程,用户可以通过按任意键来停止过程。最后,它会显示最终的Voronoi图。这是计算几何和机器视觉中常用到的算法。

相关推荐
千天夜6 分钟前
激活函数解析:神经网络背后的“驱动力”
人工智能·深度学习·神经网络
大数据面试宝典7 分钟前
用AI来写SQL:让ChatGPT成为你的数据库助手
数据库·人工智能·chatgpt
封步宇AIGC12 分钟前
量化交易系统开发-实时行情自动化交易-3.4.1.2.A股交易数据
人工智能·python·机器学习·数据挖掘
m0_5236742114 分钟前
技术前沿:从强化学习到Prompt Engineering,业务流程管理的创新之路
人工智能·深度学习·目标检测·机器学习·语言模型·自然语言处理·数据挖掘
HappyAcmen23 分钟前
IDEA部署AI代写插件
java·人工智能·intellij-idea
噜噜噜噜鲁先森1 小时前
看懂本文,入门神经网络Neural Network
人工智能
InheritGuo1 小时前
It’s All About Your Sketch: Democratising Sketch Control in Diffusion Models
人工智能·计算机视觉·sketch
weixin_307779132 小时前
证明存在常数c, C > 0,使得在一系列特定条件下,某个特定投资时刻出现的概率与天数的对数成反比
人工智能·算法·机器学习
封步宇AIGC2 小时前
量化交易系统开发-实时行情自动化交易-3.4.1.6.A股宏观经济数据
人工智能·python·机器学习·数据挖掘
Jack黄从零学c++2 小时前
opencv(c++)图像的灰度转换
c++·人工智能·opencv