c34b9c76469c17d49d4af615781391db67cfb08a
5 open System.Collections.Generic
12 // Normalize image values between 0uy and 255uy.
13 let normalizeAndConvert (img
: Image<Gray, float32
>) : Image<Gray, byte
> =
14 let min = ref [| 0.0
|]
15 let minLocation = ref <| [| Point() |]
16 let max = ref [| 0.0
|]
17 let maxLocation = ref <| [| Point() |]
18 img
.MinMax(min, max, minLocation, maxLocation)
19 ((img
- (!min).[0]) / ((!max).[0] - (!min).[0]) * 255.0).Convert<Gray, byte
>()
21 let gaussianFilter (img
: Image<'TColor, 'TDepth>) (standardDeviation
: float) : Image<'TColor, 'TDepth> =
22 let size = 2 * int (ceil
(4.0 * standardDeviation
)) + 1
23 img
.SmoothGaussian(size, size, standardDeviation
, standardDeviation
)
25 // Zhang and Suen algorithm.
26 // Modify 'mat' in place.
27 let thin (mat
: Matrix<byte
>) =
40 let mutable data1 = mat
.Data
41 let mutable data2 = Array2D.zeroCreate
<byte
> h w
43 // Return the list of neighbor values.
44 let neighborsValues (p1i
, p1j
) =
45 Array.map
(fun (ni
, nj
) ->
48 if pi < 0 || pi >= h || pj < 0 || pj >= w then 0uy else data1.[pi, pj]
51 // Return the number of 01 pattern in 'values' in a circular way.
52 let pattern01 (values
: byte
[]) =
54 let mutable lastValue = 255uy
56 if lastValue = 0uy && v
= 1uy
60 if lastValue = 0uy && values
.[0] = 1uy
65 let mutable pixelChanged = true
66 let mutable oddIteration = true
73 let values = neighborsValues (i
, j
)
74 let s = Array.reduce
(+) values
75 if s >= 2uy && s <= 6uy &&
76 pattern01 values = 1 &&
77 (not
oddIteration || (values.[0] * values.[2] * values.[4] = 0uy && values.[2] * values.[4] * values.[6] = 0uy)) && // Odd iteration.
78 (oddIteration || (values.[0] * values.[2] * values.[6] = 0uy && values.[0] * values.[4] * values.[6] = 0uy)) // Even iterations.
87 oddIteration <- not
oddIteration
94 let pop (l
: List<'a>) : 'a
=
95 let n = l
.[l
.Count - 1]
96 l
.RemoveAt(l
.Count - 1)
99 // Remove all 8-connected pixels with an area equal or greater than 'areaSize'.
100 // Modify 'mat' in place.
101 let removeArea (mat
: Matrix<byte
>) (areaSize
: int) =
112 let mat' = new Matrix<byte>(mat.Size)
118 let data' = mat'.Data
122 if data'.[i, j] = 1uy
124 let neighborhood = List<(int*int)>()
125 let neighborsToCheck = List<(int*int)>()
126 neighborsToCheck.Add((i, j))
129 while neighborsToCheck.Count > 0 do
130 let (ci
, cj
) = pop neighborsToCheck
131 neighborhood.Add((ci
, cj
))
132 for (ni
, nj
) in neighbors do
135 if pi >= 0 && pi < h && pj >= 0 && pj < w && data'.[pi, pj] = 1uy
137 neighborsToCheck.Add((pi, pj))
138 data'.[pi, pj] <- 0uy
139 if neighborhood.Count <= areaSize
141 for (ni
, nj
) in neighborhood do
144 let connectedComponents (img
: Image<Gray, byte
>) (startPoints
: List<Point>) : List<Point> =
148 let pointChecked = HashSet<Point>()
149 let pointToCheck = List<Point>(startPoints
);
153 while pointToCheck.Count > 0 do
154 let next = pop pointToCheck
155 pointChecked.Add(next) |> ignore
158 if ny
<> 0 && nx
<> 0
160 let p = Point(next.X + nx
, next.Y + ny
)
161 if p.X >= 0 && p.X < w && p.Y >= 0 && p.Y < h && data.[p.Y, p.X, 0] > 0uy && not
(pointChecked.Contains p)
165 List<Point>(pointChecked)
168 let saveImg (img
: Image<'TColor, 'TDepth>) (filepath
: string) =
172 let saveMat (mat: Matrix<'TDepth>) (filepath: string) =
173 use img = new Image<Gray, 'TDeph>(mat.Size)
177 (*let drawEllipse (img: Image<'TColor, 'TDepth>) (e: Types.Ellipse) (color: 'TColor) =
178 let e' = Ellipse(PointF(float32 e.cx, float32 e.cy), SizeF(2.0f * float32 e.a, 2.0f * float32 e.b), float32 e.alpha)
179 img.Draw(e', color)*)
181 let drawLine (img: Image<'TColor, 'TDepth>) (color
: 'TColor) (x0: int) (y0: int) (x1: int) (y1: int) =
182 img.Draw(LineSegment2D(Point(x0, y0), Point(x1, y1)), color, 1);
184 let drawLineF (img: Image<'TColor, 'TDepth>) (color: 'TColor) (x0
: float) (y0
: float) (x1
: float) (y1
: float) =
185 let x0, y0
, x1
, y1
= roundInt
(x0), roundInt
(y0
), roundInt
(x1
), roundInt
(y1
)
186 drawLine img color
x0 y0 x1 y1
188 let drawEllipse (img: Image<'TColor, 'TDepth>) (e: Types.Ellipse) (color
: 'TColor) =
189 let cosAlpha = cos e.Alpha
190 let sinAlpha = sin e.Alpha
194 let mutable first_iteration = true
197 let thetaIncrement = 2.0 * Math.PI / (float n)
199 for theta in 0.0 .. thetaIncrement .. 2.0 * Math.PI do
200 let cosTheta = cos theta
201 let sinTheta = sin theta
202 let x = e.Cx + cosAlpha * e.A * cosTheta - sinAlpha * e.B * sinTheta
203 let y = e.Cy + sinAlpha * e.A * cosTheta + cosAlpha * e.B * sinTheta
205 if not first_iteration
207 drawLineF img color x0 y0 x y
209 first_iteration <- false
214 let drawEllipses (img: Image<'TColor, 'TDepth>) (ellipses: Types.Ellipse list) (color: 'TColor) =
215 List.iter
(fun e -> drawEllipse img e color) ellipses
218 let rngCell = System.Random()
219 let drawCell (img: Image<Bgr, byte
>) (drawCellContent
: bool) (c
: Types.Cell) =
222 let colorB = rngCell.Next(20, 70)
223 let colorG = rngCell.Next(20, 70)
224 let colorR = rngCell.Next(20, 70)
226 for y in 0 .. c
.elements
.Height - 1 do
227 for x in 0 .. c
.elements
.Width - 1 do
228 if c
.elements
.[y, x] > 0uy
230 let dx, dy
= c
.center
.X - c
.elements
.Width / 2, c
.center
.Y - c
.elements
.Height / 2
231 let b = img.Data.[y + dy
, x + dx, 0] |> int
232 let g = img.Data.[y + dy
, x + dx, 1] |> int
233 let r = img.Data.[y + dy
, x + dx, 2] |> int
234 img.Data.[y + dy
, x + dx, 0] <- if b + colorB > 255 then 255uy else byte (b + colorB)
235 img.Data.[y + dy
, x + dx, 1] <- if g + colorG > 255 then 255uy else byte (g + colorG)
236 img.Data.[y + dy
, x + dx, 2] <- if r + colorR > 255 then 255uy else byte (r + colorR)
238 let crossColor = match c
.cellClass
with
239 | Types.HealthyRBC -> Bgr(255.0, 0.0, 0.0)
240 | Types.InfectedRBC -> Bgr(0.0, 0.0, 255.0)
241 | Types.Peculiar -> Bgr(0.0, 0.0, 0.0)
243 drawLine img crossColor (c
.center
.X - 3) c
.center
.Y (c
.center
.X + 3) c
.center
.Y
244 drawLine img crossColor c
.center
.X (c
.center
.Y - 3) c
.center
.X (c
.center
.Y + 3)
246 let drawCells (img: Image<Bgr, byte>) (drawCellContent
: bool) (cells
: Types.Cell list) =
247 List.iter
(fun c
-> drawCell img drawCellContent
c) cells