LookUp Table for 16-Bit Mat Efficient way?
Asked Answered
C

2

1

I want to reduce a 16-Bit Mat using opencv. I tried to use opencv LUT function to reduce this mat. But it seems like it wont support 16-Bit Mat. What is the efficient way of reducing a 16-Bit Mat using opencv c++? Any help is appreciated!

e.g I want to scan & reduce all the pixels by 10 Grey levels! I want to implement the same example given in the opencv documentation for 16-Bit Mat.

How to access each element of Mat through Pointers?

Conventual answered 24/11, 2014 at 6:10 Comment(3)
Can you give more details about "reduce" means here ?Grigg
You could build your own look-up table using a Mat with type int.Grigg
Yes we can! But how to access that using pointers? can you elaborate your ans?Conventual
C
0

Thank you for helping me to solve this problem! Here is my code for 16-Bit Look up table based reduction. hope this might be useful for someone!

main()
{
    Size Img_Size(320,240);
    Mat Img_Source_16(Size(320,240),CV_16UC1,Scalar::all(0));
    Mat Img_Destination_16(Size(320,240),CV_16UC1,Scalar::all(0));

    unsigned short LookupTable[4096];
    for (int i = 0; i < 4096; i++)
    {
        LookupTable[i]= 4096-i;
    }

    int i=0;
    for (int Row = 0; Row < Img_Size.height; Row++)
    {
        for (int Col = 0; Col < Img_Size.width; Col++)
        {
            Img_Source_16.at<short>(Row,Col)= i;
            i++;
            if(i>=4095)
                i=0;
        }
    }

    imshow("Img_Source",Img_Source_16);

    t1.start();
    Img_Destination_16= ScanImageAndReduceC_16UC1(Img_Source_16.clone(),LookupTable);

    imshow("Img_Destination",Img_Destination_16);
    t1.stop();
}

Mat& ScanImageAndReduceC_16UC1(Mat& I, const unsigned short* const table)
{
    // accept only char type matrices
    CV_Assert(I.depth() != sizeof(uchar));

    int channels = I.channels();

    int nRows = I.rows;
    int nCols = I.cols * channels;

    if (I.isContinuous())
    {
        nCols *= nRows;
        nRows = 1;
    }

    int i,j;
    unsigned short* p = (unsigned short*)I.data;
    for( unsigned int i =0; i < nCols*nRows; ++i)
        *p++ = table[*p];

    return I;
}
Conventual answered 1/12, 2014 at 9:29 Comment(0)
B
1

The source code of LUT is in this file: https://github.com/Itseez/opencv/blob/fd59551ff0648d33568d7fc63164bf86c5d3ccb6/modules/core/src/convert.cpp

OpenCV can use several methods for performing lookup-table transforms efficiently: it can use Intel IPP library (class IppLUTParallelBody_LUTCN, for 3 or 4-channel images). If have Intel IPP, you can just copy the code of this class and use ippiLUTPalette_16u_C3R instead of ippiLUTPalette_8u_C3R +fix initialization).

Another possible way is OpenCL library (for GPU), it's invoked from ocl_LUT (sorry, have no experience with it, so I can't give any advice).

Or it uses LUTParallelBody/IppLUTParallelBody_LUTCN classes (corresponding to single and multichannel images). These classes use LUT8u_ template function. No rocket science here: it just iterates over the image a substitutes the values. So you can simply copy and paste IppLUTParallelBody and use slightly different function inside the loop. ParallelLoopBody base class uses a library like OpenMP or Intel TBB to run the loop in multiple threads. I suppose, you don't have to modify anything in it to make it work with new function.

Bloomery answered 24/11, 2014 at 7:20 Comment(0)
C
0

Thank you for helping me to solve this problem! Here is my code for 16-Bit Look up table based reduction. hope this might be useful for someone!

main()
{
    Size Img_Size(320,240);
    Mat Img_Source_16(Size(320,240),CV_16UC1,Scalar::all(0));
    Mat Img_Destination_16(Size(320,240),CV_16UC1,Scalar::all(0));

    unsigned short LookupTable[4096];
    for (int i = 0; i < 4096; i++)
    {
        LookupTable[i]= 4096-i;
    }

    int i=0;
    for (int Row = 0; Row < Img_Size.height; Row++)
    {
        for (int Col = 0; Col < Img_Size.width; Col++)
        {
            Img_Source_16.at<short>(Row,Col)= i;
            i++;
            if(i>=4095)
                i=0;
        }
    }

    imshow("Img_Source",Img_Source_16);

    t1.start();
    Img_Destination_16= ScanImageAndReduceC_16UC1(Img_Source_16.clone(),LookupTable);

    imshow("Img_Destination",Img_Destination_16);
    t1.stop();
}

Mat& ScanImageAndReduceC_16UC1(Mat& I, const unsigned short* const table)
{
    // accept only char type matrices
    CV_Assert(I.depth() != sizeof(uchar));

    int channels = I.channels();

    int nRows = I.rows;
    int nCols = I.cols * channels;

    if (I.isContinuous())
    {
        nCols *= nRows;
        nRows = 1;
    }

    int i,j;
    unsigned short* p = (unsigned short*)I.data;
    for( unsigned int i =0; i < nCols*nRows; ++i)
        *p++ = table[*p];

    return I;
}
Conventual answered 1/12, 2014 at 9:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.