X-Git-Url: http://git.euphorik.ch/?p=master-thesis.git;a=blobdiff_plain;f=Parasitemia%2FParasitemia%2FClassifier.fs;h=3ed42f0e2ff5800bf940526d3f7bc7b4d8bbd523;hp=37507c5e927c1b685c5bd3a541afd4ec57821608;hb=b070295cf67b2025164a34b6594e84f0d771cdc9;hpb=e76da913cd58078ad2479357b2430ed62a6e0777 diff --git a/Parasitemia/Parasitemia/Classifier.fs b/Parasitemia/Parasitemia/Classifier.fs index 37507c5..3ed42f0 100644 --- a/Parasitemia/Parasitemia/Classifier.fs +++ b/Parasitemia/Parasitemia/Classifier.fs @@ -40,12 +40,13 @@ let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker.Result) (fg: let a = int (e.A + 0.5) cx - a, cy - a, cx + a, cy + a - // 1) Remove ellipses touching the edges. - let ellipsesInside = ellipses |> List.map (fun e -> - EllipseFlaggedKd (e, Removed = e.isOutside (float fg.Width) (float fg.Height))) + let w = float fg.Width + let h = float fg.Height - // 2) Associate touching ellipses with each ellipses. - let tree = KdTree.Tree.BuildTree ellipsesInside + let ellipses = ellipses |> List.map EllipseFlaggedKd + + // 1) Associate touching ellipses with each ellipses. + let tree = KdTree.Tree.BuildTree ellipses let neighbors (e: Ellipse) : (EllipseFlaggedKd * PointD * PointD) list = tree.Search (searchRegion e) // We only keep the ellipses touching 'e'. @@ -56,31 +57,53 @@ let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker.Result) (fg: | _ -> None ) - let ellipsesWithNeigbors = ellipsesInside |> List.choose (fun e -> if e.Removed then None else Some (e, neighbors e)) + let ellipsesWithNeigbors = ellipses |> List.choose (fun e -> if e.Removed then None else Some (e, neighbors e)) - // 3) Remove ellipse with a lower percentage of foreground. - let fgData = fg.Data - for e, neighbors in ellipsesWithNeigbors do + // 2) Remove ellipses with a lower percentage of foreground. (taken from the lower score to the highest). + for e, neighbors in List.rev 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 + for y in (if minY < 0 then 0 else minY) .. (if maxY >= fg.Height then fg.Height - 1 else maxY) do + for x in (if minX < 0 then 0 else minX) .. (if maxX >= fg.Width then fg.Width - 1 else maxX) do let yf, xf = float y, float x - if e.Contains xf yf && neighbors |> List.forall (fun (otherE, _, _) -> not <| otherE.Contains xf yf) - then - totalElement <- totalElement + 1 - if fgData.[y, x, 0] > 0uy + if e.Contains xf yf && neighbors |> List.forall (fun (otherE, _, _) -> otherE.Removed || not <| otherE.Contains xf yf) then - fgElement <- fgElement + 1 + totalElement <- totalElement + 1 + if fg.Data.[y, x, 0] > 0uy + then + fgElement <- fgElement + 1 - if totalElement < config.minimumCellArea || (float fgElement) / (float totalElement) < config.percentageOfFgValidCell + if (float fgElement) / (float totalElement) < config.percentageOfFgValidCell then e.Removed <- true - // 3) Define pixels associated to each ellipse and create the cells. + // 3) Remove ellipses touching the edges. + for e in ellipses do + if e.isOutside w h then e.Removed <- true + + // 4) Remove ellipses with little area. + for e, neighbors in ellipsesWithNeigbors do + if not e.Removed + then + let minX, minY, maxX, maxY = ellipseWindow e + + let mutable area = 0 + for y in (if minY < 0 then 0 else minY) .. (if maxY >= fg.Height then fg.Height - 1 else maxY) do + for x in (if minX < 0 then 0 else minX) .. (if maxX >= fg.Width then fg.Width - 1 else maxX) do + let yf, xf = float y, float x + if fg.Data.[y, x, 0] > 0uy && + e.Contains xf yf && + neighbors |> List.forall (fun (otherE, _, _) -> otherE.Removed || not <| otherE.Contains xf yf) + then + area <- area + 1 + + if area < config.minimumCellArea + then + e.Removed <- true + + // 5) Define pixels associated to each ellipse and create the cells. // Return 'true' if the point 'p' is owned by e. // The lines represents all intersections with other ellipses. @@ -94,7 +117,6 @@ let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker.Result) (fg: yield sign (c.X - p.X) <> sign (c.X - p'.X) || Utils.squaredDistanceTwoPoints c p' > Utils.squaredDistanceTwoPoints c p // 'false' -> the point is owned by another ellipse. } |> Seq.forall id - ellipsesWithNeigbors |> List.choose (fun (e, neighbors) -> if e.Removed