在我们进行图像处理的时候,有可能需要对图像进行细化,提取出图像的骨架信息,进行更加有效的分析。
图像细化(Image Thinning),一般指二值图像的骨架化(Image Skeletonization) 的一种操作运算。
所谓的细化就是经过一层层的剥离,从原来的图中去掉一些点,但仍要保持原来的形状,直到得到图像的骨架。骨架,可以理解为图象的中轴。
好的细化算法一定要满足:
- 收敛性;
- 保证细化后细线的连通性;
- 保持原图的基本形状;
- 减少笔画相交处的畸变;
- 细化结果是原图像的中心线;
- 细化的快速性和迭代次数少;
1 void chao_thinimage(Mat &srcimage)//单通道、二值化后的图像
2 {
3 vector<Point> deletelist1;
4 int Zhangmude[9];
5 int nl = srcimage.rows;
6 int nc = srcimage.cols;
7 while (true)
8 {
9 for (int j = 1; j < (nl - 1); j++)
10 {
11 uchar* data_last = srcimage.ptr<uchar>(j - 1);
12 uchar* data = srcimage.ptr<uchar>(j);
13 uchar* data_next = srcimage.ptr<uchar>(j + 1);
14 for (int i = 1; i < (nc - 1); i++)
15 {
16 if (data[i] == 255)
17 {
18 Zhangmude[0] = 1;
19 if (data_last[i] == 255) Zhangmude[1] = 1;
20 else Zhangmude[1] = 0;
21 if (data_last[i + 1] == 255) Zhangmude[2] = 1;
22 else Zhangmude[2] = 0;
23 if (data[i + 1] == 255) Zhangmude[3] = 1;
24 else Zhangmude[3] = 0;
25 if (data_next[i + 1] == 255) Zhangmude[4] = 1;
26 else Zhangmude[4] = 0;
27 if (data_next[i] == 255) Zhangmude[5] = 1;
28 else Zhangmude[5] = 0;
29 if (data_next[i - 1] == 255) Zhangmude[6] = 1;
30 else Zhangmude[6] = 0;
31 if (data[i - 1] == 255) Zhangmude[7] = 1;
32 else Zhangmude[7] = 0;
33 if (data_last[i - 1] == 255) Zhangmude[8] = 1;
34 else Zhangmude[8] = 0;
35 int whitepointtotal = 0;
36 for (int k = 1; k < 9; k++)
37 {
38 whitepointtotal = whitepointtotal + Zhangmude[k];
39 }
40 if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
41 {
42 int ap = 0;
43 if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
44 if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
45 if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
46 if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
47 if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
48 if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
49 if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
50 if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
51 if (ap == 1)
52 {
53 if ((Zhangmude[1] * Zhangmude[7] * Zhangmude[5] == 0) && (Zhangmude[3] * Zhangmude[5] * Zhangmude[7] == 0))
54 {
55 deletelist1.push_back(Point(i, j));
56 }
57 }
58 }
59 }
60 }
61 }
62 if (deletelist1.size() == 0) break;
63 for (size_t i = 0; i < deletelist1.size(); i++)
64 {
65 Point tem;
66 tem = deletelist1[i];
67 uchar* data = srcimage.ptr<uchar>(tem.y);
68 data[tem.x] = 0;
69 }
70 deletelist1.clear();
71
72 for (int j = 1; j < (nl - 1); j++)
73 {
74 uchar* data_last = srcimage.ptr<uchar>(j - 1);
75 uchar* data = srcimage.ptr<uchar>(j);
76 uchar* data_next = srcimage.ptr<uchar>(j + 1);
77 for (int i = 1; i < (nc - 1); i++)
78 {
79 if (data[i] == 255)
80 {
81 Zhangmude[0] = 1;
82 if (data_last[i] == 255) Zhangmude[1] = 1;
83 else Zhangmude[1] = 0;
84 if (data_last[i + 1] == 255) Zhangmude[2] = 1;
85 else Zhangmude[2] = 0;
86 if (data[i + 1] == 255) Zhangmude[3] = 1;
87 else Zhangmude[3] = 0;
88 if (data_next[i + 1] == 255) Zhangmude[4] = 1;
89 else Zhangmude[4] = 0;
90 if (data_next[i] == 255) Zhangmude[5] = 1;
91 else Zhangmude[5] = 0;
92 if (data_next[i - 1] == 255) Zhangmude[6] = 1;
93 else Zhangmude[6] = 0;
94 if (data[i - 1] == 255) Zhangmude[7] = 1;
95 else Zhangmude[7] = 0;
96 if (data_last[i - 1] == 255) Zhangmude[8] = 1;
97 else Zhangmude[8] = 0;
98 int whitepointtotal = 0;
99 for (int k = 1; k < 9; k++)
100 {
101 whitepointtotal = whitepointtotal + Zhangmude[k];
102 }
103 if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
104 {
105 int ap = 0;
106 if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
107 if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
108 if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
109 if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
110 if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
111 if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
112 if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
113 if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
114 if (ap == 1)
115 {
116 if ((Zhangmude[1] * Zhangmude[3] * Zhangmude[5] == 0) && (Zhangmude[3] * Zhangmude[1] * Zhangmude[7] == 0))
117 {
118 deletelist1.push_back(Point(i, j));
119 }
120 }
121 }
122 }
123 }
124 }
125 if (deletelist1.size() == 0) break;
126 for (size_t i = 0; i < deletelist1.size(); i++)
127 {
128 Point tem;
129 tem = deletelist1[i];
130 uchar* data = srcimage.ptr<uchar>(tem.y);
131 data[tem.x] = 0;
132 }
133 deletelist1.clear();
134 }
135 }