--- /dev/null
+module Classifier
+
+open System
+open System.Drawing
+
+open Emgu.CV
+open Emgu.CV.Structure
+
+
+type CellClass = HealthyRBC | InfectedRBC | Peculiar
+
+type Cell = {
+ cellClass: CellClass
+ center: Point
+ elements: Matrix<byte> }
+
+let findCells (ellipses: Types.Ellipse list) (parasites: ParasitesMarker.Result) (fg: Image<Gray, byte>) : Cell list =
+ []
\ No newline at end of file
quad ()
-
-let EEOverlapArea (e1: Types.Ellipse) (e2: Types.Ellipse) : float =
+// Return a tuple (area, x intersections, y intersections)
+let EEOverlapArea (e1: Types.Ellipse) (e2: Types.Ellipse) : (float * float[] * float[]) option =
let h1, k1, a1, b1, phi_1 = e1.Cx, e1.Cy, e1.A, e1.B, e1.Alpha
let h2, k2, a2, b2, phi_2 = e2.Cx, e2.Cy, e2.A, e2.B, e2.Alpha
if a1 <= EPS || b1 <= EPS || a2 <= EPS || b2 <= EPS
then
- -1.0
+ None
else
let phi_1 = phi_1 % Math.PI
let phi_2 = phi_2 % Math.PI
if returnValue = -1.0
then
- returnValue
+ None
else
- match nintpts with
- | 0 | 1 -> nointpts a1 b1 a2 b2 h1 k1 h2 k2 phi_1 phi_2 h2_tr k2_tr aa bb cc dd ee ff
- | 2 -> match istanpt xint.[0] yint.[0] a1 b1 aa bb cc dd ee ff with
- | TANGENT_POINT ->
+ let area =
+ match nintpts with
+ | 0 | 1 -> nointpts a1 b1 a2 b2 h1 k1 h2 k2 phi_1 phi_2 h2_tr k2_tr aa bb cc dd ee ff
+ | 2 -> match istanpt xint.[0] yint.[0] a1 b1 aa bb cc dd ee ff with
+ | TANGENT_POINT ->
#if DEBUG_LOG
- printf "one point is tangent\n"
+ printf "one point is tangent\n"
#endif
- nointpts a1 b1 a2 b2 h1 k1 h2 k2 phi_1 phi_2 h2_tr k2_tr aa bb cc dd ee ff
+ nointpts a1 b1 a2 b2 h1 k1 h2 k2 phi_1 phi_2 h2_tr k2_tr aa bb cc dd ee ff
- | INTERSECTION_POINT ->
+ | INTERSECTION_POINT ->
#if DEBUG_LOG
- printf "check twointpts\n"
+ printf "check twointpts\n"
#endif
- twointpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
- | 3 -> threeintpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
- | 4 -> fourintpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
- | _ -> -1.0
+ twointpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
+ | 3 -> threeintpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
+ | 4 -> fourintpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
+ | _ -> -1.0
+ Some (area, xint.[..nintpts-1], yint.[..nintpts-1])
\ No newline at end of file
open Config
open Types
-type Result = {
+(*type Result = {
RBCPositions : Point list
infectedRBCPositions : Point list
img: Image<Bgr, byte>
-}
+}*)
-let doAnalysis (img: Image<Bgr, byte>) (config: Config) : Result =
+let doAnalysis (img: Image<Bgr, byte>) (config: Config) : Classifier.Cell list =
let imgFloat = img.Convert<Bgr, float32>()
use scaledImg = if config.scale = 1.0 then imgFloat else imgFloat.Resize(config.scale, CvEnum.Inter.Area)
use magnitudesByte = ((magnitudes / !max) * 255.0).Convert<byte>() // Otsu from OpenCV only support 'byte'.
use edges = new Matrix<byte>(xEdges.Size)
- let threshold = CvInvoke.Threshold(magnitudesByte, edges, 0.0, 1.0, CvEnum.ThresholdType.Otsu ||| CvEnum.ThresholdType.Binary)
-
-// let filteredGreenMat = new Matrix<float32>(filteredGreen.Size)
-// filteredGreen.CopyTo(filteredGreenMat)
- let parasites = ParasitesMarker.find green filteredGreen config
-
- saveImg parasites.darkStain "parasites_dark_stain.png"
- saveImg parasites.stain "parasites_stain.png"
- saveImg parasites.infection "parasites_infection.png"
-
+ CvInvoke.Threshold(magnitudesByte, edges, 0.0, 1.0, CvEnum.ThresholdType.Otsu ||| CvEnum.ThresholdType.Binary) |> ignore
+
logTime "Finding edges" (fun() ->
thin edges)
saveMat (edges * 255.0) "edges.png"
+
+ let kmediansResults = KMedians.kmedians filteredGreen 1.0
+
+ let parasites = ParasitesMarker.find green filteredGreen kmediansResults config
+
+ saveImg parasites.darkStain "parasites_dark_stain.png"
+ saveImg parasites.stain "parasites_stain.png"
+ saveImg parasites.infection "parasites_infection.png"
+
let radiusRange = config.scale * 20.0, config.scale * 40.0
let windowSize = roundInt (1.6 * (snd radiusRange))
let factorNbPick = 1.5
drawEllipses img ellipses (Bgr(0.0, 255.0, 255.0))
//saveImg img "ellipses.png"
- { RBCPositions = []; infectedRBCPositions = []; img = img }
+ Classifier.findCells ellipses parasites kmediansResults.fg
//
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)
+ match EEOver.EEOverlapArea e.Ellipse other.Ellipse with
+ | Some (commonArea, _, _) ->
+ 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))
<Compile Include="Types.fs" />
<Compile Include="ImgTools.fs" />
<Compile Include="Config.fs" />
+ <Compile Include="KMedians.fs" />
<Compile Include="EEOver.fs" />
+ <Compile Include="ParasitesMarker.fs" />
<Compile Include="KdTree.fs" />
+ <Compile Include="Classifier.fs" />
<Compile Include="MatchingEllipses.fs" />
<Compile Include="Ellipse.fs" />
- <Compile Include="KMedians.fs" />
- <Compile Include="ParasitesMarker.fs" />
<Compile Include="ImageAnalysis.fs" />
<Compile Include="Program.fs" />
<None Include="App.config" />
stain: Image<Gray, byte>
infection: Image<Gray, byte> }
-let find (green: Image<Gray, float32>) (filteredGreen: Image<Gray, float32>) (config: Config.Config) : Result =
+let find (green: Image<Gray, float32>) (filteredGreen: Image<Gray, float32>) (kmediansResult: KMedians.Result) (config: Config.Config) : Result =
// We use the filtered image to find the dark stain.
- let { KMedians.fg = fg; KMedians.median_bg = median_bg; KMedians.median_fg = median_fg; KMedians.d_fg = d_fg } = KMedians.kmedians filteredGreen 1.0
+ let { KMedians.fg = fg; KMedians.median_bg = median_bg; KMedians.median_fg = median_fg; KMedians.d_fg = d_fg } = kmediansResult
let darkStain = d_fg.Cmp(median_bg * config.darkStainLevel, CvEnum.CmpType.GreaterThan)
darkStain._And(filteredGreen.Cmp(median_fg, CvEnum.CmpType.LessThan))
darkStain._And(fg)
let result = ImageAnalysis.doAnalysis img config
- display mainWindow result.img
+ display mainWindow img
mainWindow.Root.Show()
app.Run() |> ignore