骨架提取/图像细,相信很多人都听说过,图像细化原理 可以参看这篇博文。由于opencv没有现成的函数,因此,看懂了原理之后,自己写了一个函数出来。
现在分享一下代码。
现在越来越觉得C博客的好处,可以看到好多前辈分享的代码,大大缩短了自己掌握图像处理技巧的时间。
这种乐于分享的氛围,必将极大的促进技术的进步和革新。
本代码配置条件 opencv2.4.9+vs2013 应该其他版本的vs和opencv也可以跑起来
输入的srcimage为二值化后的图像,其中白色为要细化的特征
void chao_thinimage(Mat &srcimage)//单通道、二值化后的图像
{
vector<Point> deletelist1;
int Zhangmude[9];
int nl = srcimage.rows;
int nc = srcimage.cols;
while (true)
{
for (int j = 1; j<(nl - 1); j++)
{
uchar* data_last = srcimage.ptr<uchar>(j - 1);
uchar* data = srcimage.ptr<uchar>(j);
uchar* data_next = srcimage.ptr<uchar>(j + 1);
for (int i = 1; i<(nc - 1); i++)
{
if (data[i] == 255)
{
Zhangmude[0] = 1;
if (data_last[i] == 255) Zhangmude[1] = 1;
else Zhangmude[1] = 0;
if (data_last[i + 1] == 255) Zhangmude[2] = 1;
else Zhangmude[2] = 0;
if (data[i + 1] == 255) Zhangmude[3] = 1;
else Zhangmude[3] = 0;
if (data_next[i + 1] == 255) Zhangmude[4] = 1;
else Zhangmude[4] = 0;
if (data_next[i] == 255) Zhangmude[5] = 1;
else Zhangmude[5] = 0;
if (data_next[i - 1] == 255) Zhangmude[6] = 1;
else Zhangmude[6] = 0;
if (data[i - 1] == 255) Zhangmude[7] = 1;
else Zhangmude[7] = 0;
if (data_last[i - 1] == 255) Zhangmude[8] = 1;
else Zhangmude[8] = 0;
int whitepointtotal = 0;
for (int k = 1; k < 9; k++)
{
whitepointtotal = whitepointtotal + Zhangmude[k];
}
if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
{
int ap = 0;
if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
if (ap == 1)
{
if ((Zhangmude[1] * Zhangmude[7] * Zhangmude[5] == 0) && (Zhangmude[3] * Zhangmude[5] * Zhangmude[7] == 0))
{
deletelist1.push_back(Point(i, j));
}
}
}
}
}
}
if (deletelist1.size() == 0) break;
for (size_t i = 0; i < deletelist1.size(); i++)
{
Point tem;
tem = deletelist1[i];
uchar* data = srcimage.ptr<uchar>(tem.y);
data[tem.x] = 0;
}
deletelist1.clear();
for (int j = 1; j<(nl - 1); j++)
{
uchar* data_last = srcimage.ptr<uchar>(j - 1);
uchar* data = srcimage.ptr<uchar>(j);
uchar* data_next = srcimage.ptr<uchar>(j + 1);
for (int i = 1; i<(nc - 1); i++)
{
if (data[i] == 255)
{
Zhangmude[0] = 1;
if (data_last[i] == 255) Zhangmude[1] = 1;
else Zhangmude[1] = 0;
if (data_last[i + 1] == 255) Zhangmude[2] = 1;
else Zhangmude[2] = 0;
if (data[i + 1] == 255) Zhangmude[3] = 1;
else Zhangmude[3] = 0;
if (data_next[i + 1] == 255) Zhangmude[4] = 1;
else Zhangmude[4] = 0;
if (data_next[i] == 255) Zhangmude[5] = 1;
else Zhangmude[5] = 0;
if (data_next[i - 1] == 255) Zhangmude[6] = 1;
else Zhangmude[6] = 0;
if (data[i - 1] == 255) Zhangmude[7] = 1;
else Zhangmude[7] = 0;
if (data_last[i - 1] == 255) Zhangmude[8] = 1;
else Zhangmude[8] = 0;
int whitepointtotal = 0;
for (int k = 1; k < 9; k++)
{
whitepointtotal = whitepointtotal + Zhangmude[k];
}
if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
{
int ap = 0;
if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
if (ap == 1)
{
if ((Zhangmude[1] * Zhangmude[3] * Zhangmude[5] == 0) && (Zhangmude[3] * Zhangmude[1] * Zhangmude[7] == 0))
{
deletelist1.push_back(Point(i, j));
}
}
}
}
}
}
if (deletelist1.size() == 0) break;
for (size_t i = 0; i < deletelist1.size(); i++)
{
Point tem;
tem = deletelist1[i];
uchar* data = srcimage.ptr<uchar>(tem.y);
data[tem.x] = 0;
}
deletelist1.clear();
}
效果如下图所示