第二神奇----轮廓寻找(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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,我来给你展示一下用 Python 实现 α-shape 算法提取点云切片轮廓点的代码。 ```python import numpy as np from scipy.spatial import Delaunay def alpha_shape(points, alpha): """ 计算α-shape算法提取点云切片轮廓点 :param points: 点云数据,格式为 N x 3 的 numpy 数组,表示 N 个点的 x、y、z 坐标 :param alpha: 参数α,决定了α-shape的形态 :return: 轮廓点坐标,格式为 M x 3 的 numpy 数组,表示 M 个点的 x、y、z 坐标 """ # 构建 Delaunay 三角剖分 tri = Delaunay(points) # 计算每个三角形的外接圆半径 circum_radius = np.sqrt(np.sum((tri.points[tri.simplices][:, :, :] - tri.circumcenters[:, np.newaxis, :]) ** 2, axis=(1, 2))) # 根据参数 alpha,筛选出需要保留的三角形 edge_length = np.max(tri.transform[:, :2].dot((tri.points[tri.simplices][:, 1] - tri.points[tri.simplices][:, 0])[:, :2, :]), axis=1) keep = circum_radius < 1.0 / alpha * edge_length # 获取保留三角形的边界点 tri_points = tri.points[tri.simplices][keep] edges = np.concatenate((tri_points[:, :2], tri_points[:, 1:], tri_points[:, ::2]), axis=0) edge_points = edges[np.lexsort((edges[:, 1], edges[:, 0]))] edge_diff = np.diff(edge_points, axis=0) edges_idx = np.concatenate((np.array([0]), np.where(np.any(edge_diff, axis=1))[0] + 1, np.array([edge_points.shape[0]]))) # 获取边界点的坐标 contour_points = [] for i in range(edges_idx.shape[0] - 1): contour_points.append(edge_points[edges_idx[i]:edges_idx[i + 1]][0]) contour_points.append(edge_points[edges_idx[-1] - 1]) # 返回轮廓点坐标 return np.array(contour_points) ``` 使用方法: ```python # 生成一些随机的点云数据 points = np.random.rand(100, 3) # 计算轮廓contour_points = alpha_shape(points, 0.5) # 打印轮廓点坐标 print(contour_points) ``` 其中,`points` 是点云数据,格式为 N x 3 的 numpy 数组,表示 N 个点的 x、y、z 坐标;`alpha` 是参数α,决定了α-shape的形态;`contour_points` 是轮廓点坐标,格式为 M x 3 的 numpy 数组,表示 M 个点的 x、y、z 坐标。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值