X-Git-Url: http://git.euphorik.ch/?p=master-thesis.git;a=blobdiff_plain;f=Parasitemia%2FParasitemia%2FMatchingEllipses.fs;h=afc4ab7b10c0cb4954c2206cf07238ae905ab1a8;hp=e4eae8dc192c30218aba070feabfda573e5af379;hb=dec96d50e56e1932bbfa09e6bedf90d6b707ccbd;hpb=ba64921fb9a0c36cd8cf802cbf1b2c0f79bc25f6 diff --git a/Parasitemia/Parasitemia/MatchingEllipses.fs b/Parasitemia/Parasitemia/MatchingEllipses.fs index e4eae8d..afc4ab7 100644 --- a/Parasitemia/Parasitemia/MatchingEllipses.fs +++ b/Parasitemia/Parasitemia/MatchingEllipses.fs @@ -2,55 +2,95 @@ open System open System.Linq +open System.Collections open System.Collections.Generic open Types open Utils -type EllipseScore = { mutable matchingScore: float; e: Ellipse } +let matchingScoreThreshold1 = 0.6 +let matchingScoreThreshold2 = 1.0 -let matchingScoreThreshold1 = 0.5 -let matchingScoreThreshold2 = 2.0 +type EllipseScore (matchingScore: float, e: Ellipse) = + let mutable matchingScore = matchingScore -let ellipseArea e = e.a * e.b * Math.PI + member this.MatchingScore = matchingScore + member this.Ellipse = e + member val Processed = false with get, set + member val Removed = false with get, set -type MatchingEllipses () = + member this.AddMatchingScore(score: float) = + matchingScore <- matchingScore + score + + interface KdTree.I2DCoords with + member this.X = e.Cx + member this.Y = e.Cy + +type MatchingEllipses (radiusMin: float) = let ellipses = List() member this.Add (e: Ellipse) = - - // dprintfn "new ellipse: %A, nb: %A" e ellipses.Count - - let areaE = ellipseArea e - - let mutable matchingScoreE = 0.0 + ellipses.Add(EllipseScore(0.0, e)) - 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 + member this.Ellipses : Ellipse list = + // 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 = radiusMin + for e in ellipses do + e.Processed <- true + let areaE = e.Ellipse.Area + let window = { KdTree.minX = e.Ellipse.Cx - windowSize / 2.0 + KdTree.maxX = e.Ellipse.Cx + windowSize / 2.0 + KdTree.minY = e.Ellipse.Cy - windowSize / 2.0 + KdTree.maxY = e.Ellipse.Cy + windowSize / 2.0 } + for other in KdTree.Tree.search tree window do + if not other.Processed + then + let areaOther = other.Ellipse.Area + let commonArea = EEOver.EEOverlapArea e.Ellipse other.Ellipse + let matchingScore = 2.0 * commonArea / (areaE + areaOther) + if matchingScore >= matchingScoreThreshold1 + then + other.AddMatchingScore(matchingScore) + e.AddMatchingScore(matchingScore) + + // 3) Sort ellipses by their score. + ellipses.Sort(fun e1 e2 -> e2.MatchingScore.CompareTo(e1.MatchingScore)) + + // 4) Remove ellipses wich have a low score. + let i = ellipses.BinarySearch(EllipseScore(matchingScoreThreshold2, Ellipse(0.0, 0.0, 0.0, 0.0, 0.0)), + { new IComparer with + member this.Compare(e1, e2) = e2.MatchingScore.CompareTo(e1.MatchingScore) }) |> abs + let nbToRemove = ellipses.Count - i + if nbToRemove > 0 + then + for j in i .. nbToRemove - 1 do + ellipses.[j].Removed <- true + ellipses.RemoveRange(i, nbToRemove) + + // 5) Remove ellipses whose center is into an ellipse with a better score + for e in ellipses do + if not e.Removed then - other.matchingScore <- other.matchingScore + matchingScore - matchingScoreE <- matchingScoreE + matchingScore - printfn "Score" - - ellipses.Add({ matchingScore = matchingScoreE; e = e }) + 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 KdTree.Tree.search tree window do + if not other.Removed && other.MatchingScore < e.MatchingScore + then + if e.Ellipse.Contains other.Ellipse.Cx other.Ellipse.Cy + then + other.Removed <- true + ellipses.RemoveAll(fun e -> e.Removed) |> ignore - 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) + List.ofSeq ellipses |> List.map (fun e -> e.Ellipse) - // ellipses.Where(fun e -> e.matchingScore >= matchingScoreThreshold2) - // ([], fun acc { matchingScore = score; e = e } -> if score >= matchingScoreThreshold2 then e :: acc else acc)