From 632545e927bf1bf734f2f453f76852655555c064 Mon Sep 17 00:00:00 2001 From: schultezub Date: Mon, 4 Feb 2013 13:36:57 +0000 Subject: [PATCH] Further work on AdvancedUsFusion processor: implemented HSL and HCY colorspace git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@441 bb408c1c-ae56-11e1-83d9-df6b3e0c105e --- core/datastructures/datacontainer.cpp | 1 + core/datastructures/datacontainer.h | 5 +- core/glsl/tools/colorspace.frag | 159 ++++++++++++++---- .../advancedusvis/glsl/advancedusfusion.frag | 15 ++ .../processors/advancedusfusion.cpp | 8 +- 5 files changed, 149 insertions(+), 39 deletions(-) diff --git a/core/datastructures/datacontainer.cpp b/core/datastructures/datacontainer.cpp index 77e14589..b859a04c 100644 --- a/core/datastructures/datacontainer.cpp +++ b/core/datastructures/datacontainer.cpp @@ -51,6 +51,7 @@ namespace campvis { } void DataContainer::addDataHandle(const std::string& name, const DataHandle& dh) { + tgtAssert(dh.getData() != 0, "The data in the DataHandle must not be 0!"); { tbb::spin_mutex::scoped_lock lock(_localMutex); std::map::iterator it = _handles.lower_bound(name); diff --git a/core/datastructures/datacontainer.h b/core/datastructures/datacontainer.h index a4988a45..113d35b1 100644 --- a/core/datastructures/datacontainer.h +++ b/core/datastructures/datacontainer.h @@ -131,8 +131,8 @@ namespace campvis { * In doing so, the DataContainer (respectively the created DataHandle) takes ownership of \a data * and will manage its lifetime. So don't even think about deleting \a data yourself! * - * \param name Key for accessing the DataHandle within this DataContainer - * \param data DataHandle to add. + * \param name Key for accessing the DataHandle within this DataContainer. + * \param data The data to wrap in a DataHandle and add to this DataContainer, must not be 0. * \return A DataHandle containing \a data. */ DataHandle addData(const std::string& name, AbstractData* data); @@ -196,6 +196,7 @@ namespace campvis { sigslot::signal0<> s_changed; private: + /// Map of the DataHandles in this collection and their IDs. The DataHandles contain valid data. std::map _handles; mutable tbb::spin_mutex _localMutex; diff --git a/core/glsl/tools/colorspace.frag b/core/glsl/tools/colorspace.frag index 01e76335..71e0ae95 100644 --- a/core/glsl/tools/colorspace.frag +++ b/core/glsl/tools/colorspace.frag @@ -27,55 +27,146 @@ // // ================================================================================================ +// The weights of RGB contributions to luminance. +// Should sum to unity. +const vec3 HCYwts_ = vec3(0.299, 0.587, 0.114); + /** - * Converts a color from RGB space to HSV space. - * Using the efficient implementation from http://chilliant.blogspot.de/2010/11/rgbhsv-in-hlsl.html. - * \param colorRGB color in RGB space - * \return The given color in HSV space. + * Converts pure Hue to RGB + * Using the efficient implementation from http://www.chilliant.com/rgb2hsv.html. + * \param H Pure hue + * \return The pure hue converted to RGB. */ -vec3 rgb2hsv(vec3 colorRGB) { - vec3 HSV = vec3(0.0); - - HSV.z = max(colorRGB.r, max(colorRGB.g, colorRGB.b)); - float M = min(colorRGB.r, min(colorRGB.g, colorRGB.b)); - float difference = HSV.z - M; +vec3 hue2rgb(in float H) { + float R = abs(H * 6.0 - 3.0) - 1.0; + float G = 2.0 - abs(H * 6.0 - 2.0); + float B = 2.0 - abs(H * 6.0 - 4.0); + return clamp(vec3(R,G,B), 0.0, 1.0); +} - if (difference != 0) { - HSV.y = difference / HSV.z; - vec3 delta = (HSV.z - colorRGB) / difference; - delta.rgb -= delta.brg; - delta.rg += vec2(2.0, 4.0); +/** + * Converts RGB color plus chromacity and value to hue value. + * Using the efficient implementation from http://www.chilliant.com/rgb2hsv.html. + * \param RGB color in RGB space + * \param C Chromacity + * \param V Value + * \return The corresponding hue. + */ +float rgbcv2hue(in vec3 RGB, in float C, in float V) { + vec3 delta = (V - RGB) / C; + delta.rgb -= delta.brg; + delta.rgb += vec3(2.0, 4.0, 6.0); + delta.brg = step(V, RGB) * delta.brg; + float H; + H = max(delta.r, max(delta.g, delta.b)); + return fract(H / 6.0); +} - if (colorRGB.r >= HSV.z) - HSV.x = delta.b; - else if (colorRGB.g >= HSV.z) - HSV.x = delta.r; - else - HSV.x = delta.g; +/** + * Converts a color from HSV space to RGB space. + * Using the efficient implementation from http://www.chilliant.com/rgb2hsv.html. + * \param HSV color in HSV space + * \return The given color in RGB space. + */ +vec3 hsv2rgb(in vec3 HSV) { + vec3 RGB = hue2rgb(HSV.x); + return ((RGB - 1.0) * HSV.y + 1.0) * HSV.z; +} - HSV.x = fract(HSV.x / 6.0); +/** + * Converts a color from HSL space to RGB space. + * Using the efficient implementation from http://www.chilliant.com/rgb2hsv.html. + * \param HSL color in HSL space + * \return The given color in RGB space. + */ +vec3 hsl2rgb(in vec3 HSL) { + vec3 RGB = hue2rgb(HSL.x); + float C = (1.0 - abs(2.0 * HSL.z - 1.0)) * HSL.y; + return (RGB - 0.5) * C + HSL.z; +} + +/** + * Converts a color from HCY space to RGB space. + * Using the efficient implementation from http://www.chilliant.com/rgb2hsv.html. + * \param HCY color in HCY space + * \return The given color in RGB space. + */ +vec3 hcy2rgb(in vec3 HCY) { + vec3 RGB = hue2rgb(HCY.x); + float Z = dot(RGB, HCYwts_); + if (HCY.z < Z) { + HCY.y *= HCY.z / Z; + } + else if (Z < 1.0) { + HCY.y *= (1.0 - HCY.z) / (1 - Z); } + return (RGB - vec3(Z, Z, Z)) * HCY.y + HCY.z; +} +/** + * Converts a color from RGB space to HSV space. + * Using the efficient implementation from http://www.chilliant.com/rgb2hsv.html. + * \param RGB color in RGB space + * \return The given color in HSV space. + */ +vec3 rgb2hsv(in vec3 RGB) { + vec3 HSV = vec3(0.0, 0.0, 0.0); + HSV.z = max(RGB.r, max(RGB.g, RGB.b)); + float M = min(RGB.r, min(RGB.g, RGB.b)); + float C = HSV.z - M; + if (C != 0) { + HSV.x = rgbcv2hue(RGB, C, HSV.z); + HSV.y = C / HSV.z; + } return HSV; } - /** - * Converts a color from HSV space to RGB space. - * Using the efficient implementation from http://chilliant.blogspot.de/2010/11/rgbhsv-in-hlsl.html. - * \param colorHSV color in HSV space. - * \return The given color in RGB space. + * Converts a color from RGB space to HSL space. + * Using the efficient implementation from http://www.chilliant.com/rgb2hsv.html. + * \param RGB color in RGB space + * \return The given color in HSL space. */ -vec3 hsv2rgb(vec3 colorHSV) { - float R = abs(colorHSV.x * 6.0 - 3.0) - 1.0; - float G = 2.0 - abs(colorHSV.x * 6.0 - 2.0); - float B = 2.0 - abs(colorHSV.x * 6.0 - 4.0); - - vec3 toReturn = clamp(vec3(R, G, B), 0.0, 1.0); - return ((toReturn - 1.0) * colorHSV.y + 1.0) * colorHSV.z; +vec3 rgb2hsl(in vec3 RGB) { + vec3 HSL = vec3(0.0, 0.0, 0.0); + float U, V; + U = -min(RGB.r, min(RGB.g, RGB.b)); + V = max(RGB.r, max(RGB.g, RGB.b)); + HSL.z = (V - U) * 0.5; + float C = V + U; + if (C != 0) { + HSL.x = rgbcv2hue(RGB, C, V); + HSL.y = C / (1.0 - abs(2.0 * HSL.z - 1.0)); + } + return HSL; } +/** + * Converts a color from RGB space to HCY space. + * Using the efficient implementation from http://www.chilliant.com/rgb2hsv.html. + * \param RGB color in RGB space + * \return The given color in HCY space. + */ +vec3 rgb2hcy(in vec3 RGB) { + vec3 HCY = vec3(0.0, 0.0, 0.0); + float U, V; + U = -min(RGB.r, min(RGB.g, RGB.b)); + V = max(RGB.r, max(RGB.g, RGB.b)); + HCY.y = V + U; + HCY.z = dot(RGB, HCYwts_); + if (HCY.y != 0) { + HCY.x = rgbcv2hue(RGB, HCY.y, V); + float Z = dot(hue2rgb(HCY.x), HCYwts_); + if (HCY.z > Z) { + HCY.z = 1 - HCY.z; + Z = 1 - Z; + } + HCY.y *= Z / HCY.z; + } + return HCY; +} + /** * Converts a color from RGB space to CIEXYZ space. * \see http://wiki.labomedia.org/images/1/10/Orange_Book_-_OpenGL_Shading_Language_2nd_Edition.pdf diff --git a/modules/advancedusvis/glsl/advancedusfusion.frag b/modules/advancedusvis/glsl/advancedusfusion.frag index 0ca8aa79..d0b9cc97 100644 --- a/modules/advancedusvis/glsl/advancedusfusion.frag +++ b/modules/advancedusvis/glsl/advancedusfusion.frag @@ -67,10 +67,25 @@ void main() { case 3: out_Color = lookupTF(_transferFunction, texel.a); vec3 hsv = rgb2hsv(out_Color.xyz); + hsv.x = 0.15; hsv.y = 1.0 - confidence; out_Color.xyz = hsv2rgb(hsv); break; case 4: + out_Color = lookupTF(_transferFunction, texel.a); + vec3 hsl = rgb2hsl(out_Color.xyz); + hsl.x = 0.15; + hsl.y = 1.0 - confidence; + out_Color.xyz = hsl2rgb(hsl); + break; + case 5: + out_Color = lookupTF(_transferFunction, texel.a); + vec3 hcy = rgb2hcy(out_Color.xyz); + hcy.x = 0.15; + hcy.y = 1.0 - confidence; + out_Color.xyz = hcy2rgb(hcy); + break; + case 6: float intensity = mix(blurred.a, 2.0 * texel.a - blurred.a, confidence); out_Color = lookupTF(_transferFunction, intensity); break; diff --git a/modules/advancedusvis/processors/advancedusfusion.cpp b/modules/advancedusvis/processors/advancedusfusion.cpp index 11f8852a..28602a43 100644 --- a/modules/advancedusvis/processors/advancedusfusion.cpp +++ b/modules/advancedusvis/processors/advancedusfusion.cpp @@ -44,11 +44,13 @@ namespace campvis { const std::string AdvancedUsFusion::loggerCat_ = "CAMPVis.modules.vis.AdvancedUsFusion"; - GenericOption viewOptions[5] = { + GenericOption viewOptions[7] = { GenericOption("us", "Ultrasound Only"), GenericOption("smoothed", "Smoothed US Only"), GenericOption("sharpened", "Sharpened US Only"), - GenericOption("mappingSaturation", "Mapping Uncertainty to Saturation"), + GenericOption("mappingSaturationHSV", "Mapping Uncertainty to Saturation (HSV)"), + GenericOption("mappingSaturationHSL", "Mapping Uncertainty to Saturation (HSL)"), + GenericOption("mappingChromacity", "Mapping Uncertainty to Chromacity"), GenericOption("mappingSharpness", "Mapping Uncertainty to Sharpness") }; @@ -61,7 +63,7 @@ namespace campvis { , p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE) , p_sliceNumber("sliceNumber", "Slice Number", 0, 0, 0) , p_transferFunction("transferFunction", "Transfer Function", new SimpleTransferFunction(256)) - , p_view("View", "Image to Render", viewOptions, 5) + , p_view("View", "Image to Render", viewOptions, 7) , p_blurredScaling("BlurredScaling", "Scaling for blurred image intensity", 1.f, .001f, 1000.f) , _shader(0) { -- GitLab