Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

xVict
Hi All!
When vtkImageMapToWindowLevelColors  using lookupTable,
in the method:
template <class T>
void vtkImageMapToWindowLevelColorsExecute(
  vtkImageMapToWindowLevelColors *self,
  vtkImageData *inData, T *inPtr,
  vtkImageData *outData,
  unsigned char *outPtr,
  int outExt[6], int id)

in the condition ( line: 323 in master from (<42f7955511> 2018-05-23 [David
E. DeMarle])):

if ( lookupTable )
      {
        lookupTable->MapScalarsThroughTable2(
          inPtr1,
          static_cast<unsigned char *>(outPtr1),
          dataType,extX,numberOfComponents,
          outputFormat);

        for (idxX = 0; idxX < extX; idxX++)

the for-loop is not needed. It spoils the rgb values expected from the
lookupTable.
I don't understand:

          *optr = static_cast<unsigned char>((*optr * ushort_val) >> 8);

gray = linear conversion of values from the specified window level to range
0-255

r_out = r * gray / 256
g_out = g * gray / 256
b_out = b * gray / 256

I propose to remove this for-loop. I.e., lines: 331 - 367.
After it for example user's lookuptable correctly applied for imageViwer2.

Sincerely, Victor.



--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Dev-f1251487.html
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

David E DeMarle
Can you tell us more about the failure conditions?

I strongly suspect the code is correct. git blame indicates that it has been doing this scaling and biasing with minor variations since 2000.

Try running the tests locally with your proposed change. Test failures should indicate use cases of the existing code path.



David E DeMarle
Kitware, Inc.
Principal Engineer
21 Corporate Drive
Clifton Park, NY 12065-8662
Phone: 518-881-4909

On Fri, May 25, 2018 at 6:27 AM, xVict <[hidden email]> wrote:
Hi All!
When vtkImageMapToWindowLevelColors  using lookupTable,
in the method:
template <class T>
void vtkImageMapToWindowLevelColorsExecute(
  vtkImageMapToWindowLevelColors *self,
  vtkImageData *inData, T *inPtr,
  vtkImageData *outData,
  unsigned char *outPtr,
  int outExt[6], int id)

in the condition ( line: 323 in master from (<42f7955511> 2018-05-23 [David
E. DeMarle])):

if ( lookupTable )
      {
        lookupTable->MapScalarsThroughTable2(
          inPtr1,
          static_cast<unsigned char *>(outPtr1),
          dataType,extX,numberOfComponents,
          outputFormat);

        for (idxX = 0; idxX < extX; idxX++)

the for-loop is not needed. It spoils the rgb values expected from the
lookupTable.
I don't understand:

          *optr = static_cast<unsigned char>((*optr * ushort_val) >> 8);

gray = linear conversion of values from the specified window level to range
0-255

r_out = r * gray / 256
g_out = g * gray / 256
b_out = b * gray / 256

I propose to remove this for-loop. I.e., lines: 331 - 367.
After it for example user's lookuptable correctly applied for imageViwer2.

Sincerely, Victor.



--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Dev-f1251487.html
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers



_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

xVict
Hi David!

Some code skeleton:
// Image viewer creation
    this->imgViewer       = vtkSmartPointer<vtkImageViewer2>::New();

// Lut creation
    if (colorLut == nullptr)
        colorLut = vtkSmartPointer<vtkLookupTable>::New();
    int norm = Range[1] - Range[0] + 1;
    colorLut->SetRange(Range[0], Range[1]);
    colorLut->SetIndexedLookup(0);
    colorLut->SetNumberOfTableValues(norm);
    colorLut->Build();
    for (int i = 0; i < norm; i++) {
      double cl = double(i) / (norm - 1);
      colorLut->SetTableValue(i, cl, cl, cl);
    }

// change view option
        double c = 0.5*(this->Range[1] + this->Range[0]);
        double w = 1.0*(this->Range[1] - this->Range[0]);
        this->imgViewer->GetWindowLevel()->SetLevel(c);
        this->imgViewer->GetWindowLevel()->SetWindow(w);
        if (this->optycaltype == PSEUDO_COLOR) {
            createPseudoLUT();
            if (this->imgViewer->GetWindowLevel()->GetLookupTable() ==
nullptr)
                this->imgViewer->GetWindowLevel()->SetLookupTable(colorLut);
        }
        else {
            if (this->imgViewer->GetWindowLevel()->GetLookupTable() !=
nullptr)
                this->imgViewer->GetWindowLevel()->SetLookupTable(nullptr);
        }
        if (this->source != nullptr)
            imgViewer->Render();

For 16bit image this code should show identical picture. But for
PSEUDO_COLOR==8bit-gray (r=g=b in range [0...1] == [0...255]).

Sincerely, Victor.




--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Dev-f1251487.html
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

David Gobbi
Hi xVict,

I've never trusted that code either, a per-component shift and scale only
makes sense to me if the input data is RGB.  I don't understand why
this class applies per-component shift and scale after vtkLookupTable.

Can anyone explain what's going on in this code?

 - David
 

On Fri, May 25, 2018 at 8:53 AM, xVict <[hidden email]> wrote:
Hi David!

Some code skeleton:
// Image viewer creation
    this->imgViewer       = vtkSmartPointer<vtkImageViewer2>::New();

// Lut creation
    if (colorLut == nullptr)
        colorLut = vtkSmartPointer<vtkLookupTable>::New();
    int norm = Range[1] - Range[0] + 1;
    colorLut->SetRange(Range[0], Range[1]);
    colorLut->SetIndexedLookup(0);
    colorLut->SetNumberOfTableValues(norm);
    colorLut->Build();
    for (int i = 0; i < norm; i++) {
      double cl = double(i) / (norm - 1);
      colorLut->SetTableValue(i, cl, cl, cl);
    }

// change view option
        double c = 0.5*(this->Range[1] + this->Range[0]);
        double w = 1.0*(this->Range[1] - this->Range[0]);
        this->imgViewer->GetWindowLevel()->SetLevel(c);
        this->imgViewer->GetWindowLevel()->SetWindow(w);
        if (this->optycaltype == PSEUDO_COLOR) {
            createPseudoLUT();
            if (this->imgViewer->GetWindowLevel()->GetLookupTable() ==
nullptr)
                this->imgViewer->GetWindowLevel()->SetLookupTable(colorLut);
        }
        else {
            if (this->imgViewer->GetWindowLevel()->GetLookupTable() !=
nullptr)
                this->imgViewer->GetWindowLevel()->SetLookupTable(nullptr);
        }
        if (this->source != nullptr)
            imgViewer->Render();

For 16bit image this code should show identical picture. But for
PSEUDO_COLOR==8bit-gray (r=g=b in range [0...1] == [0...255]).

Sincerely, Victor.

_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

David Gobbi
I'm going to try to answer my own question, hopefully someone
will jump in and correct me if I am wrong.

The idea behind vtkImageMapToWindowLevelColors seems to
be that the vtkLookupTable is intended to map the input values
to different hues (using whatever Range was specified), and
then the Window/Level is used to adjust the luminance.

My own typical use of VTK is medical image display, using
16-bit input images.  So I want the window/level to be applied
directly to the 16-bit values.  I definitely do not want to convert
my 16-bit values to 8-bit, and then rescale each 8-bit value
according to where the 16-bit value sits in the Window/Level.
But this seems to be what vtkImageMapToWindowLevelColors
does.

 - David


On Fri, May 25, 2018 at 12:02 PM, David Gobbi <[hidden email]> wrote:
Hi xVict,

I've never trusted that code either, a per-component shift and scale only
makes sense to me if the input data is RGB.  I don't understand why
this class applies per-component shift and scale after vtkLookupTable.

Can anyone explain what's going on in this code?

 - David
 

On Fri, May 25, 2018 at 8:53 AM, xVict <[hidden email]> wrote:
Hi David!

Some code skeleton:
// Image viewer creation
    this->imgViewer       = vtkSmartPointer<vtkImageViewer2>::New();

// Lut creation
    if (colorLut == nullptr)
        colorLut = vtkSmartPointer<vtkLookupTable>::New();
    int norm = Range[1] - Range[0] + 1;
    colorLut->SetRange(Range[0], Range[1]);
    colorLut->SetIndexedLookup(0);
    colorLut->SetNumberOfTableValues(norm);
    colorLut->Build();
    for (int i = 0; i < norm; i++) {
      double cl = double(i) / (norm - 1);
      colorLut->SetTableValue(i, cl, cl, cl);
    }

// change view option
        double c = 0.5*(this->Range[1] + this->Range[0]);
        double w = 1.0*(this->Range[1] - this->Range[0]);
        this->imgViewer->GetWindowLevel()->SetLevel(c);
        this->imgViewer->GetWindowLevel()->SetWindow(w);
        if (this->optycaltype == PSEUDO_COLOR) {
            createPseudoLUT();
            if (this->imgViewer->GetWindowLevel()->GetLookupTable() ==
nullptr)
                this->imgViewer->GetWindowLevel()->SetLookupTable(colorLut);
        }
        else {
            if (this->imgViewer->GetWindowLevel()->GetLookupTable() !=
nullptr)
                this->imgViewer->GetWindowLevel()->SetLookupTable(nullptr);
        }
        if (this->source != nullptr)
            imgViewer->Render();

For 16bit image this code should show identical picture. But for
PSEUDO_COLOR==8bit-gray (r=g=b in range [0...1] == [0...255]).

Sincerely, Victor.


_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

xVict
Hi David!

1. We want to show the medical image correctly
As a starting point, consider an example:
https://lorensen.github.io/VTKExamples/site/Cxx/IO/ReadDICOM/
We have next pipeline:
vtkDICOMImageReader->vtkImageViewer2
By mouse we can change windowLevel and windowWidth.
ImageViewer2 internally transform 16bit input gray to output r=g=b color
into the render window.
Internally ImageViewer2 use vtkImageMapToWindowLevelColors for window-level.

2. I want use the same transformation but with LUT for 10-bit monitor.
Because I pass my LUT to this class.
imgViewer->GetWindowLevel()->SetLookupTable(colorLut);
And for tests I using LUT with r=g=b.
If that's wrong, correct me. (Specify the correct example to display 16-bit
images on a 10-bit monitor).
But this does not exclude the incomprehensible code in the
vtkImageMapToWindowLevelColors class. Values less than 16 go to zero.

Victor



--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Dev-f1251487.html
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

David Gobbi
Hi Victor,

I've written dozens of VTK apps for medical image visualization,
and I haven't used vtkImageViewer2 for any of them, nor have I
ever used vtkImageMapToWindowLevelColors.  I've always used
one of the following approaches:

1) Generate an RGB or RGBA image with vtkImageMapToColors,
 (use the Range of vtkLookupTable to control the window/level),
 put the image in a vtkTexture, and then apply the texture to a
 rectangular polygon.  This is for 2D images or for image slices
 extracted from a volume with vtkImageReslice.
 
