From cb90b01c85183b2c75ee6d22b378b3ca99df6bf3 Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Thu, 21 Jan 2016 13:50:59 +0100 Subject: [PATCH] Add an option to change the brightness of the highlight box color (healthy/infected) (Can't be changed with the UI). --- Parasitemia/ParasitemiaCore/AssemblyInfo.fs | 8 +-- Parasitemia/ParasitemiaCore/Types.fs | 8 ++- Parasitemia/ParasitemiaCore/UnitsOfMeasure.fs | 4 -- Parasitemia/ParasitemiaUI/AssemblyInfo.fs | 4 +- Parasitemia/ParasitemiaUI/GUI.fs | 35 +++++------ .../ParasitemiaUI/ParasitemiaUI.fsproj | 1 + Parasitemia/ParasitemiaUI/PiaZ.fs | 63 +++++++++++++------ Parasitemia/ParasitemiaUI/State.fs | 10 ++- Parasitemia/ParasitemiaUI/Types.fs | 19 +++++- .../ParasitemiaUI/XAML/MainWindow.xaml | 2 +- 10 files changed, 101 insertions(+), 53 deletions(-) diff --git a/Parasitemia/ParasitemiaCore/AssemblyInfo.fs b/Parasitemia/ParasitemiaCore/AssemblyInfo.fs index 268f060..89d76f0 100644 --- a/Parasitemia/ParasitemiaCore/AssemblyInfo.fs +++ b/Parasitemia/ParasitemiaCore/AssemblyInfo.fs @@ -10,9 +10,9 @@ open System.Runtime.InteropServices [] [] [] -[] +[] [] -[] +[] [] [] @@ -34,8 +34,8 @@ open System.Runtime.InteropServices // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [] -[] -[] +[] +[] do () \ No newline at end of file diff --git a/Parasitemia/ParasitemiaCore/Types.fs b/Parasitemia/ParasitemiaCore/Types.fs index e2accb7..7bfbd7f 100644 --- a/Parasitemia/ParasitemiaCore/Types.fs +++ b/Parasitemia/ParasitemiaCore/Types.fs @@ -35,7 +35,7 @@ type Ellipse (cx: float32, cy: float32, a: float32, b: float32, alpha: float32) this.CutAVericalLine 0.f || this.CutAVericalLine width || this.CutAnHorizontalLine 0.f || this.CutAnHorizontalLine height - member this.Scale (factor: float32) = + member this.Scale (factor: float32) : Ellipse = Ellipse(this.Cx, this.Cy, this.A * factor, this.B * factor, alpha) // Approximation of Ramanujan. @@ -68,8 +68,10 @@ type MaybeBuilder () = member this.ReturnFrom (x) = x member this.TryFinally (body, compensation) = - try this.ReturnFrom(body()) - finally compensation() + try + this.ReturnFrom(body()) + finally + compensation() member this.Using (disposable: 'a when 'a :> IDisposable, body) = let body' = fun () -> body disposable diff --git a/Parasitemia/ParasitemiaCore/UnitsOfMeasure.fs b/Parasitemia/ParasitemiaCore/UnitsOfMeasure.fs index 81ce51f..0d84d16 100644 --- a/Parasitemia/ParasitemiaCore/UnitsOfMeasure.fs +++ b/Parasitemia/ParasitemiaCore/UnitsOfMeasure.fs @@ -10,7 +10,3 @@ let μmInchRatio = 25.4e3<μm/inch> let μmToInch(x: float<μm>) : float = x / μmInchRatio let inchToμm(x: float) : float<μm> = x * μmInchRatio - - - - diff --git a/Parasitemia/ParasitemiaUI/AssemblyInfo.fs b/Parasitemia/ParasitemiaUI/AssemblyInfo.fs index 16cfbfc..004f87f 100644 --- a/Parasitemia/ParasitemiaUI/AssemblyInfo.fs +++ b/Parasitemia/ParasitemiaUI/AssemblyInfo.fs @@ -34,8 +34,8 @@ open System.Runtime.InteropServices // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [] -[] -[] +[] +[] do () \ No newline at end of file diff --git a/Parasitemia/ParasitemiaUI/GUI.fs b/Parasitemia/ParasitemiaUI/GUI.fs index a71aa96..2ff3116 100644 --- a/Parasitemia/ParasitemiaUI/GUI.fs +++ b/Parasitemia/ParasitemiaUI/GUI.fs @@ -24,9 +24,6 @@ let run (defaultConfig: Config) (fileToOpen: string option) = let mainWindow = Views.MainWindow() let ctrl (name: string): 'a = mainWindow.Root.FindName(name) :?> 'a - let colorRBCHealthy = Brushes.YellowGreen - let colorRBCInfected = Brushes.Red - let state = State.State() let mutable currentScale = 1. let mutable displayHealthy = false @@ -78,19 +75,19 @@ let run (defaultConfig: Config) (fileToOpen: string option) = System.Drawing.Size((if x + w >= img.Width then img.Width - x else w), (if y + h >= img.Height then img.Height - y else h)))) - let setRBCFrameStyle (rbc: RBC) (frame: Views.RBCFrame) = + let setRBCFrameStyle (srcImg: SourceImage) (rbc: RBC) (frame: Views.RBCFrame) = frame.Opacity <- if displayHealthy || rbc.setManually || rbc.infected then 1. else 0. - let color = if rbc.infected then colorRBCInfected else colorRBCHealthy + let color = if rbc.infected then srcImg.InfectedRBCColor else srcImg.HealthyRBCColor frame.manuallyAdded.Visibility <- if rbc.setManually then Visibility.Visible else Visibility.Hidden frame.manuallyAdded.Fill <- color frame.border.Stroke <- color - let RBCFrameFromExisting (rbc: RBC) (frame: Views.RBCFrame) : Views.RBCFrame = + let RBCFrameFromExisting (srcImg: SourceImage) (rbc: RBC) (frame: Views.RBCFrame) : Views.RBCFrame = frame.Visibility <- Visibility.Visible frame.Height <- rbc.size.Height frame.Width <- rbc.size.Width frame.Tag <- rbc - setRBCFrameStyle rbc frame + setRBCFrameStyle srcImg rbc frame frame.border.StrokeThickness <- 1. frame.txtRBCNumber.Text <- rbc.num.ToString() frame @@ -179,7 +176,7 @@ let run (defaultConfig: Config) (fileToOpen: string option) = else preview.viewport.Visibility <- Visibility.Hidden - let rec setAsInfected (rbc: RBC) (infected: bool) = + let rec setAsInfected (srcImg: SourceImage) (rbc: RBC) (infected: bool) = state.SetAsInfected rbc infected canvasCurrentImage.Children |> Seq.cast @@ -187,16 +184,16 @@ let run (defaultConfig: Config) (fileToOpen: string option) = (fun frame -> if (frame.Tag :?> RBC) = rbc then - setRBCFrameStyle rbc frame) + setRBCFrameStyle srcImg rbc frame) updateRBCFramesPreview () updateCurrentImageInformation () updateGlobalParasitemia () - and RBCFrame (rbc: RBC) : Views.RBCFrame = - let frame = RBCFrameFromExisting rbc (Views.RBCFrame()) + and RBCFrame (srcImg: SourceImage) (rbc: RBC) : Views.RBCFrame = + let frame = RBCFrameFromExisting srcImg rbc (Views.RBCFrame()) frame.SetValue(Panel.ZIndexProperty, Int32.MaxValue - rbc.num) // To be sure the - frame.menuRBCSetAsHealthy.Click.AddHandler(fun obj args -> setAsInfected (frame.Tag :?> RBC) false) - frame.menuRBCSetAsInfected.Click.AddHandler(fun obj args -> setAsInfected (frame.Tag :?> RBC) true) + frame.menuRBCSetAsHealthy.Click.AddHandler(fun obj args -> setAsInfected srcImg (frame.Tag :?> RBC) false) + frame.menuRBCSetAsInfected.Click.AddHandler(fun obj args -> setAsInfected srcImg (frame.Tag :?> RBC) true) frame.ContextMenuOpening.AddHandler( fun obj args -> if (frame.Tag :?> RBC).infected @@ -220,9 +217,9 @@ let run (defaultConfig: Config) (fileToOpen: string option) = let previewInfected = if currentPreview < stackRBC.Children.Count then - RBCFrameFromExisting rbc (stackRBC.Children.[currentPreview] :?> Views.RBCFrame) + RBCFrameFromExisting srcImg rbc (stackRBC.Children.[currentPreview] :?> Views.RBCFrame) else - let f = RBCFrame rbc + let f = RBCFrame srcImg rbc f.MouseLeftButtonUp.AddHandler(fun obj args -> zoomToRBC (f.Tag :?> RBC)) stackRBC.Children.Add(f) |> ignore f @@ -246,9 +243,9 @@ let run (defaultConfig: Config) (fileToOpen: string option) = let frame = if currentCanvas < canvasCurrentImage.Children.Count then - RBCFrameFromExisting rbc (canvasCurrentImage.Children.[currentCanvas] :?> Views.RBCFrame) + RBCFrameFromExisting srcImg rbc (canvasCurrentImage.Children.[currentCanvas] :?> Views.RBCFrame) else - let f = RBCFrame rbc + let f = RBCFrame srcImg rbc f.Root.Opacity <- 0.7 canvasCurrentImage.Children.Add(f) |> ignore f @@ -327,8 +324,10 @@ let run (defaultConfig: Config) (fileToOpen: string option) = updateRBCFramesCurrent () updateRBCFramesPreview () + | None -> imgLogos.Visibility <- Visibility.Visible + stackRBC.Children.Clear() canvasCurrentImage.Children.Clear() canvasCurrentImage.Background <- canvasCurrentImageColor @@ -591,4 +590,4 @@ let run (defaultConfig: Config) (fileToOpen: string option) = | Some filepath -> loadFile filepath | None -> () - app.Run() \ No newline at end of file + app.Run() diff --git a/Parasitemia/ParasitemiaUI/ParasitemiaUI.fsproj b/Parasitemia/ParasitemiaUI/ParasitemiaUI.fsproj index 483888f..0859274 100644 --- a/Parasitemia/ParasitemiaUI/ParasitemiaUI.fsproj +++ b/Parasitemia/ParasitemiaUI/ParasitemiaUI.fsproj @@ -68,6 +68,7 @@ + diff --git a/Parasitemia/ParasitemiaUI/PiaZ.fs b/Parasitemia/ParasitemiaUI/PiaZ.fs index d4ea46f..c9dfd5b 100644 --- a/Parasitemia/ParasitemiaUI/PiaZ.fs +++ b/Parasitemia/ParasitemiaUI/PiaZ.fs @@ -20,6 +20,7 @@ let filter = "PIA|*.piaz" // Information associated to a document. type JSONInformation = { patientID: string + fileVersion: int } // Information associated to each images. @@ -29,6 +30,9 @@ type JSONSourceImage = { parameters: ParasitemiaCore.Config.Parameters dateLastAnalysis: DateTime rbcs: RBC List + + healthyRBCBrightness: float32 // 0 to 1. + infectedRBCBrightness: float32 // 0 to 1. } type DocumentData = { @@ -38,6 +42,7 @@ type DocumentData = { let mainEntryName = "info.json" let imageExtension = ".tiff" +let currentFileVersion = 1 /// /// Save a document in a give file path. The file may already exist. @@ -54,7 +59,7 @@ let save (filePath: string) (data: DocumentData) = // Main JSON file. let mainEntry = file.CreateEntry(mainEntryName, CompressionLevel.Fastest) use mainEntryWriter = new StreamWriter(mainEntry.Open()) - mainEntryWriter.Write(JsonConvert.SerializeObject({ JSONInformation.patientID = data.patientID })) + mainEntryWriter.Write(JsonConvert.SerializeObject({ patientID = data.patientID; fileVersion = currentFileVersion })) // Write each images and the associated information. for srcImg in data.images do @@ -64,7 +69,23 @@ let save (filePath: string) (data: DocumentData) = let imgJSONEntry = file.CreateEntry(imgFilename + ".json", CompressionLevel.Fastest) use imgJSONFileWriter = new StreamWriter(imgJSONEntry.Open()) - imgJSONFileWriter.Write(JsonConvert.SerializeObject({ num = srcImg.num; RBCRadius = srcImg.config.RBCRadius.Pixel; parameters = srcImg.config.Parameters; dateLastAnalysis = srcImg.dateLastAnalysis; rbcs = srcImg.rbcs })) + imgJSONFileWriter.Write( + JsonConvert.SerializeObject( + { num = srcImg.num + RBCRadius = srcImg.config.RBCRadius.Pixel + parameters = srcImg.config.Parameters + dateLastAnalysis = srcImg.dateLastAnalysis + rbcs = srcImg.rbcs + healthyRBCBrightness = srcImg.healthyRBCBrightness + infectedRBCBrightness = srcImg.infectedRBCBrightness })) + +let updateDocumentData (fromVersion: int) (toVersion: int) (data: DocumentData) : DocumentData = + for v in fromVersion + 1 .. toVersion do + match v with + | 1 -> // Version 0 -> 1 : set initial brightness for rbc. + data.images |> List.iter (fun i -> i.healthyRBCBrightness <- 1.f; i.infectedRBCBrightness <- 1.f) + | _ -> () + data /// /// Load document from a give file path. @@ -78,20 +99,24 @@ let load (filePath: string) : DocumentData = use mainEntryReader = new StreamReader(mainEntry.Open()) let info = JsonConvert.DeserializeObject(mainEntryReader.ReadToEnd()) - { patientID = info.patientID - images = [ let mutable imgNum = 0 - for imgEntry in file.Entries do - if imgEntry.Name.EndsWith(imageExtension) - then - let img = new Image(new System.Drawing.Bitmap(imgEntry.Open(), false)) // FIXME: Should we dispose the bitmap? - imgNum <- imgNum + 1 - let imgEntry = file.GetEntry(imgEntry.Name + ".json") - use imgEntryFileReader = new StreamReader(imgEntry.Open()) - let imgInfo = JsonConvert.DeserializeObject(imgEntryFileReader.ReadToEnd()) - let config = ParasitemiaCore.Config.Config(imgInfo.parameters) - config.SetRBCRadius imgInfo.RBCRadius - yield { num = imgNum - config = config - dateLastAnalysis = imgInfo.dateLastAnalysis - img = img - rbcs = imgInfo.rbcs } ] } \ No newline at end of file + updateDocumentData info.fileVersion currentFileVersion + { patientID = info.patientID + images = [ let mutable imgNum = 0 + for imgEntry in file.Entries do + if imgEntry.Name.EndsWith(imageExtension) + then + use bitmap = new System.Drawing.Bitmap(imgEntry.Open(), false) + let img = new Image(bitmap) + imgNum <- imgNum + 1 + let imgEntry = file.GetEntry(imgEntry.Name + ".json") + use imgEntryFileReader = new StreamReader(imgEntry.Open()) + let imgInfo = JsonConvert.DeserializeObject(imgEntryFileReader.ReadToEnd()) + let config = ParasitemiaCore.Config.Config(imgInfo.parameters) + config.SetRBCRadius imgInfo.RBCRadius + yield { num = imgNum + config = config + dateLastAnalysis = imgInfo.dateLastAnalysis + img = img + rbcs = imgInfo.rbcs + healthyRBCBrightness = imgInfo.healthyRBCBrightness + infectedRBCBrightness = imgInfo.infectedRBCBrightness } ] } \ No newline at end of file diff --git a/Parasitemia/ParasitemiaUI/State.fs b/Parasitemia/ParasitemiaUI/State.fs index f133640..63b9bbf 100644 --- a/Parasitemia/ParasitemiaUI/State.fs +++ b/Parasitemia/ParasitemiaUI/State.fs @@ -73,7 +73,15 @@ type State () = /// /// If the image cannot be read member this.AddSourceImage (filePath: string) (defaultConfig: ParasitemiaCore.Config.Config) : SourceImage = - let srcImg = { num = sourceImages.Count + 1; config = defaultConfig.Copy(); dateLastAnalysis = DateTime(0L); rbcs = []; img = new Image(filePath) } + let srcImg = + { num = sourceImages.Count + 1 + config = defaultConfig.Copy() + dateLastAnalysis = DateTime(0L) + rbcs = [] + img = new Image(filePath) + healthyRBCBrightness = 1.f + infectedRBCBrightness = 1.f } + sourceImages.Add(srcImg) if sourceImages.Count = 1 then this.CurrentImage <- Some sourceImages.[0] diff --git a/Parasitemia/ParasitemiaUI/Types.fs b/Parasitemia/ParasitemiaUI/Types.fs index 7d80294..5de71e6 100644 --- a/Parasitemia/ParasitemiaUI/Types.fs +++ b/Parasitemia/ParasitemiaUI/Types.fs @@ -2,10 +2,14 @@ open System open System.Windows +open System.Windows.Media open Emgu.CV open Emgu.CV.Structure +let healthyRBColor = Color.FromRgb(255uy, 255uy, 0uy) // Yellow-green. +let infectedRBColor = Color.FromRgb(255uy, 0uy, 40uy) // Red with a bit of blue. + type RBC = { num: int @@ -21,4 +25,17 @@ type SourceImage = { mutable config: ParasitemiaCore.Config.Config mutable dateLastAnalysis: DateTime // UTC. img: Image - mutable rbcs: RBC list } \ No newline at end of file + mutable rbcs: RBC list + + mutable healthyRBCBrightness: float32 + mutable infectedRBCBrightness: float32 } with + + member this.HealthyRBCColor: SolidColorBrush = + let mutable color = healthyRBColor * this.healthyRBCBrightness + color.A <- 255uy; + SolidColorBrush(color) + + member this.InfectedRBCColor: SolidColorBrush = + let mutable color = infectedRBColor * this.infectedRBCBrightness + color.A <- 255uy; + SolidColorBrush(color) \ No newline at end of file diff --git a/Parasitemia/ParasitemiaUI/XAML/MainWindow.xaml b/Parasitemia/ParasitemiaUI/XAML/MainWindow.xaml index 2b43c86..e763bea 100644 --- a/Parasitemia/ParasitemiaUI/XAML/MainWindow.xaml +++ b/Parasitemia/ParasitemiaUI/XAML/MainWindow.xaml @@ -70,7 +70,7 @@ - + -- 2.43.0