轮廓寻找算法建立在斑(blob)寻找基础之上,这个算法有参考杨淑莹的图像处理,有两个版本,第一版本c#代码如下:
private void SingleTrack(ref byte[] image, int w, int h, ref List
{
CPointNode1[] direct = new CPointNode1[8];
direct[0].x = 1; direct[0].y = 0;
direct[1].x = 1; direct[1].y = -1;
direct[2].x = 0; direct[2].y = -1;
direct[3].x = -1; direct[3].y = -1;
direct[4].x = -1; direct[4].y = 0;
direct[5].x = -1; direct[5].y = 1;
direct[6].x = 0; direct[6].y = 1;
direct[7].x = 1; direct[7].y = 1;
Point temppt = new Point();
int nx = i, ny = j; int indexindex = 0;
temppt.X = nx;
temppt.Y = ny;
list.Add(temppt);
do
{
indexindex = NextcontourPoint(ref image, w, h, nx, ny, indexindex, ref list, threshold);
if (indexindex == 9) break;
nx += direct[indexindex].x;
ny += direct[indexindex].y;
}
while (nx != i || ny != j);
}
private int NextcontourPoint(ref byte[] image, int w, int h, int i, int j, int entrelinkcode, ref List
{
CPointNode1[] direct = new CPointNode1[8];
direct[0].x = 1; direct[0].y = 0;
direct[1].x = 1; direct[1].y = -1;
direct[2].x =0; direct[2].y = -1;
direct[3].x = -1; direct[3].y = -1;
direct[4].x = -1; direct[4].y = 0;
direct[5].x = -1; direct[5].y = 1;
direct[6].x = 0; direct[6].y = 1;
direct[7].x = 1; direct[7].y = 1;
int startindex = entrelinkcode + 3 + 8;
// int i = 0;
for (int ii = 0; ii <= 7; ii++)
{
int indexindex = (startindex - ii) % 8;
int nx = i + direct[indexindex].x;
int ny = j + direct[indexindex].y;
if (image[nx * w + ny] == threshold)
{
Point temppt = new Point();
temppt.X = nx;
temppt.Y = ny;
list.Add(temppt);
return indexindex;
}
}
return 9;
}
第二版本c#代码如下:
private void FindContinueFigure2(ref byte[] image, int w, int h, ref List
{
Point startpoint = new Point();
Point currentpoint = new Point();
CPointNode1[] direct = new CPointNode1[8];
direct[0].x = -1; direct[0].y = 1;
direct[1].x = -1; direct[1].y = 0;
direct[2].x = -1; direct[2].y = -1;
direct[3].x = 0; direct[3].y = -1;
direct[4].x = 1; direct[4].y = -1;
direct[5].x = 1; direct[5].y = 0;
direct[6].x = 1; direct[6].y = 1;
direct[7].x = 0; direct[7].y = 1;
int startdirect = 3;
bool findstartpoint = false;
Point temppt = new Point();
temppt.X = startpoint.X = i;
temppt.Y = startpoint.Y = j;
list.Add(temppt);
currentpoint.X = startpoint.X;
currentpoint.Y = startpoint.Y;
while (!findstartpoint)
{
bool findpoint = false;
while (!findpoint)
{
int ay = (currentpoint.Y + direct[startdirect].y);
int ax=currentpoint.X + direct[startdirect].x;
// if(ax>0&&ax
{
findpoint = true;
// image[(currentpoint.Y + direct[startdirect].y) * w + currentpoint.X + direct[startdirect].x] = 0;
temppt.X = currentpoint.X = currentpoint.X + direct[startdirect].x;
temppt.Y = currentpoint.Y = currentpoint.Y + direct[startdirect].y;
list.Add(temppt);
if (currentpoint.X == startpoint.X &&
currentpoint.Y == startpoint.Y)
{
findstartpoint = true;
}
startdirect--;
if (startdirect == -1)
startdirect = 7;
startdirect--;
if (startdirect == -1)
startdirect = 7;
}
else
{
startdirect++;
if (startdirect == 8)
startdirect = 0;
}
}
}
}
public struct CPointNode1
{
public int x;
public int y;
};
调用如下:
singlefigureSS = new List>();//此保存所有斑(blob)的轮廓
for (int i = 0; i < glob_llp.Count; i++)//glob_llp为所有斑(blob),glob_llp[i][0]为所有斑的第一个点,它在边界上。
{
List
FindContinueFigure2(ref tempallimage8, Con_W, Con_H, //原图像和宽,高.
ref temp_singlefigure,//返回每个斑(blob)的轮廓
glob_llp[i][0].X, glob_llp[i][0].Y, 240);//threshold,门槛值(小时候,家里老房子的门槛高的望而生畏,现在一去不复返)
singlefigureSS.Add(temp_singlefigure);
}
第二版效果图:
考虑为什么会使用第二版本?答案是,第一版本极少数的结果让人惊诧,明明有轮廓,却只找到一个小圈圈,用了一两年才发现(因为 只是偶尔偶尔偶尔出现),不知道是什么原因,后来又参考左飞的数字图像处理,才发现是进入链码的值不对导致的。
关于斑和轮廓不想再立篇探讨匹配的应用了,因为在这两篇中,斑和轮廓已经为你提供了用来匹配的足够多的信息特征,关于质心,周长,面积,最远矩,最短矩,凸多边形,外接圆,外接矩形,外接椭圆,以及Hu不变矩的计算......等等,根据个人爱好和具体项目实践应用,任意想象,任意发挥。轮廓与斑,一对孪生姊妹,相辅相成,机器视觉处理基础必备。
待续(慢慢来!...........)每天一点小改变☺