2) Same as above, but with vtkImageActor instead of vtkTexture.

3) Recently, I've switched to a new set of classes that I wrote for VTK:


VTK's colors are 8-bit, meaning 24-bit RGB or 32-bit RGBA. If you
need something for a 10-bit monitor, that might be difficult.  You
wouldn't be able to use vtkLookupTable, because even though you
sets its color components as values in the range [0.0, 1.0], it stores
the values as integers with a range of [0,255].

 - David


On Fri, May 25, 2018 at 3:08 PM, xVict <[hidden email]> wrote:
Hi David!

1. We want to show the medical image correctly
As a starting point, consider an example:
https://lorensen.github.io/VTKExamples/site/Cxx/IO/ReadDICOM/
We have next pipeline:
vtkDICOMImageReader->vtkImageViewer2
By mouse we can change windowLevel and windowWidth.
ImageViewer2 internally transform 16bit input gray to output r=g=b color
into the render window.
Internally ImageViewer2 use vtkImageMapToWindowLevelColors for window-level.

2. I want use the same transformation but with LUT for 10-bit monitor.
Because I pass my LUT to this class.
imgViewer->GetWindowLevel()->SetLookupTable(colorLut);
And for tests I using LUT with r=g=b.
If that's wrong, correct me. (Specify the correct example to display 16-bit
images on a 10-bit monitor).
But this does not exclude the incomprehensible code in the
vtkImageMapToWindowLevelColors class. Values less than 16 go to zero.

