X-Git-Url: http://git.euphorik.ch/?a=blobdiff_plain;f=Parasitemia%2FParasitemia%2FMatchingEllipses.fs;h=3599bb5471742bb2711378d4baab8bfe16d21523;hb=48ecdfc43001c444eff6ad442986049384674af2;hp=e4eae8dc192c30218aba070feabfda573e5af379;hpb=ba64921fb9a0c36cd8cf802cbf1b2c0f79bc25f6;p=master-thesis.git diff --git a/Parasitemia/Parasitemia/MatchingEllipses.fs b/Parasitemia/Parasitemia/MatchingEllipses.fs index e4eae8d..3599bb5 100644 --- a/Parasitemia/Parasitemia/MatchingEllipses.fs +++ b/Parasitemia/Parasitemia/MatchingEllipses.fs @@ -2,56 +2,90 @@ open System open System.Linq +open System.Collections open System.Collections.Generic open Types open Utils +type private EllipseScoreFlaggedKd (matchingScore: float32, e: Ellipse) = + let mutable matchingScore = matchingScore -type EllipseScore = { mutable matchingScore: float; e: Ellipse } + member this.Ellipse = e -let matchingScoreThreshold1 = 0.5 -let matchingScoreThreshold2 = 2.0 + member this.MatchingScore = matchingScore -let ellipseArea e = e.a * e.b * Math.PI + member this.AddMatchingScore (score: float32) = + matchingScore <- matchingScore + score -type MatchingEllipses () = - let ellipses = List() - - member this.Add (e: Ellipse) = - - // dprintfn "new ellipse: %A, nb: %A" e ellipses.Count + member val Processed = false with get, set + member val Removed = false with get, set - let areaE = ellipseArea e + interface KdTree.I2DCoords with + member this.X = this.Ellipse.Cx + member this.Y = this.Ellipse.Cy - let mutable matchingScoreE = 0.0 +type MatchingEllipses (radius: float32) = + let ellipses = List() - for other in ellipses do - let areaOther = ellipseArea other.e - let commonArea = EEOver.EEOverlapArea e other.e - let matchingScore = (2.0 * commonArea / (areaE + areaOther)) ** 2.0 - if matchingScore >= matchingScoreThreshold1 - then - other.matchingScore <- other.matchingScore + matchingScore - matchingScoreE <- matchingScoreE + matchingScore - printfn "Score" + // All ellipses with a score below this are removed. + let matchingScoreThreshold = 1.f - ellipses.Add({ matchingScore = matchingScoreE; e = e }) + member this.Add (e: Ellipse) = + ellipses.Add(EllipseScoreFlaggedKd(0.f, e)) member this.Ellipses : Ellipse list = - dprintfn "Number of ellipse: %A" ellipses.Count - - (*let sortedEllipses = - List.filter (fun e -> e.matchingScore >= matchingScoreThreshold2) (List.ofSeq ellipses) - |> List.sortWith (fun e1 e2 -> e2.matchingScore.CompareTo(e1.matchingScore))*) - - List.filter (fun e -> e.matchingScore >= matchingScoreThreshold2) (List.ofSeq ellipses) - |> List.sortWith (fun e1 e2 -> e2.matchingScore.CompareTo(e1.matchingScore)) - |> List.map (fun { e = e } -> e) - - // ellipses.Where(fun e -> e.matchingScore >= matchingScoreThreshold2) - // ([], fun acc { matchingScore = score; e = e } -> if score >= matchingScoreThreshold2 then e :: acc else acc) - - - + List.ofSeq ellipses |> List.map (fun e -> e.Ellipse) + + member this.PrunedEllipses : Ellipse list = + if ellipses.Count = 0 + then + [] + else + // 1) Create a kd-tree from the ellipses list. + let tree = KdTree.Tree.BuildTree (List.ofSeq ellipses) + + // 2) Compute the matching score of each ellipses. + let windowSize = radius / 2.f + for e in ellipses do + e.Processed <- true + let areaE = e.Ellipse.Area + let window = { KdTree.minX = e.Ellipse.Cx - windowSize / 2.f + KdTree.maxX = e.Ellipse.Cx + windowSize / 2.f + KdTree.minY = e.Ellipse.Cy - windowSize / 2.f + KdTree.maxY = e.Ellipse.Cy + windowSize / 2.f } + for other in tree.Search window do + if not other.Processed + then + let areaOther = other.Ellipse.Area + match EEOver.EEOverlapArea e.Ellipse other.Ellipse with + | Some (overlapArea, _, _) -> + let matchingScore = (2.f * overlapArea / (areaE + areaOther)) ** 20.f + if matchingScore <= 1.f // For approximation error. + then + other.AddMatchingScore(matchingScore) + e.AddMatchingScore(matchingScore) + | _ -> () + + // 3) Remove ellipses whose center is near the center of another ellipse with a better score. + for e in ellipses do + if e.MatchingScore < matchingScoreThreshold + then + e.Removed <- true + else + let window = { KdTree.minX = e.Ellipse.Cx - e.Ellipse.A + KdTree.maxX = e.Ellipse.Cx + e.Ellipse.A + KdTree.minY = e.Ellipse.Cy - e.Ellipse.A + KdTree.maxY = e.Ellipse.Cy + e.Ellipse.A } + for other in tree.Search window do + if not other.Removed && e.MatchingScore > other.MatchingScore && + distanceTwoPoints (PointD(e.Ellipse.Cx, e.Ellipse.Cy)) (PointD(other.Ellipse.Cx, other.Ellipse.Cy)) < 0.3f * e.Ellipse.B + then + other.Removed <- true + + ellipses + |> List.ofSeq + |> List.filter (fun e -> not e.Removed) + |> List.sortWith (fun e1 e2 -> e2.MatchingScore.CompareTo(e1.MatchingScore)) + |> List.map (fun e -> e.Ellipse)