- // 1) Remove ellipses touching the edges.
- let w = float fg.Width
- let h = float fg.Height
- let ellipsesInside = ellipses |> List.map (fun e -> EllipseFlaggedKd (e, Removed = e.isOutside w h))
-
- // 2) Associate touching ellipses with each ellipses.
- let tree = KdTree.Tree.BuildTree ellipsesInside
- let neighbors (e: Ellipse) : (EllipseFlaggedKd * PointD * PointD) list =
- tree.Search (searchRegion e)
- // We only keep the ellipses touching 'e'.
- |> List.choose (fun otherE ->
- match EEOver.EEOverlapArea e otherE with
- | Some (area, px, py) when area > 0.0 && px.Length >= 2 && py.Length >= 2 ->
- Some (otherE, PointD(px.[0], py.[0]), PointD(px.[1], py.[1]))
- | _ ->
- None )
-
- let ellipsesWithNeigbors = ellipsesInside |> List.choose (fun e -> if e.Removed then None else Some (e, neighbors e))
-
- // 3) Remove ellipses with a lower percentage of foreground.
- for e, neighbors in ellipsesWithNeigbors do
- let minX, minY, maxX, maxY = ellipseWindow e
-
- let mutable totalElement = 0
- let mutable fgElement = 0
- for y in minY .. maxY do
- for x in minX .. maxX do
- let yf, xf = float y, float x
- if e.Contains xf yf && neighbors |> List.forall (fun (otherE, _, _) -> not <| otherE.Contains xf yf)
+ let w = img.Width
+ let w_f = float w
+ let h = img.Height
+ let h_f = float h
+
+ // Return 'true' if the point 'p' is owned by e.
+ // The lines represents all intersections with other ellipses.
+ let pixelOwnedByE (p: PointD) (e: Ellipse) (others: (Ellipse * Line) list) =
+ e.Contains p.X p.Y &&
+ seq {
+ let c = PointD(e.Cx, e.Cy)
+ for e', d1 in others do
+ let d2 = Utils.lineFromTwoPoints c p
+ let c' = PointD(e'.Cx, e'.Cy)
+ let v = pointFromTwoLines d1 (lineFromTwoPoints c c')
+ let case1 = sign (v.X - c.X) <> sign (v.X - c'.X) || Utils.squaredDistanceTwoPoints v c > Utils.squaredDistanceTwoPoints v c'
+ if d2.Valid
+ then
+ let p' = Utils.pointFromTwoLines d1 d2
+ // Yield 'false' when the point is owned by another ellipse.
+ if case1