//根据上述细化算法,在OpenCV中采用3×3结构元素的细化代码如下:
//函数名称:Mat thinning()
//基本功能:对二值图像进行细化运算
//参数说明:待细化二值图像,该图像中背景色为0,前景色(目标)为255
//返回值:返回细化后二值图像
Mat thinning(Mat & binaryImg)
{
int i, j, k;
uchar p[11];
int pos[9][2] = { {0,0},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1, -1},{0, -1},{-1, -1} };
int condl, cond3, cond4,cond2=0, counter = 0;
bool pointsDeleted = true;
Mat mask, dstImg;
dstImg = binaryImg / 255; //转化为0.1二值图像
while (pointsDeleted) //若存在可删除像素点,执行迭代
{
mask = Mat::zeros(dstImg.size(), CV_8UC1); //初始化模板为全0
pointsDeleted = false;
for (i = 1;i < dstImg.rows - 1;i++)
{
for (j = 1;j < dstImg.cols - 1;j++)
// 获取3×3结构元素pl~p9对应像素值,其中pl为中心点
{
for (k = 1;k < 10;k++)
{
p[k] = dstImg.at<uchar>(i + pos[k - 1][0], j + pos[k - 1][1]);
}
if (p[1] == 0)continue; //若中心点为背景色(黑色),跳过
condl = 0; //计算中心点周囤所有像素值之和
for (k = 2;k < 10;k++)condl += p[k]; //计算p2~p9从0到1变化的次数
cond2 = 0;
p[10] = p[2]; //用于处理k=8,p[k+2]越界情况
for (k = 2;k < 10;k += 2)
cond2 += ((p[k] == 0 && p[k + 1] == 1) + (p[k + 1] == 0 && p[k + 2] == 1));
if (counter % 2 == 0) //偶数次选代判断条件
{
cond3 = p[2] * p[4] * p[6];
cond4 = p[4] * p[6] * p[8];
}
else //奇数次迭代判断条件
{
cond3 = p[2] * p[4] * p[8];
cond4 = p[2] * p[6] * p[8];
}
//若同时满足条件1~条件4
if ((2 <= condl && condl <= 6) && (cond2 == 1) && (cond3 == 0) && (cond4 == 0))
{
pointsDeleted= true;
mask.at<uchar>(i,j) = 1; // 写入待删除的像素点至模板
}
}
}
dstImg &= ~mask; //通过逻辑与操作删除目标像素点(白色)
counter ++; // 记录迭代次数
}
dstImg *= 255; //恢复为0 255 二值图像
return dstImg;
}
void Thinning()
{
//原图像名称
string Img_name = "C:/opencv/image/lena_gray8bit.bmp";
//载入源图像
Mat Src = imread(Img_name);
Mat src = Src.clone();
//灰度化
cvtColor(src, src, COLOR_RGB2GRAY);
Mat Img;
//二值化
threshold(src, Img, 128, 255, THRESH_BINARY_INV);
namedWindow("原始二值化图像", 0);
imshow("原始二值化图像", Img);
Mat dst=thinning(Img);
namedWindow("细化图像", 0);
imshow("细化图像", dst);
waitKey(0);
return;
}
代码来源:数字图像处理第三版(何东健)随书代码