第二神奇----轮廓寻找(contour find)算法(感兴趣区域(roi)变化为轮廓)

轮廓寻找算法建立在斑(blob)寻找基础之上,这个算法有参考杨淑莹的图像处理,有两个版本,第一版本c#代码如下:

 private void SingleTrack(ref byte[] image, int w, int h, ref List<Point> list, int i, int j, uint threshold)
        {
            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<Point> list, uint threshold)
        {
             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> list, int i, int j, uint threshold)//threshold //default=255
        {
            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<w&&ay>0&&ay<h)
                    if (image[ay * w + ax] == threshold)
                    {
                        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<List<Point>>();//此保存所有斑(blob)的轮廓
          
            for (int i = 0; i < glob_llp.Count; i++)//glob_llp为所有斑(blob),glob_llp[i][0]为所有斑的第一个点,它在边界上
            {
            List<Point> temp_singlefigure = new List<Point>();
            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不变矩的计算......等等,根据个人爱好和具体项目实践应用,任意想象,任意发挥。轮廓与斑,一对孪生姊妹,相辅相成,机器视觉处理基础必备。

待续(慢慢来!...........)每天一点小改变☺

我的邮箱liuganggang_1978@163.com;734523623@qq.com

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值