glConvolutionFilter2D and 16 bit luminance data

I’ve written a viewing tool that displays static frames and sequences of FLIR imagery. The image pixel data is loaded per frame and stored in unsigned short array. The dynamic range of the luminance values within the imagery nominally fall within the range [0,4000] (possible range for unsigned shorts is [0,32767]). As a result, there is no visible contrast in almost all of the images.

In order to facilitate viewing of the imagery, I have traditionally resorted to performing a histogram equalization on each and every image frame independently. This helps dramatically and gives a great visualization of the FLIR frame content. This equalization process is computationally expensive as I have to compute the probability density of the luminance values, compute a transformation function, then apply that transformation function to an image. All of this has to be done every single frame …

I have a background in image processing so I can design 2D convolution kernels that will enhance the image contrast as I see fit. Before I go off and implement a kernel convolution in code, I thought I would try using glConvolutionFilter2D to do the work for me. I have read that it’s not normally implemented on the GPU but it would be convenient anyway simply because I would not have to write and test code to perform it.

Anyhow, I have been unable to get it to show any effect on the FLIR 16 bit luminance data with any 2D kernel at all. Even using a Sobel or Prewitt, both of which should dramatically effect the image, I can see no net effect of the filtering on the displayed image.

Surely I am just missing something simple here … Maybe I am using the wrong arguments for glConvolutionFilter2D(…) ? My rendering code follows, any help would be appreciated.

Thanks,
Paul Leopard


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Render the current FLIR image

void FLIRViewer::renderFLIR()
{
    // Set to projection and save current state
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    {
        glLoadIdentity();

        GLfloat rawWidth = m_FLIRGrabber.columnCount();
        GLfloat rawHeight = m_FLIRGrabber.rowCount();

        // Setup orthogonal projection to match the image dimensions
        gluOrtho2D(0,rawWidth,0,rawHeight);

        GLfloat scale = 0.84;

        glRasterPos2f(0,rawHeight-1);

        // Turn off pixel path and per-fragment operations that slow down imaging operations
        VaGLOptimizeForImaging();

        // Swap the y-direction of image to top-to-bottom
        glPixelZoom(scale,-scale);

        // Convolve if required
        if (ImageProcessing)
        {
            static GLfloat Kernel[3][3] =
            {
                { 0.0f, -1.0f,  0.0f },
                {-1.0f,  5.0f, -1.0f },
                { 0.0f, -1.0f,  0.0f }
            };

            glConvolutionFilter2D(
                GL_CONVOLUTION_2D,
                GL_LUMINANCE,
                3,
                3,
                GL_LUMINANCE,
                GL_FLOAT,
                Kernel
            );

           glEnable(GL_CONVOLUTION_2D);
        }

        // Draw the pixels
        const unsigned short *pData = a_FLIRImage.get();
        glDrawPixels(rawWidth, rawHeight,GL_LUMINANCE,GL_UNSIGNED_SHORT,pData);

        if (ImageProcessing)
        {
            glDisable(GL_CONVOLUTION_2D);
        }

        // Reset to normal orientation
        glPixelZoom(1, 1);
    }

    // Set to projection and restore state
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
}


Oops …

(possible range for unsigned shorts is [0,32767])

Should be :

(possible range for unsigned shorts is [0,65535])

Bump

Maybe because GL_LUMINANCE is 8 bits; you should probably be using GL_LUMINANCE16 instead?

Yup, that’s it … thanks :slight_smile:

Replace the above with :


            glConvolutionFilter2D(
                GL_CONVOLUTION_2D,
                GL_LUMINANCE16,
                3,
                3,
                GL_LUMINANCE,
                GL_FLOAT,
                Kernel
            );