细化算法:
假设某图像中的一个3*3区域,对其中各点标记名称P1,P2,P3...P9,分布如下:
P3 P2 P9
P4 P1 P8
P5 P6 P7
这里假设1表示黑色,0表示白色,且中心P1=1(黑色),那么,在同时满足以下4个条件时就删除P1(令P1=0):
(1) 7>NZ(P1)>1;
(2) Z0(P1)=1;
(3) P2*P4*P6=0 OR Z0(P2)!=1;
(4) P2*P4*P8=0 OR Z0(P4)!=1;
其中的NZ(P)表示P点的8领域中1的数目;而Z0(P)可按如下方式计算:
Set ncount=1;
if P2=0 and P3=1, then ncount++;
if P3=0 and P4=1, then ncount++;
if P4=0 and P5=1, then ncount++;
if P5=0 and P6=1, then ncount++;
if P6=0 and P7=1, then ncount++;
if P7=0 and P8=1,then ncount++;
if P8=0 and P9=1,then ncount++;
if P9=0 and P2=1,then ncount++;
Z0(P)=ncount;
#include <iostream>
#include "cv.h"
#include "highgui.h"
using namespace std;
using namespace cv;
Mat ThinImage(Mat img)
{
int i,j,count,ncount;
for (i=2;i<img.rows-2;i++)
{
for (j=2;j<img.cols-2;j++)
{
if(img.at<uchar>(i,j)==255)
{
bool condition1=false,
condition2=false,
condition3=false,
condition4=false;
//count P(i,j) around #1
count=0;
if(img.at<uchar>(i-1,j-1)==255)
count++;
if(img.at<uchar>(i-1,j)==255)
count++;
if(img.at<uchar>(i-1,j+1)==255)
count++;
if(img.at<uchar>(i,j-1)==255)
count++;
if(img.at<uchar>(i,j+1)==255)
count++;
if(img.at<uchar>(i+1,j-1)==255)
count++;
if(img.at<uchar>(i+1,j)==255)
count++;
if(img.at<uchar>(i+1,j+1)==255)
count++;
if(count<7&&count>1)
condition1=true;
//compute ncount
ncount=0;
if(img.at<uchar>(i-1,j)==0&&img.at<uchar>(i-1,j-1)==255)
ncount++;
if(img.at<uchar>(i-1,j-1)==0&&img.at<uchar>(i,j-1)==255)
ncount++;
if(img.at<uchar>(i,j-1)==0&&img.at<uchar>(i+1,j-1)==255)
ncount++;
if(img.at<uchar>(i+1,j-1)==0&&img.at<uchar>(i+1,j)==255)
ncount++;
if(img.at<uchar>(i+1,j)==0&&img.at<uchar>(i+1,j+1)==255)
ncount++;
if(img.at<uchar>(i+1,j+1)==0&&img.at<uchar>(i,j+1)==255)
ncount++;
if(img.at<uchar>(i,j+1)==0&&img.at<uchar>(i-1,j+1)==255)
ncount++;
if(img.at<uchar>(i-1,j+1)==0&&img.at<uchar>(i-1,j)==255)
ncount++;
if(ncount==1)
condition2=true;
if (img.at<uchar>(i-1,j)*img.at<uchar>(i,j-1)*img.at<uchar>(i,j+1)==0)
condition3=true;
else
{
ncount=0;
i-=1;
if(img.at<uchar>(i-1,j)==0&&img.at<uchar>(i-1,j-1)==255)
ncount++;
if(img.at<uchar>(i-1,j-1)==0&&img.at<uchar>(i,j-1)==255)
ncount++;
if(img.at<uchar>(i,j-1)==0&&img.at<uchar>(i+1,j-1)==255)
ncount++;
if(img.at<uchar>(i+1,j-1)==0&&img.at<uchar>(i+1,j)==255)
ncount++;
if(img.at<uchar>(i+1,j)==0&&img.at<uchar>(i+1,j+1)==255)
ncount++;
if(img.at<uchar>(i+1,j+1)==0&&img.at<uchar>(i,j+1)==255)
ncount++;
if(img.at<uchar>(i,j+1)==0&&img.at<uchar>(i-1,j+1)==255)
ncount++;
if(img.at<uchar>(i-1,j+1)==0&&img.at<uchar>(i-1,j)==255)
ncount++;
if(ncount!=1)
condition3=true;
i+=1;
}
if (img.at<uchar>(i-1,j)*img.at<uchar>(i,j-1)*img.at<uchar>(i+1,j)==0)
condition4=true;
else
{
ncount=0;
j-=1;
if(img.at<uchar>(i-1,j)==0&&img.at<uchar>(i-1,j-1)==255)
ncount++;
if(img.at<uchar>(i-1,j-1)==0&&img.at<uchar>(i,j-1)==255)
ncount++;
if(img.at<uchar>(i,j-1)==0&&img.at<uchar>(i+1,j-1)==255)
ncount++;
if(img.at<uchar>(i+1,j-1)==0&&img.at<uchar>(i+1,j)==255)
ncount++;
if(img.at<uchar>(i+1,j)==0&&img.at<uchar>(i+1,j+1)==255)
ncount++;
if(img.at<uchar>(i+1,j+1)==0&&img.at<uchar>(i,j+1)==255)
ncount++;
if(img.at<uchar>(i,j+1)==0&&img.at<uchar>(i-1,j+1)==255)
ncount++;
if(img.at<uchar>(i-1,j+1)==0&&img.at<uchar>(i-1,j)==255)
ncount++;
if(ncount!=1)
condition4=true;
j+=1;
}
if(condition1&&condition2&&condition3&&condition4==true)
img.at<uchar>(i,j)=0;
}
}
}
imshow("ThinImage",img);
waitKey();
return img;
}
细节:
注意环境复原,i,j 的处理,否则会进入死循环!
参考:
《数字图像处理与机器视觉》(人民邮电出版社)
(新手上路,如有错误或不够优化的地方请大方指出,共同提高!)