Victor

_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

xVict
Hi David,

To test the vtkImageMapToWindowLevelColors class the sources was uploaded on
GitHub:
https://github.com/xThorn/vtk-tests
See mapToWLC folder.

By first item: can I set texture type GL_UNSIGNED_INT_2_10_10_10_REV?

In https://www.vtk.org/Wiki/VTK/Image_Rendering_Classes

Many greyscale monitors with DVI inputs use the equation L = 0.30*R + 0.59*G
+ 0.11B to convert the 24-bit RGB DVI signal into a greyscale signal. For
such monitors, it is possible to create a vtkLookupTable with 4096 entries
that provides distinct greyscale values via appropriately-chosen RGB values.

This method works through GDI.

Victor.



--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Dev-f1251487.html
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

David Gobbi
Hi Victor,

I have updated the vtkImageMapToWindowLevelColors documentation according to my understanding of how it works:
Honestly I think the class would be better without the "color modulation" feature.  If you are displaying grayscale, you can use the class without a lookup table.

It might be possible to set GL_UNSIGNED_INT_2_10_10_10_REV in VTK if you make your own frame buffer object, but you can't use it with any of the usual image viewers or image mappers that are already in VTK, since they all assume 8 bits per color component for the display.  The luminance via RGB trick should work fine if you have a suitable grayscale monitor with RGB input.

 - David



