二值图像细化原理

在做小车走迷宫的图像处理的过程,要对路径进行细化,参看了T. Y. ZHANG and C. Y. SUEN写的《A Fast Parallel Algorithm for Thinning Digital Patterns》

受益匪浅,故将学习到的mark一下


算法有N次迭代,每次迭代分为两次子迭代,第一次迭代消去东边和南边的边界点,以及西北方向的拐角点,第二次迭代消去西边和北边的边界点,东南方向的拐角点。


考虑以下三乘三矩阵,P1 P2 P3..P9为像素点,非0即1


P9 P2 P3
P8 P1 P4
P7 P6 P5

当满足以下四个条件时,即可消去P1点(第一次子迭代)

(a) 2 =< B(P1) <= 6
(b) A(P1)= 1
(c) P2 * P4 * P6 = 0
(d) P4 * P6 * P8  =  0

解释一下,A(P1)指的是P2 P3 P4..P9中的01对数量 ,B(P1)指的是P2 P3 P4..P9中1的个数


图1的P1不能消去,因为A(P1)= 2  (P1为左下和右上的连接点)

图1



图2的P1不能消去,因为B(P1)= 1 (P1其实是左端点)

图2



现在来分析一下c d条件,等价于 P4= 0 or P6 = 0 or (P2 = 0 and P8 = 0) 

分别对应于东边和南边的边界点,以及西北方向的拐角点


第二次迭代仅仅把修改c d条件为

(c') P2 * P4 * P8  =  0
(d') P2 * P6 * P8  =  0


项目中的效果



第一次迭代后



第六次迭代后


贴出源代码

<span style="font-size:12px;">void cvThin (IplImage* src, IplImage* dst, int iterations = 1) { 
	cvCopyImage(src, dst); 
	BwImage dstdat(dst); 
	IplImage* t_image = cvCloneImage(src); 
	BwImage t_dat(t_image);  
	for (int n = 0; n < iterations; n++) 
		for (int s = 0; s <= 1; s++) { 
			cvCopyImage(dst, t_image); 
			for (int i = 0; i < src->height; i++)  
				for (int j = 0; j < src->width; j++) 
					if (t_dat[i][j]) { 
						int a = 0, b = 0; 
						int d[8][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}}; 
						int p[8]; 
						p[0] = (i == 0) ? 0 : t_dat[i-1][j]; 
						for (int k = 1; k <= 8; k++) { 
							if (i+d[k%8][0] < 0 || i+d[k%8][0] >= src->height || j+d[k%8][1] < 0 || j+d[k%8][1] >= src->width) 
								p[k%8] = 0; 
							else p[k%8] = t_dat[ i+d[k%8][0] ][ j+d[k%8][1] ]; 
							if (p[k%8]) { 
								b++; 
								if (!p[k-1]) a++; 
							} 
						} 
						if (b >= 2 && b <= 6 && a == 1) 
							if (!s && !(p[2] && p[4] && (p[0] || p[6]))) 
								dstdat[i][j] = 0; 
							else if (s && !(p[0] && p[6] && (p[2] || p[4]))) 
								dstdat[i][j] = 0; 
					} 
		} 
	cvReleaseImage(&t_image); 
}</span>






展开阅读全文

没有更多推荐了,返回首页