弦箭算法的c语言实现本科毕业论文(编辑修改稿)内容摘要:

的颜色,所以一个字节可以表示 2 个像素。 对于 256 色位图,用 8 位就可以表示该像素的颜色,所以一个字节刚好可以表示 1 个像素。 下面有两点需要注意: ( 1)每一行的字节数必须是 4 的整数倍,如果不是,则需补齐。 ( 2) BMP 文件的数据存放是从下到上,从左到右的。 也就是说,从文件中最先读到的是图像最下面一行的左边第一个像素,然后是第二个像素,接下来是倒数第二行左边第一个像素,左边第二个像素。 以此类推,最后得到的是最上面一行的最右边的一个像素。 2 本文 编程环境 本文编程所使用的环境是 Microsoft Visual C++。 Visual C++提供了一个支持可视化编程的集成开发环境,采用标准的多窗口 Windows 用户界面,易于使用,可以很方便的生成人机界面。 通过C++编程,弦箭算法可以方便地嵌入实际应用,其代码也可应用于诸多领域。 由于 MFC 没有封装处理与 DIB 位图相关的 Windows API 函数的类,使得利用 C 语言实现对图像的处理相对复杂。 本文 利用 一个 现有 的图像处理程序 ImageProcessing,在此基础上,嵌入弦箭算法。 利用 该 程序,可以很方便地读取图像的各种信息,以及对图像数据进行计算。 3 弦 箭 累加 的编程实现 一、 类 Cdib 及 canny 算子 程序 ImageProcessing 是 在 VC++环境下 编写的对 BMP 图像进行处理的 MFC AppWizard 程序,可以对 BMP 图像进行变换、特征提取、图像分割等多种处理。 程序通过类 Cdib 来实现对 BMP 图像文件的 读取 、 显示、保存以及获取图像文件信息 等 , 在程序 ImageProcessing 中,类 Cdib 共设计了 13 个 属性( 成员变量 ) 和 30 个成员函数 , 通过它们 来 完成对图像的 一些 处理。 这里对 类 Cdib 中的 13 种属性 进行 简要 说明 如下 : LPVOID m_lpvColorTable:调色板指针; HBITMAP m_hBitmap: BITMAP结构指针; LPBYTE m_lpImage: DIB 位图数据块地址; LPBITMAPINFOHEADER m_lpBMIH: DIB信息头指针; HGLOBAL m_hGlobal:全局的句柄,用于内存映射文件中; Alloc m_nBmihAlloc:表示信息头内存分配的状况; Alloc m_nImageAlloc:表示位图数据分配的状况; DWORD m_dwSizeImage: DIB 位图中的字节数(信息头和调色板数据 除外); int m_nColorTableEntries:调色板表项数; HANDLE m_hFile:文件句柄; HANDLE m_hMap:内存映射文件句柄; LPVOID m_lpvFile:文件句柄; HPALETTE m_hPalette:调色板句柄; 对于 Cdib 类的构造函数、文件读写成员函数以及大多数 Get 成员函数等意义都是暗含的,程序中也都有详细的注解,在此不再详细讨论。 canny 算子是对图像进行边缘检测的一种算法 ,其主要通过以下几个函数来实现:函数 GaussianSmooth 对原图象进 行高斯滤波;函数 DirGrad 来计算 x、 y 方向上的导数;函数 GradMagnitude 计算梯度的幅度; 通过 函数 NonmaxSuppress 应用 nonmaximum 抑制 ; 应用Hysteresis, 找到找到所有的边界。 canny 函数 输入参数 说明如下 : unsigned char *pUnchImage 图象数据 int nWidth 图象数据宽度 int nHeight 图象数据高度 double sigma 高斯滤 波的标准方差 double dRatioLow 低阈值和高阈值之间的比例 double dRatioHigh 高阈值占图象象素总数的比例 unsigned char *pUnchEdge canny 算子计算后的分割图 canny 分割算子,计算的结果保存在 pUnchEdge 中,逻辑 1(255)表示该点为边界点,逻辑 0(0)表示该点为非边界点。 该函数的参数sigma, dRatioLow, dRatioHigh,是需要指定的。 这些参数会影响分割后边界点数目的多少 ,程序中这些 参数取值为 , ,。 经过 canny 算子计算后的结果如下图 31 所示。 ( a)原图 ( b) canny算子计算后的图像 图 31 二、割断图像中分叉的边缘点 经过 canny 算子的图像曲线,会有很多分叉的曲线,我们通过将曲线交叉点置为 0 来将其断开。 首先按从上到下的、从左到右的顺序扫描图像,寻找数值不为 0 的点,定义整形变量 count 来记录该点四邻域中不为 0 的点的个数 , count 初始化为 0。 若 count 值 大于 2,则表示 曲线在 该点处分叉, count 值 小于 1(即为 0) ,表示该点为孤立点 , count 值为 1 表示该点为 其 所在曲线的一个端点,count 值为 2 表示该点为曲线的一个中间点。 我们只要要将 count 值大于 2 的点置为 0,就可以将分叉的曲线断开,但是这样做会将分叉的曲线断成三条曲线 , 如图 32( b) 所示。 通 过分析发现,如果 将该点四邻域中不为 0 的一个点置为 0,最多只会将曲线断成两条曲线,如图 32( c)所示。 这样不仅减少了曲线条数,也是曲线尽可能不被断成短线,提高算法准确率。 该段程序流程如图 33 所示。 图 32 三、删除图像中长度大于某一阈值的直线 过滤掉边缘曲线中的长度大于某一阈值的直线, 对直线的判断采用爬行算法, 删除图像中长度大于某一阈值的直线,主要 通过Del_line 和 Del_l 两个函数来实现。 函数 Del_l()实现的功能是删除从点( x, y)开始的 dir_long个值为 255 的点,其输入参数说明如下: a b c d 0 b c d a b 0 d ( a) a 点四邻域有 b、c、 d 三个点 ,曲线在 a点处 分叉 ( b) 若 将 a 点置为 0后, b、 c、 d 点分别位于三条曲线 ( c) 若 将 a 点邻域中 c 点置为 0 后,曲线最多被分割成为两条: c 点引出的曲线和 a、 b、 d 点所在曲线 开 始点 ( x , y ) 为 图像 最 后 一 个 点。 点 ( x , y ) 值为 0。 判 断 其 四 邻 域 中 非 0 点 的 个 数 c o u n tc o u n t 2。 删 除 该 点 四 邻 域 中的 一 个 点结 束否是是( x , y ) 移 到 下 一 个 点( x , y ) 初 始 化 为 图 像中 第 一 个 点是否否 unsigned char *pUnchEdge 经过边缘检测后的图象数据; int nWidth 图象数据宽度; int x, int y 图象数据中的点( x, y); int dir_long 要删除的点的个数; 在函数中定义了变量 x y1 来对各点进行判断,其初始化为 x、y,通过变量 i 控制循环。 算法流程图如图 34 所示。 图 33 割断分叉点 图 33Del_l函数流程图 函数 Del_line()实现的功能是删除图像中长度小 于某一阈值 p的直线,其输入参数说明如下 : 开始( x 1 , y 1 ) 初始化为 ( x , y )i 初始化为 0删除点 ( x 1 , y 1 )i d ir _ lon g ?( x 1 , y 1 ) 移到曲线下一个点删除点 ( x 1 , y 1 )结束是否 unsigned char *pUnchEdge 经过边缘检测后的图象数据 int nWidth 图象数据宽度 int nHeight 图像数据高度 int x, int y 图象边缘曲线中的一个点 在函数中定义变量 x y1 来 依次 对各点进行 判断 ,其值初始化 图 34 Del_line函数流程图 开 始( x 1 , y 1 ) 初 始 化 为 ( x , y )判 断 ( x 1 , y 1 ) 下 一 个 点 的 方 向 d i rd i r 与 上 一 点 的方 向 相 同。 d i r _ l o n g + +( x 1 , y 1 ) 移 到 下 一 个 点d i r _ l o n g 阈 值p。 调 用 D e l _ l 函 数 删 除 从 ( x 1 , y 1 )开 始 的 d i r _ l o n g 个 点将 ( x 1 , y 1 ) 作 为 输 入 参数 递 归 调 用 D i r _ l o n g 对 删除 后 的 曲 线 进 行 判 断是是( x 1 , y 1 ) 为 曲线 最 后 一 个 点。 d i r _ l o n g 阈 值p。 调 用 D e l _ l 函 数 删 除 从 ( x 1 , y 1 )开 始 的 d i r _ l o n g 个 点是是结 束 为 x、 y;变量 p 为长度阈值;变量 dir 为方向向量 , 记录曲线中点的走向 ,初始化为 0;变量 dir_long 为直线长度 ,初始化为 0;通过 new 函数开辟一段大小为 nWidth*nHeight 的数据单元 unsigned char * pUnchEdge1,其 数据 初始化 为图像数据,通过其 来控制我完成 对 曲线的搜索计算。 该函数算法流程图如图 34 所示 ,函数在完成对变量的初始化后,从点( x, y)判断曲线的下一个点在其四邻域中的位置 方向 ,dir 记录了上一次判断的方向。 如果 dir 与本次判断一致,则变量dir_long 加一。 如果不一致, 且 dir_long 的值是小于阈值 p,只需更 改 dir 的值,继续判断下一个点;如果 dir_long 的值大于阈值 p,则 先改变 曲线 下一个点的值(将其赋值 254),调用 del_l 函数删除从( x1, y1)开始的曲线上的 dir_long 个值为 255 的点。 再 递归 调用 dir_long 函数从这下一个点开始判断,直至该条曲线所有点判断完毕后,算法结束。 四、 搜索并标记曲线算法 该算法主要是依次 搜索 图像中各 条曲线,在数组 pUnchImage 记录图像中各点所在曲线的序号,并删除图像中过短的曲线。 算法通过函数 Del_cur 和函数 Serch_cur 来实现 ,算法流程图如下图 35所示。 函数 Del_cur 用于删除图像中以点( x, y)为起始点的曲线。 曲线中所有的点在 pUnchImage 中标记了对应曲线序号,图像数据pUnchEdge 中 标记 了曲线端点, 曲线中 其余点均为 0,曲线端点在pUnchEdge 中以值不为 0。 删除曲线后,图像数据 pUnchEdge、 曲线编号数据 pUnchImage 中各点对应值均置为 0。 函数的输入参数说明如下: unsigned char *pUnchEdge – 对图像中曲线进行搜索处理过的图象数据 unsigned char *pUnchImage 记录图像中各点所在曲线编号的数据 int nWidth 图象数据宽度 int x, int y 图象中 所要 要删除曲线的一个端。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。