On Tue, May 29, 2018 at 3:21 AM, xVict <[hidden email]> wrote:
Hi David,

To test the vtkImageMapToWindowLevelColors class the sources was uploaded on
GitHub:
https://github.com/xThorn/vtk-tests
See mapToWLC folder.

By first item: can I set texture type GL_UNSIGNED_INT_2_10_10_10_REV?

In https://www.vtk.org/Wiki/VTK/Image_Rendering_Classes

Many greyscale monitors with DVI inputs use the equation L = 0.30*R + 0.59*G
+ 0.11B to convert the 24-bit RGB DVI signal into a greyscale signal. For
such monitors, it is possible to create a vtkLookupTable with 4096 entries
that provides distinct greyscale values via appropriately-chosen RGB values.

This method works through GDI.

Victor.



--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Dev-f1251487.html
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers



_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

David Gobbi
According to the VTK testing dashboard, removing the "color modulation" code does not cause any VTK to fail, see the "CDash" link on the following page:

So there isn't any code in VTK that relies on the old behavior of vtkImageMapToWindowLevelColors.  I also looked at the image rendering code in 3D Slicer.  Interestingly, it uses this class without a lookup table, and then applies a lookup table to the resulting 8-bit data (so a two-stage process, vtkImageMapToWindowLevelColors to generate 8-bit data, followed by vtkImageMapToColors with a 256-entry lookup table to generate color data).  So apparently the Slicer folks found the LUT behavior of this class to be not useful, and had to added extra stage to their pipeline to apply the LUT.

Does anyone out there use the color modulation feature of vtkImageMapToWindowLevelColors?

 - David


On Wed, May 30, 2018 at 8:56 AM, David Gobbi <[hidden email]> wrote:
Hi Victor,

I have updated the vtkImageMapToWindowLevelColors documentation according to my understanding of how it works:
Honestly I think the class would be better without the "color modulation" feature.  If you are displaying grayscale, you can use the class without a lookup table.

It might be possible to set GL_UNSIGNED_INT_2_10_10_10_REV in VTK if you make your own frame buffer object, but you can't use it with any of the usual image viewers or image mappers that are already in VTK, since they all assume 8 bits per color component for the display.  The luminance via RGB trick should work fine if you have a suitable grayscale monitor with RGB input.

 - David



On Tue, May 29, 2018 at 3:21 AM, xVict <[hidden email]> wrote:
Hi David,

To test the vtkImageMapToWindowLevelColors class the sources was uploaded on
GitHub:
https://github.com/xThorn/vtk-tests
See mapToWLC folder.

By first item: can I set texture type GL_UNSIGNED_INT_2_10_10_10_REV?

In https://www.vtk.org/Wiki/VTK/Image_Rendering_Classes

Many greyscale monitors with DVI inputs use the equation L = 0.30*R + 0.59*G
+ 0.11B to convert the 24-bit RGB DVI signal into a greyscale signal. For
such monitors, it is possible to create a vtkLookupTable with 4096 entries
that provides distinct greyscale values via appropriately-chosen RGB values.

This method works through GDI.

Victor.



--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Dev-f1251487.html
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://vtk.org/mailman/listinfo/vtk-developers




_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers

Reply | Threaded
Open this post in threaded view
|

Re: Incorrect color function in vtkImageMapToWindowLevelColors with lookupTable

xVict
Hi David!

This is good news.

If anyone uses color modulation, I thought about writing a proposal to make
modulation optional.
https://github.com/xThorn/vtk-tests/blob/master/mapToWLC/issue/vtkImageMapToWindowLevelColors.h
https://github.com/xThorn/vtk-tests/blob/master/mapToWLC/issue/vtkImageMapToWindowLevelColors.cxx

Victor.




--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Dev-f1251487.html
_______________________________________________
Powered by www.kitware.com

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Search the list archives at: http://markmail.org/search/?q=vtk-developers

Follow this link to subscribe/unsubscribe:
https://public.kitware.com/mailman/listinfo/vtk-developers