cc09405b3477005646cf8f560eea32016e54dbcf
5 open System.Collections.Generic
12 let gaussianFilter (img
: Image<'TColor, 'TDepth>) (standardDeviation
: float) : Image<'TColor, 'TDepth> =
13 let size = 2 * int (ceil
(4.0 * standardDeviation
)) + 1
14 img
.SmoothGaussian(size, size, standardDeviation
, standardDeviation
)
16 // Zhang and Suen algorithm.
17 // Modify 'mat' in place.
18 let thin (mat
: Matrix<byte
>) =
31 let mutable data1 = mat
.Data
32 let mutable data2 = Array2D.zeroCreate
<byte
> h w
34 // Return the list of neighbor values.
35 let neighborsValues (p1i
, p1j
) =
36 Array.map
(fun (ni
, nj
) ->
39 if pi < 0 || pi >= h || pj < 0 || pj >= w then 0uy else data1.[pi, pj]
42 // Return the number of 01 pattern in 'values' in a circular way.
43 let pattern01 (values
: byte
[]) =
45 let mutable lastValue = 255uy
47 if lastValue = 0uy && v
= 1uy
51 if lastValue = 0uy && values
.[0] = 1uy
56 let mutable pixelChanged = true
57 let mutable oddIteration = true
64 let values = neighborsValues (i
, j
)
65 let s = Array.reduce
(+) values
66 if s >= 2uy && s <= 6uy &&
67 pattern01 values = 1 &&
68 (not
oddIteration || (values.[0] * values.[2] * values.[4] = 0uy && values.[2] * values.[4] * values.[6] = 0uy)) && // Odd iteration.
69 (oddIteration || (values.[0] * values.[2] * values.[6] = 0uy && values.[0] * values.[4] * values.[6] = 0uy)) // Even iterations.
78 oddIteration <- not
oddIteration
84 // Remove all 8-connected pixels with an area equal or greater than 'areaSize'.
85 // Modify 'mat' in place.
86 let removeArea (mat
: Matrix<byte
>) (areaSize
: int) =
97 let mat' = new Matrix<byte>(mat.Size)
103 let data' = mat'.Data
107 if data'.[i, j] = 1uy
109 let neighborhood = List<(int*int)>()
110 let neighborsToCheck = List<(int*int)>()
111 neighborsToCheck.Add((i, j))
114 let pop (l
: List<'a>) : 'a
=
115 let n = l
.[l
.Count - 1]
116 l
.RemoveAt(l
.Count - 1)
119 while neighborsToCheck.Count > 0 do
120 let (ci
, cj
) = pop neighborsToCheck
121 neighborhood.Add((ci
, cj
))
122 for (ni
, nj
) in neighbors do
125 if pi >= 0 && pi < h && pj >= 0 && pj < w && data'.[pi, pj] = 1uy
127 neighborsToCheck.Add((pi, pj))
128 data'.[pi, pj] <- 0uy
129 if neighborhood.Count <= areaSize
131 for (ni
, nj
) in neighborhood do
135 let saveImg (img
: Image<'TColor, 'TDepth>) (name
: string) =
136 img
.Save("output/" + name
)
139 let saveMat (mat: Matrix<'TDepth>) (name: string) =
140 use img = new Image<Gray, 'TDeph>(mat.Size)
144 (*let drawEllipse (img: Image<'TColor, 'TDepth>) (e: Types.Ellipse) (color: 'TColor) =
145 let e' = Ellipse(PointF(float32 e.cx, float32 e.cy), SizeF(2.0f * float32 e.a, 2.0f * float32 e.b), float32 e.alpha)
146 img.Draw(e', color)*)
148 let drawLine (img: Image<'TColor, 'TDepth>) (color
: 'TColor) (x0: float) (y0: float) (x1: float) (y1: float) =
149 let x0, y0, x1, y1 = roundInt(x0), roundInt(y0), roundInt(x1), roundInt(y1)
151 img.Draw(LineSegment2D(Point(x0, y0), Point(x1, y1)), color, 1);
153 let drawEllipse (img: Image<'TColor, 'TDepth>) (e: Types.Ellipse) (color: 'TColor) =
154 let cosAlpha = cos
e.alpha
155 let sinAlpha = sin
e.alpha
159 let mutable first_iteration = true
162 let thetaIncrement = 2.0 * Math.PI / (float n)
164 for theta
in 0.0 .. thetaIncrement .. 2.0 * Math.PI do
165 let cosTheta = cos
theta
166 let sinTheta = sin
theta
167 let x = e.cx
+ cosAlpha * e.a
* cosTheta - sinAlpha * e.b
* sinTheta
168 let y = e.cy
+ sinAlpha * e.a
* cosTheta + cosAlpha * e.b
* sinTheta
170 if not
first_iteration
172 drawLine img color
x0 y0 x y
174 first_iteration <- false