--- /dev/null
+module ImgTools
+
+open System
+open System.Drawing
+open System.Collections.Generic
+
+open Emgu.CV
+open Emgu.CV.Structure
+
+open Utils
+
+let gaussianFilter (img : Image<'TColor, 'TDepth>) (standardDeviation : float) : Image<'TColor, 'TDepth> =
+ let size = 2 * int (ceil (4.0 * standardDeviation)) + 1
+ img.SmoothGaussian(size, size, standardDeviation, standardDeviation)
+
+// 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 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.
+ then
+ data2.[i, j] <- 0uy
+ pixelChanged <- true
+ else
+ data2.[i, j] <- 1uy
+ else
+ data2.[i, j] <- 0uy
+
+ oddIteration <- not oddIteration
+ let tmp = data1
+ data1 <- data2
+ data2 <- tmp
+
+
+// Remove all 8-connected pixels with an area equal or greater than 'areaSize'.
+// Modify 'mat' in place.
+let removeArea (mat: Matrix<byte>) (areaSize: int) =
+ 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 mat' = new Matrix<byte>(mat.Size)
+ let w = mat'.Width
+ let h = mat'.Height
+ mat.CopyTo(mat')
+
+ let data = mat.Data
+ let data' = mat'.Data
+
+ for i in 0..h-1 do
+ for j in 0..w-1 do
+ if data'.[i, j] = 1uy
+ then
+ let neighborhood = List<(int*int)>()
+ let neighborsToCheck = List<(int*int)>()
+ neighborsToCheck.Add((i, j))
+ data'.[i, j] <- 0uy
+
+ let pop (l: List<'a>) : 'a =
+ let n = l.[l.Count - 1]
+ l.RemoveAt(l.Count - 1)
+ n
+
+ while neighborsToCheck.Count > 0 do
+ let (ci, cj) = pop neighborsToCheck
+ neighborhood.Add((ci, cj))
+ for (ni, nj) in neighbors do
+ let pi = ci + ni
+ let pj = cj + nj
+ if pi >= 0 && pi < h && pj >= 0 && pj < w && data'.[pi, pj] = 1uy
+ then
+ neighborsToCheck.Add((pi, pj))
+ data'.[pi, pj] <- 0uy
+ if neighborhood.Count <= areaSize
+ then
+ for (ni, nj) in neighborhood do
+ data.[ni, nj] <- 0uy
+
+
+let saveImg (img: Image<'TColor, 'TDepth>) (name: string) =
+ img.Save("output/" + name)
+
+
+let saveMat (mat: Matrix<'TDepth>) (name: string) =
+ use img = new Image<Gray, 'TDeph>(mat.Size)
+ mat.CopyTo(img)
+ saveImg img name
+
+(*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: float) (y0: float) (x1: float) (y1: float) =
+ let x0, y0, x1, y1 = roundInt(x0), roundInt(y0), roundInt(x1), roundInt(y1)
+
+ img.Draw(LineSegment2D(Point(x0, y0), Point(x1, y1)), color, 1);
+
+let drawEllipse (img: Image<'TColor, 'TDepth>) (e: Types.Ellipse) (color: 'TColor) =
+ let cosAlpha = cos e.alpha
+ let sinAlpha = sin e.alpha
+
+ let mutable x0 = 0.0
+ let mutable y0 = 0.0
+ let mutable first_iteration = true
+
+ let n = 40
+ let thetaIncrement = 2.0 * Math.PI / (float n)
+
+ for theta in 0.0 .. thetaIncrement .. 2.0 * Math.PI do
+ let cosTheta = cos theta
+ let sinTheta = sin theta
+ let x = e.cx + cosAlpha * e.a * cosTheta - sinAlpha * e.b * sinTheta
+ let y = e.cy + sinAlpha * e.a * cosTheta + cosAlpha * e.b * sinTheta
+
+ if not first_iteration
+ then
+ drawLine img color x0 y0 x y
+ else
+ first_iteration <- false
+
+ x0 <- x
+ y0 <- y
\ No newline at end of file