取图像的骨架,方法是不断对图像进行腐蚀并且标记每个像素腐蚀到值不再变化的次数。得到的图像可以进一步被利用,如进行细化。
上代码
void erode(LPBYTE lpDst, LPBYTE lpDst1, int nW, int nH)
{
bool flag;
for (int j = 0; j < nH; j++)
{
for (int i = 0; i < nW; i++)
{
//目标图像中的当前点先赋成白色
lpDst[j*nW + i] = (unsigned char)255;//前景为黑色,背景为白色
if (lpDst1[j*nW + i] == 0)
{
flag = true;
for (int sub_row = -1; sub_row < 2; sub_row++)
{
for (int sub_col = -1; sub_col < 2; sub_col++)
{
if (j + sub_row < nH&&j + sub_row >= 0 && i + sub_col < nW&&i + sub_col >= 0)
{
if (lpDst1[(j + sub_row)*nW + i + sub_col] != 0)
{
flag = false; break;
}
}
}
if (!flag)
break;
}
if (flag)
lpDst[j*nW + i] = 0;
}
}
}
for (int j = 0; j < nH; j++)
{
for (int i = 0; i < nW; i++)
{
lpDst1[j*nW + i] = lpDst[j*nW + i];
}
}
}
void CImageColorProcess::DistanceTransform(LPBYTE lpSrc, LPBYTE lpDst, LPBYTE lpDst_, int nSrcCount, int nW, int nH)
{
this->OSTUThreshold(lpSrc, lpDst_, nSrcCount, nW, nH);
int*array = new int[nW*nH];//存储每个像素点被腐蚀掉之前所经历的腐蚀次数
//memset(array, 255, nW*nH);//初始化
for (int j = 0; j < nH; j++)
{
for (int i = 0; i < nW; i++)
{
array[j*nW + i] = 255;
}
}
bool flag1 = true;//设置标志
int count(0);//记录腐蚀操作的次数
while (flag1)
{
erode(lpDst, lpDst_, nW, nH);//标记为真进行腐蚀
for (int j = 0; j < nH; j++)
{
for (int i = 0; i < nW; i++)
{
if (lpDst[j*nW + i] == 0)
array[j*nW + i] = array[j*nW + i]-5;
}
}
for (int j = 0; j < nH; j++)
{
flag1 = false;
for (int i = 0; i < nW; i++)
{
if (lpDst[j*nW + i] == 0)
{
flag1 = true;
count++;
break;
}
}
if (flag1)
break;
}
}
for (int j = 0; j < nH; j++)
{
for (int i = 0; i < nW; i++)
{
lpDst[j*nW + i] = (array[j*nW + i] < 0 ? 0 : array[j*nW + i]);
}
}
}
还可以继续优化下
调试的时候最开始用memset初始化,总得不到结果,改成两个for循环初始化后问题解决,后来明白memset只能初始化为0