Improve the thinning process performance.
[master-thesis.git] / Parasitemia / Parasitemia / ImgTools.fs
index c34b9c7..f7e5a4a 100644 (file)
@@ -25,62 +25,45 @@ let gaussianFilter (img : Image<'TColor, 'TDepth>) (standardDeviation : float) :
 // Zhang and Suen algorithm.
 // Modify 'mat' in place.
 let thin (mat: Matrix<byte>) =
-    let neighbors = [|
-        (-1,  0) // p2
-        (-1,  1) // p3
-        ( 0,  1) // p4
-        ( 1,  1) // p5
-        ( 1,  0) // p6
-        ( 1, -1) // p7
-        ( 0, -1) // p8
-        (-1, -1) |] // p9
-
     let w = mat.Width
     let h = mat.Height
     let mutable data1 = mat.Data
-    let mutable data2 = Array2D.zeroCreate<byte> h w
-
-    // Return the list of neighbor values.
-    let neighborsValues (p1i, p1j) =
-        Array.map (fun (ni, nj) ->
-            let pi = p1i + ni
-            let pj = p1j + nj
-            if pi < 0 || pi >= h || pj < 0 || pj >= w then 0uy else data1.[pi, pj]
-            ) neighbors
-
-    // Return the number of 01 pattern in 'values' in a circular way.
-    let pattern01 (values: byte[]) =
-        let mutable nb = 0
-        let mutable lastValue = 255uy
-        for v in values do
-            if lastValue = 0uy && v = 1uy
-            then
-                nb <- nb + 1
-            lastValue <- v
-        if lastValue = 0uy && values.[0] = 1uy
-        then
-            nb <- nb + 1
-        nb
+    let mutable data2 = Array2D.copy data1
 
     let mutable pixelChanged = true
     let mutable oddIteration = true
+
     while pixelChanged do
         pixelChanged <- false
         for i in 0..h-1 do
             for j in 0..w-1 do
                 if data1.[i, j] = 1uy
                 then
-                    let values = neighborsValues (i, j)
-                    let s = Array.reduce (+) values
-                    if s >= 2uy && s <= 6uy &&
-                        pattern01 values = 1 &&
-                        (not oddIteration || (values.[0] * values.[2] * values.[4] = 0uy && values.[2] * values.[4] * values.[6] = 0uy)) && // Odd iteration.
-                        (oddIteration || (values.[0] * values.[2] * values.[6] = 0uy && values.[0] * values.[4] * values.[6] = 0uy)) // Even iterations.
+                    let p2 = if i = 0 then 0uy else data1.[i-1, j]
+                    let p3 = if i = 0 || j = w-1 then 0uy else data1.[i-1, j+1]
+                    let p4 = if j = w-1 then 0uy else data1.[i, j+1]
+                    let p5 = if i = h-1 || j = w-1 then 0uy else data1.[i+1, j+1]
+                    let p6 = if i = h-1 then 0uy else data1.[i+1, j]
+                    let p7 = if i = h-1 || j = 0 then 0uy else data1.[i+1, j-1]
+                    let p8 = if j = 0 then 0uy else data1.[i, j-1]
+                    let p9 = if i = 0 || j = 0 then 0uy else data1.[i-1, j-1]
+
+                    let sumNeighbors = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9
+                    if sumNeighbors >= 2uy && sumNeighbors <= 6uy &&
+                        (if p2 = 0uy && p3 = 1uy then 1 else 0) +
+                        (if p3 = 0uy && p4 = 1uy then 1 else 0) +
+                        (if p4 = 0uy && p5 = 1uy then 1 else 0) +
+                        (if p5 = 0uy && p6 = 1uy then 1 else 0) +
+                        (if p6 = 0uy && p7 = 1uy then 1 else 0) +
+                        (if p7 = 0uy && p8 = 1uy then 1 else 0) +
+                        (if p8 = 0uy && p9 = 1uy then 1 else 0) +
+                        (if p9 = 0uy && p2 = 1uy then 1 else 0) = 1 &&
+                        if oddIteration
+                        then p2 * p4 * p6 = 0uy && p4 * p6 * p8 = 0uy
+                        else p2 * p4 * p8 = 0uy && p2 * p6 * p8 = 0uy
                     then
                         data2.[i, j] <- 0uy
                         pixelChanged <- true
-                    else
-                        data2.[i, j] <- 1uy
                 else
                     data2.[i, j] <- 0uy
 
@@ -90,7 +73,6 @@ let thin (mat: Matrix<byte>) =
         data2 <- tmp
 
 
-
 let pop (l: List<'a>) : 'a =
     let n = l.[l.Count - 1]
     l.RemoveAt(l.Count - 1)
@@ -174,10 +156,6 @@ let saveMat (mat: Matrix<'TDepth>) (filepath: string) =
     mat.CopyTo(img)
     saveImg img filepath
 
-(*let drawEllipse (img: Image<'TColor, 'TDepth>) (e: Types.Ellipse) (color: 'TColor) =
-    let e' = Ellipse(PointF(float32 e.cx, float32 e.cy), SizeF(2.0f * float32 e.a, 2.0f * float32 e.b), float32 e.alpha)
-    img.Draw(e', color)*)
-
 let drawLine (img: Image<'TColor, 'TDepth>) (color: 'TColor) (x0: int) (y0: int) (x1: int) (y1: int) =
     img.Draw(LineSegment2D(Point(x0, y0), Point(x1, y1)), color, 1);