形态学之凸壳

到目前为止我还没有应用到凸壳,但是凸壳算法倒是接触过几个,这里简单写写形态学凸壳。

凸壳的公式如下:
X k i = ( X k − 1 ⊗ B i ) ∪ A i = 1 , 2 , 3 , 4 k = 1 , 2 , 3... X_k^i=(X_{k-1}\otimes B^i)\cup A \quad i=1,2,3,4 \quad k=1,2,3... Xki=(Xk1Bi)Ai=1,2,3,4k=1,2,3...
其中 X 0 i = A X_0^i=A X0i=A。当该过程收敛时(即当 X k i = X k − 1 i X_k^i=X_{k-1}^i Xki=Xk1i时),我们另 D i = X k i D^i=X_k^i Di=Xki,则A的凸壳为:
C ( A ) = ∪ i − 1 4 D i C(A)=\cup^4_{i-1}D^i C(A)=i14Di

说实话,我刚看到这个公式的时候是懵逼的,但是结合下面的图就很简单理解了。
在这里插入图片描述
我们首先有四个不同的element B i B_i Bi,我们首先用到第一个 B 1 B_1 B1 X 0 1 X_0^1 X01( X 0 1 X_0^1 X01等于A)做击中击不中变换,然后与A做并集,得到 X 1 1 X_1^1 X11然后迭代直到 X k i = X k − 1 i X_k^i=X_{k-1}^i Xki=Xk1i,我们停止迭代,计最终结果为 D 1 D_1 D1即上图的 X 4 1 X_4^1 X41,同理我们用其他的三个element B i B_i Bi得到 D 2 , D 3 , D 4 D_2,D_3,D_4 D2,D3,D4,最后将这四个D求并集就得到了我们的凸包。

注:用 B i B_i Bi做击中击不中变换的结果是我们值得注意的,这四个结构元的远点均在其中心处,“×”项表示“不考虑”的条件,即当A中的一个33区域的中心为0时,而在阴影模板元素下的三个像素为1时,就出现了一个模板匹配。出现模板匹配时,这个33区域的0中心将会被选中,这样就填补了本来是0的孔洞区域,然后与A求并,就将A的范围变大了。当这四个模板不能够更新出新的像素时,那么凸包就形成了。

缺点:上述过程的一个明显缺点是凸壳可能超出确保凸性所需的最小尺寸。减少这种影响的一种简单方法是限制生长,以便凸壳不会超过初始点集在水平和垂直方向的尺寸。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
凸壳(Convex Hull)算法是计算几何中的一类基本问题,它的目标是找到一个点集的最小凸多边形。Java实现凸壳算法的思路大致如下: 1. 首先,我们需要定义一个点的数据结构来存储点的坐标信息。可以使用Java中的Point2D类或者自定义一个Point类。 2. 然后,我们需要找到点集中最左边的点,将其作为凸壳的起点。 3. 接着,我们需要按照极角排序将剩余的点按照与起点的极角从小到大排序。 4. 然后,我们可以开始构建凸壳。我们可以使用一个栈来维护凸壳的点集。首先将起点和极角最小的点入栈。 5. 对于剩余的点,我们需要判断它是否在凸壳的内部。如果在内部,则将栈顶元素出栈,直到该点不在凸壳内部为止。 6. 最后,将该点入栈。 7. 重复步骤5和6,直到所有点都被处理完毕。 8. 最后,栈中的点集就是凸壳的点集。 下面是Java代码示例: ```java import java.util.*; public class ConvexHull { // 定义点的数据结构 static class Point { double x; double y; public Point(double x, double y) { this.x = x; this.y = y; } } public static List<Point> convexHull(List<Point> points) { // 找到最左边的点,作为凸壳的起点 Point start = points.get(0); for (Point p : points) { if (p.x < start.x) { start = p; } } // 按照极角排序 Collections.sort(points, new Comparator<Point>() { @Override public int compare(Point p1, Point p2) { double angle1 = Math.atan2(p1.y - start.y, p1.x - start.x); double angle2 = Math.atan2(p2.y - start.y, p2.x - start.x); if (angle1 < angle2) { return -1; } else if (angle1 > angle2) { return 1; } else { return 0; } } }); // 构建凸壳 Stack<Point> stack = new Stack<>(); stack.push(start); for (int i = 1; i < points.size(); i++) { Point p = points.get(i); while (stack.size() >= 2) { Point top = stack.pop(); Point secondTop = stack.peek(); if ((p.x - secondTop.x) * (top.y - secondTop.y) - (p.y - secondTop.y) * (top.x - secondTop.x) >= 0) { stack.push(top); break; } } stack.push(p); } // 将栈中的点集转换为List返回 List<Point> result = new ArrayList<>(); while (!stack.isEmpty()) { result.add(stack.pop()); } Collections.reverse(result); return result; } public static void main(String[] args) { List<Point> points = new ArrayList<>(); points.add(new Point(0, 0)); points.add(new Point(0, 1)); points.add(new Point(1, 1)); points.add(new Point(1, 0)); points.add(new Point(0.5, 0.5)); List<Point> hull = convexHull(points); for (Point p : hull) { System.out.println(p.x + " " + p.y); } } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值