图像细化算法大全
- 格式:doc
- 大小:85.50 KB
- 文档页数:18
Zhang-Suen图像细化算法python实现算法流程⾸先要反转原图像,因为算法之后所有的操作都将0作为前景,将1作为背景。
中⼼像素x_1(x,y)的8-近邻定义如下所⽰:考虑以下两个步骤步骤1:执⾏光栅扫描并标记满⾜以下5个条件的所有像素:这是⼀个⿊⾊像素;顺时针查看x2、x3、...、x9、x2时,从0到1的变化次数仅为1;x2、x3、...、x9中1的个数在2个以上6个以下;x2、x4、x6中⾄少有1个为1;x4、x6、x8中⾄少有1个为1;将满⾜条件的所有像素标为1步骤2:执⾏光栅扫描并标记满⾜以下5个条件的所有像素:这是⼀个⿊⾊像素;顺时针查看x2、x3、...、x9、x2时,从0到1的变化次数仅为1;x2、x3、...、x9中1的个数在2个以上6个以下;x2、x4、x8中⾄少有1个为1;x2、x6、x8中⾄少有1个为1;将满⾜条件的所有像素标为1反复执⾏步骤1和步骤2,直到没有点发⽣变化。
python实现:import cv2import numpy as npimport matplotlib.pyplot as plt# Zhang Suen thining algorythmdef Zhang_Suen_thining(img):# get shapeH, W, C = img.shape# prepare out imageout = np.zeros((H, W), dtype=np.int)out[img[..., 0] > 0] = 1# inverseout = 1 - outwhile True:s1 = []s2 = []# step 1 ( rasta scan )for y in range(1, H-1):for x in range(1, W-1):# condition 1if out[y, x] > 0:continue# condition 2f1 = 0if (out[y-1, x+1] - out[y-1, x]) == 1:f1 += 1if (out[y, x+1] - out[y-1, x+1]) == 1:f1 += 1if (out[y+1, x+1] - out[y, x+1]) == 1:f1 += 1if (out[y+1, x] - out[y+1,x+1]) == 1:f1 += 1if (out[y+1, x-1] - out[y+1, x]) == 1:f1 += 1if (out[y, x-1] - out[y+1, x-1]) == 1:f1 += 1if (out[y-1, x-1] - out[y, x-1]) == 1:f1 += 1if (out[y-1, x] - out[y-1, x-1]) == 1:f1 += 1if f1 != 1:continue# condition 3f2 = np.sum(out[y-1:y+2, x-1:x+2])if f2 < 2 or f2 > 6:continue# condition 4# x2 x4 x6if (out[y-1, x] + out[y, x+1] + out[y+1, x]) < 1 : continue# condition 5# x4 x6 x8if (out[y, x+1] + out[y+1, x] + out[y, x-1]) < 1 : continues1.append([y, x])for v in s1:out[v[0], v[1]] = 1# step 2 ( rasta scan )for y in range(1, H-1):for x in range(1, W-1):# condition 1if out[y, x] > 0:continue# condition 2f1 = 0if (out[y-1, x+1] - out[y-1, x]) == 1:f1 += 1if (out[y, x+1] - out[y-1, x+1]) == 1:f1 += 1if (out[y+1, x+1] - out[y, x+1]) == 1:f1 += 1if (out[y+1, x] - out[y+1,x+1]) == 1:f1 += 1if (out[y+1, x-1] - out[y+1, x]) == 1:f1 += 1if (out[y, x-1] - out[y+1, x-1]) == 1:f1 += 1if (out[y-1, x-1] - out[y, x-1]) == 1:f1 += 1if (out[y-1, x] - out[y-1, x-1]) == 1:f1 += 1if f1 != 1:continue# condition 3f2 = np.sum(out[y-1:y+2, x-1:x+2])if f2 < 2 or f2 > 6:continue# condition 4# x2 x4 x8if (out[y-1, x] + out[y, x+1] + out[y, x-1]) < 1 : continue# condition 5# x2 x6 x8if (out[y-1, x] + out[y+1, x] + out[y, x-1]) < 1 : continues2.append([y, x])for v in s2:out[v[0], v[1]] = 1# if not any pixel is changedif len(s1) < 1 and len(s2) < 1:breakout = 1 - outout = out.astype(np.uint8) * 255return out# Read imageimg = cv2.imread("../thin.png").astype(np.float32) # Zhang Suen thiningout = Zhang_Suen_thining(img)# Save resultcv2.imwrite("out.png", out)cv2.imshow("result", out)cv2.waitKey(0)cv2.destroyAllWindows()实验结果:。
介绍常见的图像处理算法及其应用图像处理算法是计算机视觉领域的重要内容,它涵盖了许多不同的技术和方法。
本文将介绍一些常见的图像处理算法及其应用。
这些算法可以用于图像增强、图像分割、目标识别等领域,它们可以帮助我们更好地理解和处理图像数据。
一、图像滤波算法图像滤波是图像处理的基础算法之一,它通过对图像进行平滑处理来去除图像中的噪声或者增强图像的细节。
图像滤波算法有很多种,其中常见的有均值滤波、中值滤波和高斯滤波。
均值滤波是一种简单的滤波算法,它通过计算像素点周围领域像素的平均值来达到平滑图像的效果。
均值滤波对噪声有一定的去除效果,但是对于边缘和细节信息的保存能力较差。
中值滤波是一种非线性滤波算法,它通过对图像中的像素值进行排序,然后选择排序后的中间值作为当前像素的新值。
中值滤波对椒盐噪声有较好的去除效果,并且能够保持图像的边缘信息。
高斯滤波是一种基于高斯函数的线性滤波算法,它通过对图像中的像素进行加权平均来实现平滑效果。
高斯滤波对于去除高斯噪声以及其他类型的噪声都有较好的去除效果。
二、图像分割算法图像分割是将图像划分成具有语义信息的相互独立的区域的过程。
图像分割算法通常根据图像中的灰度值、颜色、纹理等特征将图像进行分割。
常见的图像分割算法有阈值分割、基于区域的分割和基于边缘的分割。
阈值分割是一种简单常用的分割算法,它将图像中的像素根据灰度值与阈值的关系进行分类。
通过调整阈值的大小,可以实现不同程度的图像分割。
基于区域的分割算法是根据像素之间的相似性将图像进行分割,使具有相似性质的像素聚合成为一个区域。
常见的基于区域的分割算法有K-means算法和基于区域的生长算法。
基于边缘的分割算法是根据图像中的边缘信息将图像进行分割。
边缘是图像中颜色、灰度值等发生突变的地方,基于边缘的分割算法通过检测图像中的边缘来实现分割。
三、图像特征提取算法图像特征提取是将图像中的信息转化为计算机可以理解和处理的形式的过程。
图像特征可以是图像的边缘、纹理、颜色等视觉特征,也可以是经过某种数学变换得到的特征。
Hilditch 细化算法是经典的二值图像细化算法,然而,在网上却很难找到一个详细、正确的介绍和实现。
可以找到一辆个 Hilditch 算法的C实现,但缺乏注释,代码可读性也很差。
在期刊网上找到几篇论文,提及了Hilditch 算法,结果一篇说的罗哩罗嗦根本看不懂,另一篇说的说的易懂,却是错误的!拿来主义是行不通了,于是只好结合着这几个论文和代码,从头写 Hilditch 细化算法。
假设像素p的3×3邻域结构为:Hilditch 细化算法的步骤为:对图像从左向右从上向下迭代每个像素,是为一个迭代周期。
在每个迭代周期中,对于每一个像素p,如果它同时满足6个条件,则标记它。
在当前迭代周期结束时,则把所有标记的像素的值设为背景值。
如果某次迭代周期中不存在标记点(即满足6个条件的像素),则算法结束。
假设背景值为0,前景值为1,则:6个条件为:(I):p 为1,即p不是背景;(2):x1,x3,x5,x7不全部为1(否则把p标记删除,图像空心了);(3):x1-x8 中,至少有2个为1(若只有1个为1,则是线段的端点。
若没有为1的,则为孤立点);(4):p的8连通联结数为1;联结数指在像素p的3*3邻域中,和p连接的图形分量的个数:上图中,左图的4连通联结数是2,8连通联结数是1,而右图的4联通联结数和8联通联结数都是2。
4连通联结数计算公式是:8连通联结数计算公式是:其中,至于公式怎么来的就不管了,直接用就行了。
(5)假设x3已经标记删除,那么当x3为0时,p的8联通联结数为1;(6)假设x5已经标记删除,那么当x5为0时,p的8联通联结数为1。
======在程序中,我使用的是这样的邻域编码:为了方便计算联结数,以0作为前景,1作为背景。
程序如下(完整程序见:/svn/trunk/src/mon/UnmanagedI mage/ImageU8.cs):/// <summary>/// 计算八联结的联结数,计算公式为:/// (p6 - p6*p7*p0) + sigma(pk - pk*p(k+1)*p(k+2)), k = {0,2,4)/// </summary>/// <param name="list"></param>/// <returns></returns>private unsafe Int32 DetectConnectivity(Int32* list){Int32 count = list[6] - list[6] * list[7] * list[0];count += list[0] - list[0] * list[1] * list[2];count += list[2] - list[2] * list[3] * list[4];count += list[4] - list[4] * list[5] * list[6];return count;}private unsafe void FillNeighbors(Byte* p, Int32* list, Int32 width, Byte foreground = 255){// list 存储的是补集,即前景点为0,背景点为1,以方便联结数的计算list[0] = p[1] == foreground ? 0 : 1;list[1] = p[1 - width] == foreground ? 0 : 1;list[2] = p[-width] == foreground ? 0 : 1;list[3] = p[-1 - width] == foreground ? 0 : 1;list[4] = p[-1] == foreground ? 0 : 1;list[5] = p[-1 + width] == foreground ? 0 : 1;list[6] = p[width] == foreground ? 0 : 1;list[7] = p[1 + width] == foreground ? 0 : 1;}/// <summary>/// 使用 hilditch 算法进行细化/// </summary>public unsafe void Thinning(Byte foreground = 255){Byte* start = this.Start;Int32 width = this.Width;Int32 height = this.Height;Int32* list = stackalloc Int32[8];Byte background = (Byte)(255 - foreground);Int32 length = this.Length;using (ImageU8 mask = new ImageU8(this.Width, this.Height)) {mask.Fill(0);Boolean loop = true;while (loop == true){loop = false;for (Int32 r = 1; r < height - 1; r++){for (Int32 c = 1; c < width - 1; c++){Byte* p = start + r * width + c;// 条件1:p 必须是前景点if (*p != foreground) continue;// p3 p2 p1// p4 p p0// p5 p6 p7// list 存储的是补集,即前景点为0,背景点为1,以方便联结数的计算FillNeighbors(p, list, width, foreground);// 条件2:p0,p2,p4,p6 不皆为前景点if (list[0] == 0 && list[2] == 0 && list[4] == 0 && list[6] == 0)continue;// 条件3: p0~p7至少两个是前景点Int32 count = 0;for (int i = 0; i < 8; i++){count += list[i];}if (count > 6) continue;// 条件4:联结数等于1if (DetectConnectivity(list) != 1) continue;// 条件5: 假设p2已标记删除,则令p2为背景,不改变p的联结数 if (mask[r - 1, c] == 1){list[2] = 1;if (DetectConnectivity(list) != 1)continue;list[2] = 0;}// 条件6: 假设p4已标记删除,则令p4为背景,不改变p的联结数 if (mask[r, c - 1] == 1){list[4] = 1;if (DetectConnectivity(list) != 1)continue;}mask[r, c] = 1; // 标记删除loop = true;}}for (int i = 0; i < length; i++){if (mask[i] == 1){this[i] = background;}}}}}。
并行图像细化算法和C代码实现图像细化一般作为一种图像预处理技术出现,目的是提取源图像的骨架,即是将原图像中线条宽度大于1个象素的线条细化成只有一个象素宽,形成'骨架',形成骨架后能比较容易的分析图像,如提取图像的特征.细化分成串行细化和并行细化2中,串行细化即是一遍检测满足细化条件的点一边删除细化点,并行细化即是检测细化点的时候不进行点的删除只进行标记,而在检测完整幅图像后一次性去除要细化的点.细化基本思想是'层层剥夺',即从线条边缘开始一层一层向里剥夺,直到线条剩下一个象素的为止.进行细化算法前要先对图像进行2值化,即图像中直包含'黑'和'白'2中颜色.细化算法:在微观上取检测点的8个临域(因为是并行细化,有些模板要扩展为12临域),如下xxxxoxxxx其中o为检测点x为其相邻点以下用1代表黑色点,用0代表白色点,用x代表任意颜色的点,要剥夺(删除)的点应满足一下8个模板中的一个.模板a(向右扩大)0x1x01110x1x模板b(向右扩大) 00xx0111x11x模板c(向右扩大) x11x011100xx模板d111x1x000模板e1x01101x0模板fx00110x1x模板gx1xx00模板h(向下扩大)000x1x111x1x符合以上8个模板的点为要剥夺的点,因为符合这8个模板的点可以确认为线条边沿上的点.而试事实上经过这8个模板并行细化后还有下面2种特殊的边沿点保留了下来, 特殊边沿点1000010111特殊边沿点2001011001造成这种2种特殊点的原因扩大后的模板a和扩大后的模板h,扩大的的本意是防止偶数列(行)的线条被完全消去(并行细化并然的).解决方法是在并行细化后再进行一次串行细化,选取缩小后的模板a和模板h 模板a(缩小后)0110x1模板h(缩小后)000x1x111其中缩小后的模板a解决了特殊情况1,缩小后的模板h解决了特殊情况2,注意这次是串行细化了.一下根据这个原理用C++Builder6.0实现,关键代码如下. //--------------------------------BCB6 代码#include <vcl.h>#pragma hdrstop#include<stdio.h>#include "Unit1.h"#include"File1.h"#include<math.h>#include<time.h>#include<vector>#pragma pack(1)using namespace std;/*程序:图像细化sboom(Lingch)日期:05年1月18日*///BMP文件头struct BITMAPFILEHEADER_{short type;int bfSize;short re1,re2;int Offbits;};//BMP信息头struct BITMAPINFO_{long size;long width,height;short planes,bitCount;long p,sizeImg;long xpels,ypels;long used,important;};//------将BMP彩色表的数据校正到BCB 的TColor的数据。
图像细化(⾻架化)算法分析图像细化(⾻架化)算法分析图像的细化是模式识别中很重要的⼀个技术,指的是将原本"臃肿"的像素简化为单像素相连接的⼆值图像(即类似⾻架的概念),细化的好坏直接影响到后⾯识别匹配的效率。
摘⾃某⽂章的话,细化就是经过⼀层层的剥离,从原来的图中去掉⼀些点,但仍要保持原来的形状,直到得到图像的⾻架。
⾻架,可以理解为图象的中轴,例如⼀个长⽅形的⾻架是它的长⽅向上的中轴线;正⽅形的⾻架是它的中⼼点;圆的⾻架是它的圆⼼,直线的⾻架是它⾃⾝,孤⽴点的⾻架也是⾃⾝。
下⾯先介绍经典的Zhang并⾏快速细化算法:设p1点的⼋邻域为:【 p9 p2 p3p8 p1 p4p7 p6 p5 】(其中p1为⽩点,如果以下四个条件同时满⾜,则删除p1,即令p1=0)其中迭代分为两个⼦过程:过程1 细化删除条件为:(1)、2 < =N(p1) <= 6, N(x)为x的8邻域中⿊点的数⽬(2)、A(p1)=1, A(x)指的是将p2-p8之间按序前后分别为0、1的对数(背景⾊:0)(3)、p2*p4*p6=0(4)、p4*p6*p8=0如果同时满⾜以上四个条件则该点可以删除(赋值为0)。
过程2 细化删除条件为:(1)、2 < =N(p1) <= 6, N(x)为x的8邻域中⿊点的数⽬(2)、A(p1)=1, A(x)指的是将p2-p8之间按序前后分别为0、1的对数(背景⾊:0)(3)、p2*p4*p8=0(4)、p2*p6*p8=0如果同时满⾜以上四个条件则该点可以删除。
代码如下:A.m1 function n=A(temp,i,j)2 %0->1的数⽬3 shuzu=[temp(i,j),temp(i-1,j),temp(i-1,j+1),temp(i,j+1),temp(i+1,j+1),temp(i+1,j),temp(i+1,j-1),temp(i,j-1),temp(i-1,j-1)];4 n=0;5for i=2:86if shuzu(i)==0&&shuzu(i+1)==17 n=n+1;8 end9 end主函数代码:1 test=input('Please input a digits image:','s'); %输⼊图像2 x=imread(test);3if ~isbw(x)4'请确保输⼊图像为⼆值化图像!';5else6 [height,width]=size(x);7 mark=1;8 % temp=zeros(height+2,width+2);9 % temp(2:height+1,2:width+1)=x(:,:);10 temp=x;11 imshow(temp);12while mark==113 mark=0;1415for i=2:height-116for j=2:width-117 condition=0;18 %判断P(r,c)是否为可细化像素19if temp(i,j)==120 n=0;21for ii=-1:122for jj=-1:123 n=n+temp(i+ii,j+jj);24 end25 end26if (n>=3 && n<=7)27 condition=condition+1;28 end29if A(temp,i,j)==130 condition=condition+1;31 end32if temp(i-1,j)*temp(i,j+1)*temp(i+1,j)==033 condition=condition+1;34 end35if temp(i,j+1)*temp(i+1,j)*temp(i,j-1)==036 condition=condition+1;37 end38if condition==439 mark=1;40 temp(i,j)=0;41 end42 end43 end44 end45 figure;imshow(temp);464748for i=2:height-149for j=2:width-150 condition=0;51 %判断P(r,c)是否为可细化像素52if temp(i,j)==153 n=0;54for ii=-1:155for jj=-1:156 n=n+temp(i+ii,j+jj);57 end58 end59if (n>=3 && n<=7)60 condition=condition+1;61 end62if A(temp,i,j)==163 condition=condition+1;64 end65if temp(i-1,j)*temp(i,j+1)*temp(i,j-1)==066 condition=condition+1;67 end68if temp(i,j-1)*temp(i+1,j)*temp(i,j-1)==069 condition=condition+1;70 end71if condition==472 mark=1;73 temp(i,j)=0;74 end75 end76 end77 end78 figure;imshow(temp);79 end80 end结果:。
Hilditch细化算法是一种用于二值图像细化(或骨架化)的算法。
以下是一个简单的Python实现:
def hilditch(image):
# 获取图像的宽度和高度
width, height = image.shape
# 创建一个与原图大小相同的掩模,所有值初始化为1
mask = image.copy()
# 遍历原图像
for y in range(height):
for x in range(width):
# 如果当前像素是1,则进行细化操作
if image[x][y] == 1:
# 判断上下左右四个方向是否为0
if (x > 0 and image[x-1][y] == 0) or (x < width-1 and image[x+1][y] == 0):
mask[x][y] = 0
if (y > 0 and image[x][y-1] == 0) or (y < height-1 and image[x][y+1] == 0):
mask[x][y] = 0
# 返回细化后的图像
return mask
这个函数接受一个二值图像作为输入,并返回一个细化后的图像。
在函数中,我们首先创建一个与原图大小相同的掩模,并将所有值初始化为1。
然后,我们遍历原图像中的每个像素,如果当前像素是1,则检查其上下左右四个方向是否为0。
如果是,则将当前像素的值设置为0,表示该像素应该被细化掉。
最后,我们返回细化后的图像。
图像处理中的数学算法图像处理是一个复杂的过程,它需要运用数学算法来处理图像中的各种信息。
这些算法可以实现图像的去噪、平滑、增强、分割、匹配等功能。
本文将介绍一些常用的图像处理算法,包括小波变换、奇异值分解、最小二乘法、K-means算法、纹理分析等。
一、小波变换小波变换是一种将时域信号转换为频域信号的数学算法。
它可以将图像分解为不同频率范围的小波系数,从而实现对图像的去噪、平滑、特征提取等操作。
小波变换在图像处理中应用广泛,特别是在去噪方面有着独特的优势。
小波变换可以将图像矩阵分解成多组小波系数,其中较高频率的小波系数表示图像中的细节信息,较低频率的小波系数表示图像中的模糊信息。
通过对小波系数的分析和处理,可以实现对图像的特定操作。
二、奇异值分解奇异值分解(SVD)是一种将矩阵分解为三个部分的数学算法,其中一个矩阵是一个对角矩阵,它的对角线上的元素称为奇异值。
奇异值对应了原始矩阵中的主要信息,可以用来构建一个低维矩阵,从而实现图像的压缩和降噪。
奇异值分解可以实现对图像中重要信息的提取和过滤,从而实现图像的压缩和去噪。
三、最小二乘法最小二乘法是一种寻找最优曲线拟合的数学方法,它的目标是通过一个最优拟合函数来表达数据的真实规律。
在图像处理中,最小二乘法可以用来寻找图像中的相关特征,从而实现对图像的分割和特征提取。
最小二乘法可以通过对图像中的像素点进行拟合来得到相应的参数,从而实现对图像中相关特征的描述和分析。
最小二乘法在图像处理中常常用于线性回归和图像灰度直方图均衡化等操作。
四、K-means算法K-means算法是一种将数据划分为多个簇的聚类算法,它可以帮助识别图像中的不同区域,并实现对图像区域的分割和聚类。
K-means算法通常可以用来处理灰度图像、二元图像和多光谱图像等。
K-means算法通过寻找多个空间点之间的相似性,来得到一个划分簇的结果。
在图像处理中,K-means算法可以用来将图像像素划分为多个簇,从而实现对图像的分割和聚类。
opencv实现⼆值图像细化的算法opencv实现⼆值图像细化的算法细化算法通常和⾻骼化、⾻架化算法是相同的意思,也就是thin算法或者skeleton算法。
虽然很多图像处理的教材上不是这么写的,具体原因可以看这篇论⽂,Louisa Lam, Seong-Whan Lee, Ching Y. Suen,“Thinning Methodologies-A Comprehensive Survey ”,IEEE TRANSACTIONS ON PATTERN ANALYSIS AND MACHINE INTELLIGENCE, VOL. 14, NO. 9, SEPTEMBER 1992 ,总结了⼏乎所有92年以前的经典细化算法。
函数:void cvThin( IplImage* src, IplImage* dst, int iterations=1)功能:将IPL_DEPTH_8U型⼆值图像进⾏细化参数:src,原始IPL_DEPTH_8U型⼆值图像dst,⽬标存储空间,必须事先分配好,且和原图像⼤⼩类型⼀致iterations,迭代次数参考⽂献:T. Y. Zhang and C. Y. Suen, “A fast parallel algorithm for thinning digital patterns,” Comm. ACM, vol. 27, no. 3, pp. 236-239, 1984.void cvThin( IplImage* src, IplImage* dst, int iterations=1){CvSize size = cvGetSize(src);cvCopy(src, dst);int n = 0,i = 0,j = 0;for(n=0; n<iterations; n++){IplImage* t_image = cvCloneImage(dst);for(i=0; i<size.height; i++){for(j=0; j<size.width; j++){if(CV_IMAGE_ELEM(t_image,byte,i,j)==1){int ap=0;int p2 = (i==0)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j);int p3 = (i==0 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j+1);if (p2==0 && p3==1){ap++;}int p4 = (j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i,j+1);if(p3==0 && p4==1){ap++;}int p5 = (i==size.height-1 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j+1);if(p4==0 && p5==1){ap++;}int p6 = (i==size.height-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j);if(p5==0 && p6==1){ap++;}int p7 = (i==size.height-1 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j-1);if(p6==0 && p7==1){ap++;}int p8 = (j==0)?0:CV_IMAGE_ELEM(t_image,byte,i,j-1);if(p7==0 && p8==1){ap++;}int p9 = (i==0 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i-1,j-1);if(p8==0 && p9==1){ap++;}if(p9==0 && p2==1){ap++;}if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7){if(ap==1){if(!(p2 && p4 && p6)){if(!(p4 && p6 && p8)){CV_IMAGE_ELEM(dst,byte,i,j)=0;}}}}}}}cvReleaseImage(&t_image);t_image = cvCloneImage(dst);for(i=0; i<size.height; i++){for(int j=0; j<size.width; j++){if(CV_IMAGE_ELEM(t_image,byte,i,j)==1){int ap=0;int p2 = (i==0)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j);int p3 = (i==0 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j+1);if (p2==0 && p3==1){ap++;}int p4 = (j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i,j+1);if(p3==0 && p4==1){ap++;}int p5 = (i==size.height-1 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j+1);if(p4==0 && p5==1){ap++;}int p6 = (i==size.height-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j);if(p5==0 && p6==1){ap++;}int p7 = (i==size.height-1 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j-1); if(p6==0 && p7==1){ap++;}int p8 = (j==0)?0:CV_IMAGE_ELEM(t_image,byte,i,j-1);if(p7==0 && p8==1){ap++;}int p9 = (i==0 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i-1,j-1);if(p8==0 && p9==1){ap++;}if(p9==0 && p2==1){ap++;}if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7) {if(ap==1){if(p2*p4*p8==0){if(p2*p6*p8==0){CV_IMAGE_ELEM(dst, byte,i,j)=0;}}}}}}}cvReleaseImage(&t_image);}}//使⽤举例#include "cxcore.h"#include "cv.h"#include "highgui.h"int main(int argc, char* argv[]){if(argc!=2){return 0;}IplImage *pSrc = NULL,*pDst = NULL,*pTmp = NULL;//传⼊⼀个灰度图像pSrc = cvLoadImage(argv[1],CV_LOAD_IMAGE_GRAYSCALE);if(!pSrc){return 0;}pTmp = cvCloneImage(pSrc);pDst = cvCreateImage(cvGetSize(pSrc),pSrc->depth,pSrc->nChannels);cvZero(pDst);cvThreshold(pSrc,pTmp,128,1,CV_THRESH_BINARY_INV);//做⼆值处理,将图像转换成0,1格式 //cvSaveImage("c://Threshold.bmp",pTmp,0);cvThin(pTmp,pDst,8);//细化,通过修改iterations参数进⼀步细化cvNamedWindow("src",1);cvNamedWindow("dst",1);cvShowImage("src",pSrc);//将⼆值图像转换成灰度,以便显⽰int i = 0,j = 0;CvSize size = cvGetSize(pDst);for(i=0; i<size.height; i++){for(j=0; j<size.width; j++){if(CV_IMAGE_ELEM(pDst,uchar,i,j)==1){CV_IMAGE_ELEM(pDst,uchar,i,j) = 0;}else{CV_IMAGE_ELEM(pDst,uchar,i,j) = 255;}}}//cvSaveImage("c://thin.bmp",pDst);cvShowImage("dst",pDst);cvWaitKey(0);cvReleaseImage(&pSrc);cvReleaseImage(&pDst);cvReleaseImage(&pTmp);cvDestroyWindow("src");cvDestroyWindow("dst");return 0;}。
一些基本的形态学算法细化1.引言1.1 概述概述形态学算法是图像处理领域中的一种重要技术,主要用于图像的分析和处理。
形态学算法基于数学形态学理论,通过对图像中的形状和结构进行操作和变换,从而实现图像的特征提取、图像增强、边缘检测等目的。
形态学算法最早是由Matheron于1964年提出的,其理论基础是数学形态学,借鉴了数学中对集合的运算和变换的概念和方法。
形态学算法主要基于结构元素(也称为模板或内核)与图像进行操作,通过结构元素在图像上的移动和比较,实现图像的形态学变化。
形态学算法的基础操作包括膨胀、腐蚀、开运算和闭运算。
膨胀操作将结构元素扩张到图像中的对象区域,从而使对象的尺寸增大;腐蚀操作将结构元素侵蚀图像中的对象区域,使对象的尺寸减小。
开运算是先进行腐蚀,再进行膨胀,通常用于去除图像中的小噪点;闭运算与开运算相反,先进行膨胀,再进行腐蚀,通常用于填补图像中的小孔洞。
除了基本形态学算法外,细化算法也是形态学算法的重要内容之一。
细化算法主要用于提取图像中的骨架或轮廓线。
骨架提取算法通过连续的腐蚀操作,逐步减小图像中的对象尺寸,最终得到对象的骨架;线条细化算法则通过针对对象边界的特征点进行腐蚀和连接操作,实现对边界线条的细化。
本文将详细介绍基本形态学算法和细化算法的原理和应用,并通过实例演示其在图像处理中的作用。
同时,强调细化算法在形态学算法中的重要性和应用前景,以期对读者深入理解和应用形态学算法具有指导意义。
1.2文章结构文章结构部分的内容是对整篇文章的组织和安排进行介绍。
在本篇文章中,主要包含了引言、正文和结论三个部分。
首先是引言部分,引言部分主要包括概述、文章结构和目的三个小节。
在概述中,介绍了本篇文章要讨论的主题,即一些基本的形态学算法的细化。
在文章结构中,说明了整篇文章的目录和结构安排。
在目的小节中,阐明了撰写这篇文章的目的和意义。
接下来是正文部分,正文部分分为基本形态学算法和细化算法两个小节。
骨架曲线提取
骨架曲线提取是图像处理中的一种技术,用于从图像中提取目标物体的主要结构或边缘信息。
骨架曲线通常代表目标物体的中轴线或主要骨干,对于形状分析、图像识别和计算机视觉等领域具有重要意义。
以下是一般的骨架曲线提取方法:
1.细化算法(Thinning Algorithm):细化算法是最常见的骨架曲线提取方法之一。
该算法通过迭代,逐渐去除目标物体的边缘像素,直到获得骨架曲线。
经典的细化算法包括Zhang-Suen细化算法和Guo-Hall细化算法。
2.距离变换(Distance Transform):这种方法首先计算图像中每个像素到最近目标物体边缘的距离,然后根据距离信息提取骨架曲线。
距离变换方法不仅用于骨架曲线提取,还广泛应用于形状分析和模式识别。
3.中轴变换(Medial Axis Transform):中轴变换寻找目标物体内部的局部极大值区域,形成中轴线,该线代表了目标的主要结构。
中轴变换方法适用于具有复杂形状的物体。
4.基于梯度的方法:利用图像梯度信息来提取目标的边缘或中轴线。
梯度信息可以通过使用Sobel、Prewitt等滤波器来获取。
5.基于模板匹配的方法:使用特定的模板匹配目标物体的结构,通过匹配过程提取目标物体的骨架信息。
在选择骨架曲线提取方法时,需要考虑目标物体的形状、图像噪声水平、计算效率等因素。
不同的方法适用于不同的场景,因此在实际应用中可能需要尝试多种方法并根据具体情况选择最适合的方法。
Matlab的图像细化算法(详细实现)(2012-08-22 17:02:57)以下示范调用MATLAB的细化函数I = imread('BW.bmp');I2 = bwmorph(I, 'thin',Inf);figure,imshow(I)figure,imshow(I2)可以看出,MATLAB的细化效果是很好的,相比之下,网上找的一些代码的效果就差很多了。
MATLAB很强大!我通过设置断点,进入MATLAB底层,看看BWMORPH这个函数是怎么样的,把程序实际运行了的代码抠出来,得到以下结果:%function[cout,lut]=bwmorph(a,op,n);fcn=deblank(functionString(idx,:));%%调试可看到匹配结果fun='thin'c = a;iter = 1;done = n == 0;while (~done)%%%循环去掉多与像素直至没有可去掉的像素lastc = c;[c,lut]=feval_r(fcn,c);%%%进入内部会跳到下面的thin函数,fcn='thin',done = ((iter>= n) | isequal(lastc, c));iter = iter + 1;endfunction[c,lut]=thin(a)%%%每执行一次thin函数,图像就分别利用lut1和lut2两个模板去掉外层像素点,lut=[];if(isempty(a))c=zeros(size(a));return;endlut1=lutthin1;image_iter1=applylut(a,lut1);lut1=lutthin2;c=applylut(image_iter1,lut2);endfunctionlut = lutthin1lut = [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;0;1;1;0;0;1;1;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;0;0;1;1;0;0;1;1;0;0;1;1;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;0;0;0;1;1;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;0;0;1;1;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;0;0;0;1;0;0;1;1;0;0;1;1;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;1;0;0;0;1;0;0;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;];functionlut = lutthin2lut = [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;0;0;1;0;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;0;1;1;1;0;0;1;1;0;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;0;0;1;0;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;0;1;1;1;0;0;1;1;0;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;0;0;1;0;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;0;1;1;1;0;0;1;1;0;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;0;0;1;0;1;1;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;0;1;1;1;0;0;1;1;0;1;1;1;];现在关键就是applylutc这个函数没有抠出来了!在目录matlab/toolbox/images/images/private下可以找到源代码。
1、前言图像细化(Image Thinning),一般指二值图像的骨架化(Image Skeletonization)的一种操作运算。
一个图像的骨架由一些线和曲线(比较理想的是单像素宽度),骨架可以提供一个图像目标的尺寸和形状信息,因而在数字图像分析中具有重要的地位,图像细化(骨架化)是进行图像识别、线条类图像目标分析的重要手段。
本文将探讨骨架的一些性质,给出如何判断一个像素是否属于图像目标的骨架,最后将给出获得图像目标骨架的基本算法。
下图是骨架的基本实例骨架化过程中必须注意的问题在于,一个目标周边细节的微小变化会对细化后的骨架结果产生较大的变化。
如下图所示,仅仅是在图像目标上端分别出现不同的凹凸点,就产生了差异巨大的细化的骨架。
2、骨架的定义:比较普遍的方法是采用目标(Object)中轴(Medial Axis)的概念。
中轴线的点(像素点)定义为距离目标边界上两个点等距的那些像素.那么在图像处理中如何实现这种等距的计算?一般有两个途径。
一是使用距离变换(Distance Transform)的方法(在此不讨论)。
另外一个方法介绍如下:思路:想象一个图像目标四周被火点燃,燃烧的速度四周保持一致,那么四周由边界向质心方向(向内部中心)燃烧时,相互遇到的那条线,就是中轴线。
以长方形为例,可以想象,分别会有许多内接圆,分别沿着长方形(矩形)的四个角向中心方形移动。
拓扑方法是实现图像骨架化的有利工具,我们可以定义一些图像目标边界上可以删除的像素点,以便最后获得图像目标的骨架。
但是,我们还要求保持图像目标(一般常用于线条类的图像目标)的连通性(Connectivity),还不能改变图像目标的个数,不能改变目标内的空洞个数,也不能改变不同目标的相互关系(位置关系等等),一旦有些像素涉及到改变上述内容的,则一律不能被当作删除的图像像素。
基本方法和原理我们可以利用一个3x3模板来检测一个像素是否应该被删除掉。
下面以下图(a)为例假定3乘3大小的图像中,中心点(黑点)被删除,那么会有如下两种情形:(1)顶端两个像素和右下端两个像素被分离了,这样就会将原来的一个目标(物体)分为两个,不符合细化操作的要求。
图像细化算法一、细化算法简介图像细化(Image Thinning),一般指二值图像的骨架化(Image keletonization)的一种操作运算。
所谓的细化就是经过一层层的剥离,从原来的图中去掉一些点,但仍要保持原来的形状,直到得到图像的骨架。
骨架,可以理解为图象的中轴。
好的细化算法一定要满足:∙收敛性;∙保证细化后细线的连通性∙保持原图的基本形状∙减少笔画相交处的畸变∙细化结果是原图像的中心线∙细化的快速性和迭代次数少依据是否使用迭代运算可以分为两类:(1)非迭代算法一次即产生骨架,如基于距离变换的方法。
游程长度编码细化等。
(2)迭代算法即重复删除图像边缘满足一定条件的像素,最终得到单像素宽带骨架。
迭代方法依据其检查像素的方法又可以再分成①串行算法是否删除像素在每次迭代的执行中是固定顺序的,它不仅取决于前次迭代的结果,也取决于本次迭代中已处理过像素点分布情况.②并行算法像素点删除与否与像素值图像中的顺序无关,仅取决于前次迭代的结果二、本文所用算法我所采用的是Zhang并行快速细化算法,它的原理也很简单:我们对一副二值图像进行骨架提取,就是删除不需要的轮廓点,只保留其骨架点。
假设一个像素点,我们定义该点为p1,则它的八邻域点p2->p9位置如下图所示,该算法考虑p1点邻域的实际情况,以便决定是否删除p1点。
假设我们处理的为二值图像,背景为黑色,值为0,要细化的前景物体像素值为1。
算法的描述如下。
首先复制源图像到目地图像,然后建立一个临时图像,接着执行下面操作:1. 把目地图像复制给临时图像,对临时图像进行一次扫描,对于不为0的点,如果满足以下四个条件,则在目地图像中删除该点(就是设置该像素为0),这里p2,…,p9是对应位置的像素灰度值(其为1或者0)。
a. 2<= p2+p3+p4+p5+p6+p7+p8+p9<=6大于等于2会保证p1点不是端点或孤立点,因为删除端点和孤立点是不合理的,小于等于6保证p1点是一个边界点,而不是一个内部点。
技术专栏专注成就专业,兴趣成就事业C#图像细化:Hilditch细化算法分类: C#开发 2012-04-09 10:55 681人阅读 评论(0) 收藏举报算法c#input图形网络2010上理论:Hilditch 细化算法的步骤为:对图像从左向右从上向下迭代每个像素,是为一个迭代周期。
在每个迭代周期中,对于每一个像素p,如果它同时满足6个条件,则标记它。
在当前迭代周期结束时,则把所有标记的像素的值设为背景值。
如果某次迭代周期中不存在标记点(即满足6个条件的像素),则算法结束。
假设背景值为0,前景值为1,则:6个条件为:(I):p 为1,即p不是背景;(2):x1,x3,x5,x7不全部为1(否则把p标记删除,图像空心了);(3):x1~x8 中,至少有2个为1(若只有1个为1,则是线段的端点。
若没有为1的,则为孤立点);(4):p的8连通联结数为1;联结数指在像素p的3*3邻域中,和p连接的图形分量的个数:(5)假设x3已经标记删除,那么当x3为0时,p的8联通联结数为1;(6)假设x5已经标记删除,那么当x5为0时,p的8联通联结数为1。
以上的理论选择网络博客:/xiaotie/archive/2010/08/12/1797760.html (此博客上有C#版本的Hilditch细化算法,但是使用unsafe的代码不是太好理解的。
我上一个自己写的代码/// <summary>/// Hilditch细化算法/// </summary>/// <param name="input"></param>/// <returns></returns>private int[,] ThinnerHilditch(int[,] input){int lWidth = input.GetLength(0);int lHeight = input.GetLength(1);bool IsModified = true;int Counter = 1;int[] nnb = new int[9];//去掉边框像素for (int i = 0; i < lWidth; i++){input[i, 0] = 0;input[i, lHeight - 1] = 0;}for (int j = 0; j < lHeight; j++){input[0, j] = 0;input[lWidth - 1, j] = 0;}do{Counter++;IsModified = false;int[,] nb = new int[3, 3];for (int i = 1; i < lWidth; i++){for (int j = 1; j < lHeight; j++){//条件1必须为黑点if (input[i, j] != 1){continue;}//取3*3领域for (int m = 0; m < 3; m++){for (int n = 0; n < 3; n++){nb[m, n] = input[i - 1 + m, j - 1 + n];}}//复制nnb[0] = nb[2, 1]==1?0:1;nnb[1] = nb[2, 0]==1?0:1;nnb[2] = nb[1, 0]==1?0:1;nnb[3] = nb[0, 0]==1?0:1;nnb[4] = nb[0, 1]==1?0:1;nnb[5] = nb[0, 2]==1?0:1;nnb[6] = nb[1, 2]==1?0:1;nnb[7] = nb[2, 2]==1?0:1;// 条件2:p0,p2,p4,p6 不皆为前景点if (nnb[0] == 0 && nnb[2] == 0 && nnb[4] == 0 && nnb[6] == 0) {continue;}// 条件3: p0~p7至少两个是前景点int iCount = 0;for (int ii = 0; ii < 8; ii++){iCount += nnb[ii];}if (iCount > 6) continue;// 条件4:联结数等于1if (DetectConnectivity(nnb) != 1){continue;}// 条件5: 假设p2已标记删除,则令p2为背景,不改变p的联结数if (input[i, j - 1] == -1){nnb[2] = 1;if (DetectConnectivity(nnb) != 1)continue;nnb[2] = 0;}// 条件6: 假设p4已标记删除,则令p4为背景,不改变p的联结数if (input[i, j + 1] == -1){nnb[6] = 1;if (DetectConnectivity(nnb) != 1) continue;nnb[6] = 0;}input[i, j] = -1;IsModified = true;}}for (int i = 0; i < lWidth; i++){for (int j = 0; j < lHeight; j++){if (input[i, j] == -1){input[i, j] = 0;}}}} while (IsModified);return input;}希望对大家有用。
帮助 | 留言交流 |首页我的图书馆主题阅读精彩目录精品文苑Tags会员浏览好书推荐图象细化算法(转载)mtjs收录于2009-01-09 阅读数:公众公开tags:vc图象算法图象细化算法#include "StdAfx.h"#include <stdlib.h>#include <malloc.h>void beforethin(unsigned char *ip, unsigned char *jp, unsigned long lx, unsigned long ly){unsigned long i,j;for(i=0; i<ly; i++){for(j=0; j<lx; j++){//这里要视前景是白点还是黑点而定,可以改动 //如果前景是白点,就是这样;反之反过来if(ip[i*lx+j]>0)jp[i*lx+j]=1;elsejp[i*lx+j]=0;}}}///////////////////////////////////////////////////////////////////////////Hilditch细化算法//功能:对图象进行细化//参数:image:代表图象的一维数组主题阅读吸烟的危害吸烟与癌症吸烟等于吸入重金属男性如此吸烟害上加害如何戒烟中药戒烟处方四则戒烟:生活中的经济学公开戒烟秘方给男士们推荐戒烟方法令人不寒而栗的戒烟广告马克思戒烟关于吸烟这件事,有趣热点推荐少见的文// lx:图象宽度// ly:图象高度// 无返回值void ThinnerHilditch(void *image, unsigned long lx, unsigned long ly) {char *f, *g;char n[10];unsigned int counter;short k, shori, xx, nrn;unsigned long i, j;long kk, kk11, kk12, kk13, kk21, kk22, kk23, kk31, kk32, kk33, size; size = (long)lx * (long)ly;g = (char *)malloc(size);if(g == NULL){printf("error in allocating memory!\n");return;}f = (char *)image;for(i=0; i<lx; i++){for(j=0; j<ly; j++){kk="i"*ly+j;if(f[kk]!=0){f[kk]=1;g[kk]=f[kk];}}}counter = 1; 革"群丑图"精心整理的80个管理类...135个治病小偏方,从...中国历史朝代让“开心穴”帮你除去烦躁佛教小常识一般学术论文的写作方法-搞笑一篇气死了九十九...心情小屋--图框(非常漂亮)婚后生活攻略文化大革命为什么没有被..."); } else { document.write(""); }Copyright © 2009 , All Rights Reserved服务条款设360doc为首页留言交流联系我们友情链接客服QQ:524562434 QQ群号:71307145do{printf("%4d*",counter); counter++;shori = 0;for(i=0; i<lx; i++){for(j=0; j<ly; j++){kk = i*ly+j;if(f[kk]<0)f[kk] = 0;g[kk]= f[kk];}}for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++) {kk="i"*ly+j;if(f[kk]!=1)continue;kk11 = (i-1)*ly+j-1; kk12 = kk11 + 1; kk13 = kk12 + 1; kk21 = i*ly+j-1;kk22 = kk21 + 1; kk23 = kk22 + 1; kk31 = (i+1)*ly+j-1; kk32 = kk31 + 1; kk33 = kk32 + 1;if((g[kk12]&&g[kk21]&&g[kk23]&&g[kk32])!=0)continue;nrn = g[kk11] + g[kk12] + g[kk13] + g[kk21] + g[kk23] + g[kk31] + g[kk32] + g[kk33];if(nrn <= 1){f[kk22] = 2;continue;}n[4] = f[kk11];n[3] = f[kk12];n[2] = f[kk13];n[5] = f[kk21];n[1] = f[kk23];n[6] = f[kk31];n[7] = f[kk32];n[8] = f[kk33];n[9] = n[1];xx = 0;for(k=1; k<8; k="k"+2){if((!n[k])&&(n[k+1]||n[k+2]))xx++;}if(xx!=1){f[kk22] = 2;continue;}if(f[kk12] == -1){f[kk12] = 0;n[3] = 0;xx = 0;for(k=1; k<8; k="k"+2){if((!n[k])&&(n[k+1]||n[k+2])) xx++;}if(xx != 1){f[kk12] = -1;continue;}f[kk12] = -1;n[3] = -1;}if(f[kk21]!=-1){f[kk22] = -1;shori = 1;continue;}f[kk21] = 0;n[5] = 0;xx = 0;for(k=1; k<8; k="k"+2){if((!n[k])&&(n[k+1]||n[k+2])) {xx++;}}if(xx == 1){f[kk21] = -1;f[kk22] = -1;shori =1;}elsef[kk21] = -1;}}}while(shori);free(g);}///////////////////////////////////////////////////////////////////////////Pavlidis细化算法//功能:对图象进行细化//参数:image:代表图象的一维数组// lx:图象宽度// ly:图象高度// 无返回值void ThinnerPavlidis(void *image, unsigned long lx, unsigned long ly) {char erase, n[8];char *f;unsigned char bdr1,bdr2,bdr4,bdr5;short c,k,b;unsigned long i,j;long kk,kk1,kk2,kk3;f = (char*)image;for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk = i*ly + j;if(f[kk])f[kk] = 1;}}for(i=0, kk1=0, kk2=ly-1; i<lx; i++, kk1+=ly, kk2+=ly) {f[kk1]=0;f[kk2]=0;}for(j=0, kk=(lx-1)*ly; j<ly; j++,kk++){f[j]=0;f[kk]=0;}c="5";erase =1;while(erase){c++;for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk="i"*ly+j;if(f[kk]!=1)kk1 = kk-ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[3] = f[kk1];n[2] = f[kk2];n[1] = f[kk3];kk1 = kk - 1;kk3 = kk + 1;n[4] = f[kk1];n[0] = f[kk3];kk1 = kk + ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[5] = f[kk1];n[6] = f[kk2];n[7] = f[kk3];bdr1 =0;for(k=0; k<8; k++){if(n[k]>=1)bdr1|=0x80>>k;}if((bdr1&0252)== 0252) continue;f[kk] = 2;b="0";for(k=0; k<=7; k++){b+=bdr1&(0x80>>k); }f[kk]=3;if((bdr1&0160)!=0&&(bdr1&07)!=0&&(bdr1&0210)==0)f[kk]=3;else if((bdr1&&0301)!=0&&(bdr1&034)!=0&&(bdr1&042)==0) f[kk]=3;else if((bdr1&0202)==0 && (bdr1&01)!=0)f[kk]=3;else if((bdr1&0240)==0 && (bdr1&0100)!=0)f[kk]=3;else if((bdr1&050)==0 && (bdr1&020)!=0)f[kk]=3;else if((bdr1&012)==0 && (bdr1&04)!=0)f[kk]=3;}}for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk = i*ly + j;if(!f[kk])continue;kk1 = kk - ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[3] = f[kk1];n[2] = f[kk2];n[1] = f[kk3];kk1 = kk - 1;kk2 = kk + 1;n[4] = f[kk1];n[0] = f[kk3];kk1 = kk + ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[5] = f[kk1];n[6] = f[kk2];n[7] = f[kk3];bdr1 = bdr2 =0;for(k=0; k<=7; k++){if(n[k]>=1)bdr1|=0x80>>k;if(n[k]>=2)bdr2|=0x80>>k;}if(bdr1==bdr2){f[kk] = 4;continue;}if(f[kk]!=2)continue;if((bdr2&0200)!=0 && (bdr1&010)==0 && ((bdr1&0100)!=0 &&(bdr1&001)!=0 ||((bdr1&0100)!=0 ||(bdr1 & 001)!=0) &&(bdr1&060)!=0 &&(bdr1&06)!=0)){f[kk] = 4;}else if((bdr2&040)!=0 && (bdr1&02)==0 && ((bdr1&020)!=0 && (bdr1&0100)!=0 ||((bdr1&020)!=0 || (bdr1&0100)!=0) &&(bdr1&014)!=0 && (bdr1&0201)!=0)){f[kk] = 4;}else if((bdr2&010)!=0 && (bdr1&0200)==0 && ((bdr1&04)!=0 && (bdr1&020)!=0 ||((bdr1&04)!=0 || (bdr1&020)!=0) &&(bdr1&03)!=0 && (bdr1&0140)!=0)){f[kk] = 4;}else if((bdr2&02)!=0 && (bdr1&040)==0 && ((bdr1&01)!=0 && (bdr1&04)!=0 ||((bdr1&01)!=0 || (bdr1&04)!=0) &&(bdr1&0300)!=0 && (bdr1&030)!=0)){f[kk] = 4;}}}for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk = i*ly + j;if(f[kk]!=2)continue;kk1 = kk - ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[3] = f[kk1];n[2] = f[kk2];n[1] = f[kk3];kk1 = kk - 1;kk2 = kk + 1;n[4] = f[kk1];n[0] = f[kk3];kk1 = kk + ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[5] = f[kk1];n[6] = f[kk2];n[7] = f[kk3];bdr4 = bdr5 =0;for(k=0; k<=7; k++){if(n[k]>=4)bdr4|=0x80>>k;if(n[k]>=5)bdr5|=0x80>>k;}if((bdr4&010) == 0){f[kk] = 5;continue;}if((bdr4&040) == 0 && bdr5 ==0) {f[kk] = 5;continue;}if(f[kk]==3||f[kk]==4)f[kk] = c;}}erase = 0;for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk = i*ly +j;if(f[kk]==2||f[kk] == 5){erase = 1;f[kk] = 0;}}}}}///////////////////////////////////////////////////////////////////////////Rosenfeld细化算法//功能:对图象进行细化//参数:image:代表图象的一维数组// lx:图象宽度// ly:图象高度// 无返回值void ThinnerRosenfeld(void *image, unsigned long lx, unsigned long ly) {char *f, *g;char n[10];char a[5] = {0, -1, 1, 0, 0};char b[5] = {0, 0, 0, 1, -1};char nrnd, cond, n48, n26, n24, n46, n68, n82, n123, n345, n567, n781; short k, shori;unsigned long i, j;long ii, jj, kk, kk1, kk2, kk3, size;size = (long)lx * (long)ly;g = (char *)malloc(size);if(g==NULL){printf("error in alocating mmeory!\n"); return;}f = (char *)image;for(kk=0l; kk<size; kk++){g[kk] = f[kk];}do{shori = 0;for(k=1; k<=4; k++){for(i=1; i<lx-1; i++){ii = i + a[k];for(j=1; j<ly-1; j++){kk = i*ly + j;if(!f[kk])continue;jj = j + b[k];kk1 = ii*ly + jj;if(f[kk1])continue;kk1 = kk - ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[2] = f[kk2];n[1] = f[kk3];kk1 = kk - 1;kk3 = kk + 1;n[4] = f[kk1];n[8] = f[kk3];kk1 = kk + ly - 1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[5] = f[kk1];n[6] = f[kk2];n[7] = f[kk3];nrnd = n[1] + n[2] + n[3] + n[4]+n[5] + n[6] + n[7] + n[8];if(nrnd<=1)continue;cond = 0;n48 = n[4] + n[8];n26 = n[2] + n[6];n24 = n[2] + n[4];n46 = n[4] + n[6];n68 = n[6] + n[8];n82 = n[8] + n[2];n123 = n[1] + n[2] + n[3];n345 = n[3] + n[4] + n[5];n567 = n[5] + n[6] + n[7];n781 = n[7] + n[8] + n[1];if(n[2]==1 && n48==0 && n567>0) {if(!cond)continue;g[kk] = 0;continue;}if(n[6]==1 && n48==0 && n123>0) {if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[8]==1 && n26==0 && n345>0) {if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[4]==1 && n26==0 && n781>0) {if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[5]==1 && n46==0){if(!cond)continue;g[kk] = 0;continue;}if(n[7]==1 && n68==0) {if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[1]==1 && n82==0) {if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[3]==1 && n24==0) {if(!cond)continue;g[kk] = 0;shori = 1;continue;}cond = 1;if(!cond)continue;g[kk] = 0;shori = 1;}}for(i=0; i<lx; i++){for(j=0; j<ly; j++){kk = i*ly + j;f[kk] = g[kk];}}}}while(shori);free(g);}///////////////////////////////////////////////////////////////////////////基于索引表的细化细化算法//功能:对图象进行细化//参数:lpDIBBits:代表图象的一维数组// lWidth:图象高度// lHeight:图象宽度// 无返回值BOOL WINAPI ThiningDIBSkeleton (LPSTR lpDIBBits, LONG lWidth, LONG lHeight){//循环变量long i;long j;long lLength;unsigned char deletemark[256] = {0,0,0,0,0,0,0,1, 0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0, 0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0, 1,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0, 1,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0, 1,0,1,1,1,0,1,1,0,0,1,1,0,0,1,1, 0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,1,1,1,1,0,1,0,0,0,1, 0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,1, 1,1,0,0,1,0,0,0,0,1,1,1,0,0,1,1, 0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1, 1,1,0,0,1,1,0,0,1,1,1,1,0,0,1,1, 1,1,0,0,1,1,0,0};//索引表unsigned char p0, p1, p2, p3, p4, p5, p6, p7;unsigned char *pmid, *pmidtemp;unsigned char sum;int changed;bool bStart = true;lLength = lWidth * lHeight;unsigned char *pTemp = (unsigned char *)malloc(sizeof(unsigned char) * lWidth * lHeight);// P0 P1 P2// P7 P3// P6 P5 P4while(bStart){bStart = false;changed = 0;//首先求边缘点(并行)pmid = (unsigned char *)lpDIBBits + lWidth + 1;memset(pTemp, (BYTE) 0, lLength);pmidtemp = (unsigned char *)pTemp + lWidth + 1; for(i = 1; i < lHeight -1; i++){for(j = 1; j < lWidth - 1; j++){if( *pmid == 0){pmid++;pmidtemp++;continue;}p3 = *(pmid + 1);p2 = *(pmid + 1 - lWidth);p1 = *(pmid - lWidth);p0 = *(pmid - lWidth -1);p7 = *(pmid - 1);p6 = *(pmid + lWidth - 1);p5 = *(pmid + lWidth);p4 = *(pmid + lWidth + 1);sum = p0 & p1 & p2 & p3 & p4 & p5 & p6 & p7; if(sum == 0){*pmidtemp = 1;}pmid++;pmidtemp++;}pmid++;pmid++;pmidtemp++;pmidtemp++;}//现在开始串行删除pmid = (unsigned char *)lpDIBBits + lWidth + 1;pmidtemp = (unsigned char *)pTemp + lWidth + 1;for(i = 1; i < lHeight -1; i++){for(j = 1; j < lWidth - 1; j++){if( *pmidtemp == 0){pmid++;pmidtemp++;continue;}p3 = *(pmid + 1);p2 = *(pmid + 1 - lWidth);p1 = *(pmid - lWidth);p0 = *(pmid - lWidth -1);p7 = *(pmid - 1);p6 = *(pmid + lWidth - 1);p5 = *(pmid + lWidth);p4 = *(pmid + lWidth + 1);p1 *= 2;p2 *= 4;p3 *= 8;p4 *= 16;p5 *= 32;p6 *= 64;p7 *= 128;sum = p0 | p1 | p2 | p3 | p4 | p5 | p6 | p7;if(deletemark[sum] == 1){*pmid = 0;bStart = true;}pmid++;pmidtemp++;}pmid++;pmid++;pmidtemp++;pmidtemp++;}}return true;}上一篇:VC++ 实现GPS全球定位系统定位数据的提取下一篇:Visual C++ 实现数字图像增强处理[上一篇] [下一篇] (mtjs的分类目录 [C++])相关文章c和c#托管与非托管代码中变量对应 - DotNet男孩社区-提供大量.Net技术文章,DotNet技术讨论区 - powered by Huobazi~2005-12-22 kenwang多个 ds18b20 C51程序 - 博客 BLOG 我的世界我的??...2008-11-19 susfly内存对齐2006-08-07 thunder123函数指针的几种不同用法2005-07-29 accesine位域排序 struct endian - 半天月·随笔 || 拾遗 -CSDNBlog2008-09-27 ShaneWua.out文件格式分析2008-03-13 redmice全面整理的C++面试题 - ljzcome的专栏2006-01-10 firedragon飞阳的半亩实验田2007-04-24 ShangShujie查看更多文章>>发送评论时内容自动复制到剪切板。
图像处理中常见算法优化方法总结在图像处理中,算法的优化是提高图像处理速度和效果的关键。
通过应用优化算法,可以实现更快速、更准确的图像处理结果。
以下是图像处理中常见的算法优化方法的总结。
1. 空间域滤波器优化空间域滤波器是一种广泛应用于图像处理的算法。
常见的优化方法包括:- 利用均值滤波器的局部性原理,通过构建滑动窗口的方式减少重复计算,从而提高滤波速度;- 采用快速傅里叶变换(FFT)算法,将空间域滤波器转换为频域滤波器,提高滤波效率。
2. 图像压缩算法优化图像压缩是在保持图像质量的前提下减小图像文件大小的过程。
常见的图像压缩算法优化方法包括:- 针对JPEG压缩算法,调整量化表的参数,减小图像失真程度;- 对基于波小波变换的压缩算法,采用快速算法实现高效的压缩和解压缩;- 优化哈夫曼编码算法的实现,提高编码和解码的速度。
3. 边缘检测算法优化边缘检测是图像处理的一个重要步骤,用于提取图像中的边界信息。
常见的边缘检测算法包括:- Sobel算子、Prewitt算子和Roberts算子等基于梯度的算法。
优化方法包括通过使用模板计算的优化和并行计算的优化,提高边缘检测的速度;- Canny算法是一种精确的边缘检测算法,优化方法包括调整滞后阈值和非极大值抑制的参数,提高边缘检测的准确性。
4. 图像分割算法优化图像分割是将图像分成若干个具有独特特征的区域的过程,常见的优化方法包括:- 针对基于阈值的分割算法,通过自适应选择阈值的方法,提高图像分割的效果;- 针对基于区域的分割算法,通过优化区域的相似度计算和合并策略,提高分割的准确性和效率。
5. 形态学图像处理算法优化形态学图像处理是一种数学形态学理论在图像处理中的应用,常见的优化方法包括:- 结构元素的设计优化,通过选择合适的结构元素形状和大小,提高形态学操作的效果;- 并行计算优化,利用多线程或GPU加速形态学操作的处理速度。
6. 图像特征提取算法优化图像特征提取是从图像中提取出表达图像特性的特征的过程,常见的优化方法包括:- 减少冗余计算,通过降低采样率、减少特征维度等方法,减少特征提取的计算量;- 采用基于树结构的快速算法,例如k-d树、VP树等方法,提高特征匹配的速度。
图像的细化主要是针对二值图而言所谓骨架,可以理解为图像的中轴,,一个长方形的骨架,是它的长方向上的中轴线,圆的骨架是它的圆心,直线的骨架是它自身,孤立点的骨架也是自身。
骨架的获取主要有两种方法:(1)基于烈火模拟设想在同一时刻,将目标的边缘线都点燃,火的前沿以匀速向内部蔓延,当前沿相交时火焰熄灭,火焰熄灭点的结合就是骨架。
(2)基于最大圆盘目标的骨架是由目标内所有内切圆盘的圆心组成我们来看看典型的图形的骨架(用粗线表示)细化的算法有很多种,但比较常用的算法是查表法细化是从原来的图中去掉一些点,但仍要保持原来的形状。
实际上是保持原图的骨架。
判断一个点是否能去掉是以8个相邻点(八连通)的情况来作为判据的,具体判据为:1,内部点不能删除2,鼓励点不能删除3,直线端点不能删除4,如果P是边界点,去掉P后,如果连通分量不增加,则P可删除看看上面那些点。
第一个点不能去除,因为它是内部点第二个点不能去除,它也是内部点第三个点不能去除,删除后会使原来相连的部分断开第四个点可以去除,这个点不是骨架第五个点不可以去除,它是直线的端点第六个点不可以去除,它是直线的端点对于所有的这样的点,我们可以做出一张表,来判断这样的点能不能删除我们对于黑色的像素点,对于它周围的8个点,我们赋予不同的价值,若周围某黑色,我们认为其价值为0,为白色则取九宫格中对应的价值对于前面那幅图中第一个点,也就是内部点,它周围的点都是黑色,所以他的总价值是0,对应于索引表的第一项前面那幅图中第二点,它周围有三个白色点,它的总价值为1+4+32=37,对应于索引表中第三十八项1.图像细化的基本原理⑴ 图像形态学处理的概念数字图像处理中的形态学处理是指将数字形态学作为工具从图像中提取对于表达和描绘区域形状有用处的图像分量,比如边界、骨架以及凸壳,还包括用于预处理或后处理的形态学过滤、细化和修剪等。
图像形态学处理中我们感兴趣的主要是二值图像。
在二值图像中,所有黑色像素的集合是图像完整的形态学描述,二值图像的各个分量是Z2的元素。
二值图像的细化算法作者:林新辉来源:《软件导刊》2011年第07期摘要:二值图像是只有黑白两种颜色的图像,二值图像的细化是讨论将一个图像中的黑色部分沿着它的中心轴线将其细化为一个像素宽的线条的处理过程,细化的结果能基本保留图形中黑色部分的拓扑结构。
介绍了一个二值图像的细化算法,思想是从原图像的边界逐层消除黑色像素点,但同时保持黑色部分的连通性,直到最后得到细化结果。
关键词:二值图像;细化;连通性;边界点;连通点中图分类号:TP312文献标识码:A文章编号:1672-7800(2011)07-0048-作者简介:林新辉(1979-),男,浙江海宁人,硕士,浙江经贸职业技术学院信息技术系助教,研究方向为计算机辅助几何设计。
0引言在计算机领域,图像处理的问题越来越成为重要的一部分,因为现在的数据交流,已不再是简单的数值,而是更多地转换到大量的图片和影音图像上来。
所以一个个的图像处理的问题就摆在了我们的面前。
但形形色色的图像处理的算法,通过抽象处理,都是可以归结为一些简单的处理。
比如多颜色的处理,可以先从两个颜色的情况开始,再进行展开。
二值图像的细化就是这些简单处理中的一个问题。
二值图像就是只有黑白两种颜色构成的图像,二值图像的细化就是将图像中的黑色部分沿着它的中心轴线将其细化为一个象素宽的线条的处理过程。
二值图像的细化在计算机的图像处理领域有重要的意义,它其实是显示了整个图像的一个拓扑结构,它在一些模式识别,点阵图形的矢量化等方面有很好的作用。
1二值图像的细化的分析首先,对二值图像进行设定。
这里假定二值图像以白色为底,细化黑色部分,且给出的黑色部分的图像为连通的。
这样,对任意的黑色图像,必定存在一个合适的n为正整数,使得它在以白色为底的2n×2n的正方形内。
由于假定黑色图像的连通性,则二值图像的细化处理后的图像必定是连通的。
为了便于处理,设计了一个256×256的正方形作为处理二值图像的区域,且在初始的作图中保证黑色部分图像的连通性。
圖像細化算法大全#include "StdAfx.h"#include <stdlib.h>#include <malloc.h>void beforethin(unsigned char *ip, unsigned char *jp,unsigned long lx, unsigned long ly){unsigned long i,j;for(i=0; i<ly; i++){for(j=0; j<lx; j++){//這裡要視前景是白點還是黑點而定,可以改動//如果前景是白點,就是這樣;反之反過來if(ip[i*lx+j]>0)jp[i*lx+j]=1;elsejp[i*lx+j]=0;}}}///////////////////////////////////////////////////////////////////////////Hilditch細化算法//功能:對圖像進行細化//參數:image:代表圖像的一維數組// lx:圖像寬度// ly:圖像高度// 無返回值void ThinnerHilditch(void *image, unsigned long lx, unsigned long ly) {char *f, *g;char n[10];unsigned int counter;short k, shori, xx, nrn;unsigned long i, j;long kk, kk11, kk12, kk13, kk21, kk22, kk23, kk31, kk32, kk33, size;size = (long)lx * (long)ly;g = (char *)malloc(size);if(g == NULL){printf("error in allocating memory!/n");return;}f = (char *)image;for(i=0; i<lx; i++){for(j=0; j<ly; j++){kk=i*ly+j;if(f[kk]!=0){f[kk]=1;g[kk]=f[kk];}}}counter = 1;do{printf("%4d*",counter);counter++;shori = 0;for(i=0; i<lx; i++){for(j=0; j<ly; j++){kk = i*ly+j;if(f[kk]<0)f[kk] = 0;g[kk]= f[kk];}}for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk=i*ly+j;if(f[kk]!=1)kk11 = (i-1)*ly+j-1;kk12 = kk11 + 1;kk13 = kk12 + 1;kk21 = i*ly+j-1;kk22 = kk21 + 1;kk23 = kk22 + 1;kk31 = (i+1)*ly+j-1;kk32 = kk31 + 1;kk33 = kk32 + 1;if((g[kk12]&&g[kk21]&&g[kk23]&&g[kk32])!=0) continue;nrn = g[kk11] + g[kk12] + g[kk13] + g[kk21] + g[kk23] + g[kk31] + g[kk32] + g[kk33];if(nrn <= 1){f[kk22] = 2;continue;}n[4] = f[kk11];n[3] = f[kk12];n[2] = f[kk13];n[5] = f[kk21];n[1] = f[kk23];n[6] = f[kk31];n[7] = f[kk32];n[8] = f[kk33];n[9] = n[1];xx = 0;for(k=1; k<8; k=k+2){if((!n[k])&&(n[k+1]||n[k+2]))xx++;}if(xx!=1){f[kk22] = 2;}if(f[kk12] == -1){f[kk12] = 0;n[3] = 0;xx = 0;for(k=1; k<8; k=k+2){if((!n[k])&&(n[k+1]||n[k+2]))xx++;}if(xx != 1){f[kk12] = -1;continue;}f[kk12] = -1;n[3] = -1;}if(f[kk21]!=-1){f[kk22] = -1;shori = 1;continue;}f[kk21] = 0;n[5] = 0;xx = 0;for(k=1; k<8; k=k+2){if((!n[k])&&(n[k+1]||n[k+2])){xx++;}}{f[kk21] = -1;f[kk22] = -1;shori =1;}elsef[kk21] = -1;}}}while(shori);free(g);}///////////////////////////////////////////////////////////////////////////Pavlidis細化算法//功能:對圖像進行細化//參數:image:代表圖像的一維數組// lx:圖像寬度// ly:圖像高度// 無返回值void ThinnerPavlidis(void *image, unsigned long lx, unsigned long ly) {char erase, n[8];char *f;unsigned char bdr1,bdr2,bdr4,bdr5;short c,k,b;unsigned long i,j;long kk,kk1,kk2,kk3;f = (char*)image;for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk = i*ly + j;if(f[kk])f[kk] = 1;}}for(i=0, kk1=0, kk2=ly-1; i<lx; i++, kk1+=ly, kk2+=ly){f[kk1]=0;f[kk2]=0;}for(j=0, kk=(lx-1)*ly; j<ly; j++,kk++) {f[j]=0;f[kk]=0;}c=5;erase =1;while(erase){c++;for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk=i*ly+j;if(f[kk]!=1)continue;kk1 = kk-ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[3] = f[kk1];n[2] = f[kk2];n[1] = f[kk3];kk1 = kk - 1;kk3 = kk + 1;n[4] = f[kk1];n[0] = f[kk3];kk1 = kk + ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[5] = f[kk1];n[6] = f[kk2];n[7] = f[kk3];bdr1 =0;for(k=0; k<8; k++){bdr1|=0x80>>k;}if((bdr1&0252)== 0252)continue;f[kk] = 2;b=0;for(k=0; k<=7; k++){b+=bdr1&(0x80>>k);}if(b<=1)f[kk]=3;if((bdr1&0160)!=0&&(bdr1&07)!=0&&(bdr1&0210)==0)f[kk]=3;else if((bdr1&&0301)!=0&&(bdr1&034)!=0&&(bdr1&042)==0) f[kk]=3;else if((bdr1&0202)==0 && (bdr1&01)!=0)f[kk]=3;else if((bdr1&0240)==0 && (bdr1&0100)!=0)f[kk]=3;else if((bdr1&050)==0 && (bdr1&020)!=0)f[kk]=3;else if((bdr1&012)==0 && (bdr1&04)!=0)f[kk]=3;}}for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk = i*ly + j;if(!f[kk])continue;kk1 = kk - ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[3] = f[kk1];n[1] = f[kk3];kk1 = kk - 1;kk2 = kk + 1;n[4] = f[kk1];n[0] = f[kk3];kk1 = kk + ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[5] = f[kk1];n[6] = f[kk2];n[7] = f[kk3];bdr1 = bdr2 =0;for(k=0; k<=7; k++){if(n[k]>=1)bdr1|=0x80>>k;if(n[k]>=2)bdr2|=0x80>>k;}if(bdr1==bdr2){f[kk] = 4;continue;}if(f[kk]!=2)continue;if((bdr2&0200)!=0 && (bdr1&010)==0 && ((bdr1&0100)!=0 &&(bdr1&001)!=0 ||((bdr1&0100)!=0 ||(bdr1 & 001)!=0) &&(bdr1&060)!=0 &&(bdr1&06)!=0)){f[kk] = 4;}else if((bdr2&040)!=0 && (bdr1&02)==0 && ((bdr1&020)!=0 && (bdr1&0100)!=0 ||((bdr1&020)!=0 || (bdr1&0100)!=0) &&(bdr1&014)!=0 && (bdr1&0201)!=0)) {}else if((bdr2&010)!=0 && (bdr1&0200)==0 &&((bdr1&04)!=0 && (bdr1&020)!=0 ||((bdr1&04)!=0 || (bdr1&020)!=0) &&(bdr1&03)!=0 && (bdr1&0140)!=0)){f[kk] = 4;}else if((bdr2&02)!=0 && (bdr1&040)==0 &&((bdr1&01)!=0 && (bdr1&04)!=0 ||((bdr1&01)!=0 || (bdr1&04)!=0) &&(bdr1&0300)!=0 && (bdr1&030)!=0)){f[kk] = 4;}}}for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk = i*ly + j;if(f[kk]!=2)continue;kk1 = kk - ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[3] = f[kk1];n[2] = f[kk2];n[1] = f[kk3];kk1 = kk - 1;kk2 = kk + 1;n[4] = f[kk1];n[0] = f[kk3];kk1 = kk + ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[5] = f[kk1];n[6] = f[kk2];n[7] = f[kk3];for(k=0; k<=7; k++){if(n[k]>=4)bdr4|=0x80>>k;if(n[k]>=5)bdr5|=0x80>>k;}if((bdr4&010) == 0){f[kk] = 5;continue;}if((bdr4&040) == 0 && bdr5 ==0){f[kk] = 5;continue;}if(f[kk]==3||f[kk]==4)f[kk] = c;}}erase = 0;for(i=1; i<lx-1; i++){for(j=1; j<ly-1; j++){kk = i*ly +j;if(f[kk]==2||f[kk] == 5){erase = 1;f[kk] = 0;}}}}}///////////////////////////////////////////////////////////////////////////Rosenfeld細化算法//功能:對圖像進行細化//參數:image:代表圖像的一維數組// lx:圖像寬度// ly:圖像高度// 無返回值void ThinnerRosenfeld(void *image, unsigned long lx, unsigned long ly) {char *f, *g;char n[10];char a[5] = {0, -1, 1, 0, 0};char b[5] = {0, 0, 0, 1, -1};char nrnd, cond, n48, n26, n24, n46, n68, n82, n123, n345, n567, n781;short k, shori;unsigned long i, j;long ii, jj, kk, kk1, kk2, kk3, size;size = (long)lx * (long)ly;g = (char *)malloc(size);if(g==NULL){printf("error in alocating mmeory!/n");return;}f = (char *)image;for(kk=0l; kk<size; kk++){g[kk] = f[kk];}do{shori = 0;for(k=1; k<=4; k++){for(i=1; i<lx-1; i++){ii = i + a[k];for(j=1; j<ly-1; j++){kk = i*ly + j;if(!f[kk])continue;jj = j + b[k];if(f[kk1])continue;kk1 = kk - ly -1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[3] = f[kk1];n[2] = f[kk2];n[1] = f[kk3];kk1 = kk - 1;kk3 = kk + 1;n[4] = f[kk1];n[8] = f[kk3];kk1 = kk + ly - 1;kk2 = kk1 + 1;kk3 = kk2 + 1;n[5] = f[kk1];n[6] = f[kk2];n[7] = f[kk3];nrnd = n[1] + n[2] + n[3] + n[4]+n[5] + n[6] + n[7] + n[8];if(nrnd<=1)continue;cond = 0;n48 = n[4] + n[8];n26 = n[2] + n[6];n24 = n[2] + n[4];n46 = n[4] + n[6];n68 = n[6] + n[8];n82 = n[8] + n[2];n123 = n[1] + n[2] + n[3];n345 = n[3] + n[4] + n[5];n567 = n[5] + n[6] + n[7];n781 = n[7] + n[8] + n[1];if(n[2]==1 && n48==0 && n567>0) {if(!cond)continue;g[kk] = 0;continue;}if(n[6]==1 && n48==0 && n123>0) {if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[8]==1 && n26==0 && n345>0) {if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[4]==1 && n26==0 && n781>0) {if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[5]==1 && n46==0){if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[7]==1 && n68==0){if(!cond)continue;shori = 1;continue;}if(n[1]==1 && n82==0){if(!cond)continue;g[kk] = 0;shori = 1;continue;}if(n[3]==1 && n24==0){if(!cond)continue;g[kk] = 0;shori = 1;continue;}cond = 1;if(!cond)continue;g[kk] = 0;shori = 1;}}for(i=0; i<lx; i++){for(j=0; j<ly; j++){kk = i*ly + j;f[kk] = g[kk];}}}}while(shori);free(g);}///////////////////////////////////////////////////////////////////////////基於索引表的細化細化算法//功能:對圖像進行細化//參數:lpDIBBits:代表圖像的一維數組// lWidth:圖像高度// lHeight:圖像寬度// 無返回值BOOL WINAPI ThiningDIBSkeleton (LPSTR lpDIBBits, LONG lWidth, LONG lHeight){//循環變量long i;long j;long lLength;unsigned char deletemark[256] = {0,0,0,0,0,0,0,1, 0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0, 0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0, 1,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0, 1,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0, 1,0,1,1,1,0,1,1,0,0,1,1,0,0,1,1, 0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,1,1,1,1,0,1,0,0,0,1, 0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,1, 1,1,0,0,1,0,0,0,0,1,1,1,0,0,1,1, 0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1, 1,1,0,0,1,1,0,0,1,1,1,1,0,0,1,1, 1,1,0,0,1,1,0,0};//索引表unsigned char p0, p1, p2, p3, p4, p5, p6, p7;unsigned char *pmid, *pmidtemp;unsigned char sum;int changed;bool bStart = true;lLength = lWidth * lHeight;unsigned char *pTemp = (unsigned char *)malloc(sizeof(unsigned char) * lWidth * lHeight);// P0 P1 P2// P7 P3// P6 P5 P4while(bStart){bStart = false;changed = 0;//首先求邊緣點(並行)pmid = (unsigned char *)lpDIBBits + lWidth + 1;memset(pTemp, (BYTE) 0, lLength);pmidtemp = (unsigned char *)pTemp + lWidth + 1;for(i = 1; i < lHeight -1; i++){for(j = 1; j < lWidth - 1; j++){if( *pmid == 0){pmid++;pmidtemp++;continue;}p3 = *(pmid + 1);p2 = *(pmid + 1 - lWidth);p1 = *(pmid - lWidth);p0 = *(pmid - lWidth -1);p7 = *(pmid - 1);p6 = *(pmid + lWidth - 1);p5 = *(pmid + lWidth);p4 = *(pmid + lWidth + 1);sum = p0 & p1 & p2 & p3 & p4 & p5 & p6 & p7;if(sum == 0){*pmidtemp = 1;}pmid++;pmidtemp++;}pmid++;pmid++;pmidtemp++;pmidtemp++;}//現在開始串行刪除pmid = (unsigned char *)lpDIBBits + lWidth + 1; pmidtemp = (unsigned char *)pTemp + lWidth + 1;for(i = 1; i < lHeight -1; i++){for(j = 1; j < lWidth - 1; j++){if( *pmidtemp == 0){pmid++;pmidtemp++;continue;}p3 = *(pmid + 1);p2 = *(pmid + 1 - lWidth);p1 = *(pmid - lWidth);p0 = *(pmid - lWidth -1);p7 = *(pmid - 1);p6 = *(pmid + lWidth - 1);p5 = *(pmid + lWidth);p4 = *(pmid + lWidth + 1);p1 *= 2;p2 *= 4;p3 *= 8;p4 *= 16;p5 *= 32;p6 *= 64;p7 *= 128;sum = p0 | p1 | p2 | p3 | p4 | p5 | p6 | p7;if(deletemark[sum] == 1){*pmid = 0;bStart = true;}pmid++;pmidtemp++;}pmid++;pmid++;pmidtemp++;pmidtemp++;}}return true;}。