module ParasitemiaCore.MatchingEllipses
open System
+open System.Drawing
open System.Linq
open System.Collections
open System.Collections.Generic
open Types
open Utils
+// All ellipses with a score below this are removed.
+let matchingScoreThresholdPerRadiusUnit = 0.07f // For a radius of 1. // 0.25
+let matchingScorePower = 20.f
+let windowSizeRadiusFactor = 1.f / 2.f // Used when searching for neighbor ellipses.
+let minimumDistanceFromCenterRadiusFactor = 1.f / 3.f
+let minimumAreaFactor = 1.1f;
+
type private EllipseScoreFlaggedKd (matchingScore: float32, e: Ellipse) =
let mutable matchingScore = matchingScore
type MatchingEllipses (radius: float32) =
let ellipses = List<EllipseScoreFlaggedKd>()
- // All ellipses with a score below this are removed.
- let matchingScoreThreshold = 0.4f // 0.5f
-
member this.Add (e: Ellipse) =
ellipses.Add(EllipseScoreFlaggedKd(0.f, e))
let tree = KdTree.Tree.BuildTree (List.ofSeq ellipses)
// 2) Compute the matching score of each ellipses.
- let windowSize = radius / 2.f
+ let windowSize = radius * windowSizeRadiusFactor
for e in ellipses do
e.Processed <- true
let areaE = e.Ellipse.Area
| Some (overlapArea, _, _)
// Because of approximation error, see https://github.com/chraibi/EEOver/issues/4
when overlapArea - areaE < 1.f && overlapArea - areaOther < 1.f ->
- let matchingScore = (2.f * overlapArea / (areaE + areaOther)) ** 30.f
+ let matchingScore = (2.f * overlapArea / (areaE + areaOther)) ** matchingScorePower
other.AddMatchingScore(matchingScore)
e.AddMatchingScore(matchingScore)
| _ -> ()
// 3) Remove ellipses whose center is near the center of another ellipse with a better score.
+ let matchingScoreThreshold = matchingScoreThresholdPerRadiusUnit * radius
for e in ellipses do
if e.MatchingScore < matchingScoreThreshold
then
if not other.Removed && e.MatchingScore > other.MatchingScore
then
// Case where ellipses are too close.
- if distanceTwoPoints (PointF(e.Ellipse.Cx, e.Ellipse.Cy)) (PointF(other.Ellipse.Cx, other.Ellipse.Cy)) < 0.3f * e.Ellipse.B
+ if distanceTwoPoints (PointF(e.Ellipse.Cx, e.Ellipse.Cy)) (PointF(other.Ellipse.Cx, other.Ellipse.Cy)) < minimumDistanceFromCenterRadiusFactor * e.Ellipse.B
then
other.Removed <- true
else
// Case where ellipses are overlapped.
match EEOver.EEOverlapArea e.Ellipse other.Ellipse with
- | Some (overlapArea, _, _) when e.Ellipse.Area < 1.1f * overlapArea || other.Ellipse.Area < 1.1f * overlapArea ->
+ | Some (overlapArea, _, _) when e.Ellipse.Area < minimumAreaFactor * overlapArea || other.Ellipse.Area < minimumAreaFactor * overlapArea ->
other.Removed <- true
| _ ->
()