轮廓追踪与C#实现

简介: 原文:轮廓追踪与C#实现            轮廓追踪是图像处理中常见的方法,主要目的是追踪二值图像中目标物体的外轮廓,所得结果为单像素闭合轮廓。 流       程:                    1. 确定种子点,即追踪的起始像素(如最左上方在轮廓上的像素点);                                       2. 以相应的追踪规则搜索外部轮廓点。
原文: 轮廓追踪与C#实现

           轮廓追踪是图像处理中常见的方法,主要目的是追踪二值图像中目标物体的外轮廓,所得结果为单像素闭合轮廓。

流       程:

                   1. 确定种子点,即追踪的起始像素(如最左上方在轮廓上的像素点);                   

                   2. 以相应的追踪规则搜索外部轮廓点。

追踪规则:以种子点为起点,按某以确定方向(如顺时针)寻找与当前轮廓点相邻(8邻域)的轮廓点(第一个相邻),再以 此点为当前轮廓点按照前述方法搜索,直到最后搜索到 的点与种子点相同为止。

注        意:搜索过程中,下一次搜索的起始方向,是上一次搜索到当前像素方向的逆时针45度方向(如果搜索方向是顺时针)。如当前像素在上个轮廓像素的右邻域,那么当前像素可以从其右上角方向搜索,因为这时其上邻域必不是轮廓像素。这样做可以减少算法的计算量。

      追踪过程如图1所示:其中红色点表示种子点,黑色点表示轮廓点,蓝色点表示目标物体内部点,搜索方向是顺时针。

      我的代码中dircection是搜索方向,定义如下:

      int[,] direction = new int[8, 2] { { -1, 0 }, { -1, +1 }, { 0, +1 }, { +1, +1 }, { +1, 0 }, { +1, -1 }, { 0, -1 }, { -1, -1 } };

      在代码中的abrect是一个矩形对象,指的是追踪目标所在矩形,这是我原来代码中要用的东西,和这个算法没有关系。

                                 

                                                                        图1.追踪过程图示

C#实现:


unsafe protected void TraceContour(byte* imagedata, int wid, int hei)
        {
            int stride = (wid + 3) / 4 * 4;
            int offset = stride - wid;

            List<Point> ContourPoints = new List<Point>();
            
            bool bfindstartpoint = false;
            int ss = 0;
            byte* p = null;
            for (int i = 0; i < hei; i++)
            {
                imagedata[i * stride] = 0;
                imagedata[i * stride + wid - 1] = 0;
            }
            for (int i = 0; i < wid; i++)
            {
                imagedata[i] = 0;
                imagedata[(hei - 1) * stride + i] = 0;
            }
            //寻找种子点
            for (int i = 1; i < hei - 1; i++)
            {
                p = imagedata + i * stride;
                for (int j = 1; j < wid - 1; j++)
                {
                    if (p[j] == 255 && (p[j + 1] + p[j - 1] + p[j - stride] + p[j + stride] + p[j + stride - 1] + p[stride + j + 1] + p[j - stride - 1] + p[j 

- stride + 1] != 0))
                    {
                        bfindstartpoint = true;
                        ss = i * stride + j;
                        break;
                    }
                }
                if (bfindstartpoint)
                {
                    break;
                }
            }

            //寻找种子点失败
            if (!bfindstartpoint)
                return ;

            //搜索方向
            /*
             * 7 0 1
             * 6 + 2
             * 5 4 3
             */           
            int begindirect = 0;//从0开始顺时针搜索
            int kk = ss;
            int k = 0;
            int bb = 0;
            bool bfindpoint = false;
            Point pt = new Point();

            while (bfindstartpoint)
            {
                bfindpoint = false;
                k = begindirect;
                while (!bfindpoint)
                {
                    bb = kk;
                    kk += (stride * direction[k, 0] + direction[k, 1]);
                    int ih = kk / stride;
                    int iw = kk % stride;
                    //如果只有一点会死循环
                    //如果超出边界
                    if (ih == hei || iw == wid || kk < ss || (kk >= stride * hei))
                    {
                        k++;
                        kk = bb;
                        if (k == 8)
                            k = 0;
                    }
                    else if (imagedata[kk] == 255)
                    {
                        //还原到原坐标系
                        pt.X = iw + abrect.X;
                        pt.Y = ih + abrect.Y;
                        ContourPoints.Add(pt);
                        if (kk == ss)
                            bfindstartpoint = false;
                        begindirect = (k + 7) % 8;//逆时针旋转45度
                        bfindpoint = true;
                    }
                    else
                    {
                        kk = bb;
                        k++;
                        if (k == 8)
                            k = 0;
                    }
                }
            }
        }


