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

3f88429ef5ac00720e47142da22983b2.png

6eab893e4c49883c98b86ea7a0b638a4.png6bc79c1cb4b42019cb25e38d6af50e31.pngaf32f6dbc0275a2e467f1d82e3510cd1.png

23fa60a0be8a8af254f2e5b4c57be780.png

b0b4280d3511782eb999d5937e825367.png

// 包含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图。这是计算几何和机器视觉中常用到的算法。

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-13 01:38:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-13 01:38:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-13 01:38:02       82 阅读
  4. Python语言-面向对象

    2024-04-13 01:38:02       91 阅读

热门阅读

  1. P2678 [NOIP2015 提高组] 跳石头

    2024-04-13 01:38:02       38 阅读
  2. Golang 为什么需要用反射

    2024-04-13 01:38:02       36 阅读
  3. Leetcode56_合并区间

    2024-04-13 01:38:02       39 阅读
  4. Latex中todonotes超出页面范围及其他参数说明

    2024-04-13 01:38:02       39 阅读
  5. 第十三届蓝桥杯省赛C&C++ 研究生组2.0

    2024-04-13 01:38:02       38 阅读
  6. Ajax跨域请求

    2024-04-13 01:38:02       36 阅读
  7. pytorch 45 使用自己的数据对groundingdino进行微调

    2024-04-13 01:38:02       33 阅读
  8. vue3-element-admin实现同一个菜单多标签

    2024-04-13 01:38:02       33 阅读