Split the module 'ImgTools' in many modules.
[master-thesis.git] / Parasitemia / ParasitemiaCore / ImgTools / Histogram.fs
diff --git a/Parasitemia/ParasitemiaCore/ImgTools/Histogram.fs b/Parasitemia/ParasitemiaCore/ImgTools/Histogram.fs
new file mode 100644 (file)
index 0000000..92b73f6
--- /dev/null
@@ -0,0 +1,84 @@
+module ParasitemiaCore.Histogram
+
+open System
+open System.Drawing
+
+open Emgu.CV
+open Emgu.CV.Structure
+
+type Histogram = {
+    data: int[]
+    total: int // Number of elements.
+    sum: int // Sum of all intensity.
+    min: float32
+    max: float32 }
+
+let histogramImg (img: Image<Gray, float32>) (nbSamples: int) : Histogram =
+    let imgData = img.Data
+
+    let min, max =
+        let min = ref [| 0.0 |]
+        let minLocation = ref <| [| Point() |]
+        let max = ref [| 0.0 |]
+        let maxLocation = ref <| [| Point() |]
+        img.MinMax(min, max, minLocation, maxLocation)
+        float32 (!min).[0], float32 (!max).[0]
+
+    let inline bin (x: float32) : int =
+        let p = int ((x - min) / (max - min) * float32 nbSamples)
+        if p >= nbSamples then nbSamples - 1 else p
+
+    let data = Array.zeroCreate nbSamples
+
+    for i in 0 .. img.Height - 1 do
+        for j in 0 .. img.Width - 1 do
+            let p = bin imgData.[i, j, 0]
+            data.[p] <- data.[p] + 1
+
+    { data = data; total = img.Height * img.Width; sum = Array.sum data; min = min; max = max }
+
+let histogramMat (mat: Matrix<float32>) (nbSamples: int) : Histogram =
+    let matData = mat.Data
+
+    let min, max =
+        let min = ref 0.0
+        let minLocation = ref <| Point()
+        let max = ref 0.0
+        let maxLocation = ref <| Point()
+        mat.MinMax(min, max, minLocation, maxLocation)
+        float32 !min, float32 !max
+
+    let inline bin (x: float32) : int =
+        let p = int ((x - min) / (max - min) * float32 nbSamples)
+        if p >= nbSamples then nbSamples - 1 else p
+
+    let data = Array.zeroCreate nbSamples
+
+    for i in 0 .. mat.Height - 1 do
+        for j in 0 .. mat.Width - 1 do
+            let p = bin matData.[i, j]
+            data.[p] <- data.[p] + 1
+
+    { data = data; total = mat.Height * mat.Width; sum = Array.sum data; min = min; max = max }
+
+let histogram (values: float32 seq) (nbSamples: int) : Histogram =
+    let mutable min = Single.MaxValue
+    let mutable max = Single.MinValue
+    let mutable n = 0
+
+    for v in values do
+        n <- n + 1
+        if v < min then min <- v
+        if v > max then max <- v
+
+    let inline bin (x: float32) : int =
+        let p = int ((x - min) / (max - min) * float32 nbSamples)
+        if p >= nbSamples then nbSamples - 1 else p
+
+    let data = Array.zeroCreate nbSamples
+
+    for v in values do
+        let p = bin v
+        data.[p] <- data.[p] + 1
+
+    { data = data; total = n; sum = Array.sum data; min = min; max = max }
\ No newline at end of file