目录
相关文章
|
机器学习/深度学习 文字识别 数据挖掘
Visionpro从小白到大佬,第一章了解工具名称和用途
Visionpro从小白到大佬,第一章了解工具名称和用途
3401 0
Visionpro从小白到大佬,第一章了解工具名称和用途
typro收费了,怎么看markdown文章?推荐谷歌markdown插件
typro收费了,怎么看markdown文章?推荐谷歌markdown插件
424 0
typro收费了,怎么看markdown文章?推荐谷歌markdown插件
|
自然语言处理 安全 前端开发
什么是CMS?CMS适合搭建什么网站?
CMS(内容管理系统)用于快速搭建、管理和发布网站内容。它支持自定义板块,降低建站门槛。CMS分为独立CMS和SaaS CMS两种类型,主要功能包括角色分配、SEO优化、多语言支持等。建站流程包括确定需求、选择系统、购买域名和主机、安装系统、选择模板、扩展栏目、添加内容、上线和维护。PageAdmin CMS是一款优秀的建站系统,推荐免费试用。
649 1
|
11月前
|
小程序 测试技术 数据安全/隐私保护
微信公众号接口测试实战指南
微信公众号接口测试是确保系统稳定性和功能完整性的重要环节。本文详细介绍了测试全流程,包括准备、工具选择(如Postman、JMeter)、用例设计与执行,以及常见问题的解决方法。通过全面测试,可以提前发现潜在问题,优化用户体验,确保公众号上线后稳定运行。内容涵盖基础接口、高级接口、微信支付和数据统计接口的测试,强调了功能验证、性能优化、安全保护及用户体验的重要性。未来,随着微信生态的发展,接口测试将面临更多挑战和机遇,如小程序融合、AI应用和国际化拓展。
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
1383 0
|
关系型数据库 数据库连接 API
Supabase
Supabase 是一款开源的后端服务平台,可以帮助开发人员快速构建和部署应用程序。Supabase 提供了基于 PostgreSQL 数据库的服务,支持实时数据同步、身份验证和授权等功能。
2964 1
|
JSON 前端开发 Java
LaTex下载、安装及配置并搭配使用Visual Studio Code教程(建议收藏)2022最新完整版
LaTex下载、安装及配置并搭配使用Visual Studio Code教程(建议收藏)2022最新完整版
2202 1
LaTex下载、安装及配置并搭配使用Visual Studio Code教程(建议收藏)2022最新完整版
|
机器学习/深度学习 存储 算法
C# | 凸包算法之Graham,快速找到一组点最外侧的凸多边形
这篇关于凸包算法的文章,本文使用C#和Graham算法来实现凸包算法。 首先消除两个最基本的问题: 什么是凸包呢? 凸包是一个包围一组点的凸多边形。凸多边形是指多边形中的每个内角都小于180度的多边形。 凸包算法有什么用呢? 凸包算法的作用是找到这个凸多边形,并且使用最少的点来绘制出它的轮廓。凸包算法在计算机图形学、计算几何和机器学习等领域中有着广泛的应用。
409 0
|
算法 小程序 大数据
大学生志愿者管理信息系统设计与实现(论文+源码)_kaic
在国家的十四五期间,志愿服务成为推动社会文明发展的重要力量。大学生是志愿活动的中坚力量。现有的志愿管理工作不能满足志愿活动的需要,存在活动找不到志愿者,志愿者找不到活动的情况。为服务良好的志愿服务体系,对大学生志愿者管理系统进行分析与设计。 大学生志愿者管理系统采用结构化开发方法,通过业务流程分析,数据流程分析,数据字典进行系统分析,系统设计包括了功能模块设计,数据库设计和输入输出设计,来实现整个开发过程。 大学生志愿者管理信息系统主要包括志愿资讯管理,志愿活动管理,志愿审核管理,志愿培训管理和基本信息管理五个功能模块。其中最重要的是志愿活动管理,从志愿组织提交活动申请和活动筹备,到志愿者报名
大学生志愿者管理信息系统设计与实现(论文+源码)_kaic

热门文章

最新文章