module ParasitemiaCore.ImgTools
open System
open System.Drawing
open Emgu.CV
open Emgu.CV.Structure
///
/// Normalize an image between 0 and 'upperLimit'.
/// FIXME: use to many memory.
///
///
///
let normalize (img: Image) (upperLimit: float) : Image =
let min = ref [| 0.0 |]
let minLocation = ref <| [| Point() |]
let max = ref [| 0.0 |]
let maxLocation = ref <| [| Point() |]
img.MinMax(min, max, minLocation, maxLocation)
let normalized = (img - (!min).[0]) / ((!max).[0] - (!min).[0])
if upperLimit = 1.0
then normalized
else upperLimit * normalized
let mergeChannels (img: Image) (rgbWeights: float * float * float) : Image =
match rgbWeights with
| 1., 0., 0. -> img.[2]
| 0., 1., 0. -> img.[1]
| 0., 0., 1. -> img.[0]
| redFactor, greenFactor, blueFactor ->
let result = new Image(img.Size)
CvInvoke.AddWeighted(result, 1., img.[2], redFactor, 0., result)
CvInvoke.AddWeighted(result, 1., img.[1], greenFactor, 0., result)
CvInvoke.AddWeighted(result, 1., img.[0], blueFactor, 0., result)
result
let mergeChannelsWithProjection (img: Image) (v1r: float32, v1g: float32, v1b: float32) (v2r: float32, v2g: float32, v2b: float32) (upperLimit: float) : Image =
let vr, vg, vb = v2r - v1r, v2g - v1g, v2b - v1b
let vMagnitude = sqrt (vr ** 2.f + vg ** 2.f + vb ** 2.f)
let project (r: float32) (g: float32) (b: float32) = ((r - v1r) * vr + (g - v1g) * vg + (b - v1b) * vb) / vMagnitude
let result = new Image(img.Size)
// TODO: Essayer en bindant Data pour gagner du temps
for i in 0 .. img.Height - 1 do
for j in 0 .. img.Width - 1 do
result.Data.[i, j, 0] <- project img.Data.[i, j, 2] img.Data.[i, j, 1] img.Data.[i, j, 0]
normalize result upperLimit
// Normalize image values between 0uy and 255uy.
let normalizeAndConvert (img: Image) : Image =
(normalize (img.Convert()) 255.).Convert()
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)