# cv::LUT API (Look Up Table)

# 1.介绍

cv::LUTOpenCV中实现的自带颜色表操作,实现数组的查表变换。将输入数组src根据变换表lut变换得到dst。其实现作用过程如下图:

其应用主要是空间换时间,可以减少运算量,如对图像应用gamma校正时可以将0-255的计算结果存储在lut中,利用查表实现gamma变换。

# 2.cv::LUT API

void cv::LUT(InputArray src,
             InputArray lut,
             OutputArray dst );

cv::LUT (opens new window) API 在头文件#include <opencv2/core.hpp>

值得注意的是,lut256个元素的数组,当src是单通道数组如CV_8UC1时,lut必须是单通道的,当src是多通道数组时如CV_8UC3,lut可以是单通道,也可以与src有同样的通道。与src同通道数时可以实现对src不同通道实现不同的查找表。其LUT源码 (opens new window)如下:

LUT8u_( const uchar* src, const T* lut, T* dst, int len, int cn, int lutcn )
{
    if( lutcn == 1 )
    {
        for( int i = 0; i < len*cn; i++ )
            dst[i] = lut[src[i]];
    }
    else
    {
        for( int i = 0; i < len*cn; i += cn )
            for( int k = 0; k < cn; k++ )
                dst[i+k] = lut[src[i+k]*cn+k];
    }
}

# 3.应用实例

void test_lut( void )
{
    cv::Mat lut1(1, 256, CV_8UC1);
    cv::Mat lut3(1, 256, CV_8UC3);
    float gamma = 4.2;
    for(int i=0; i<256; i++) {
        unsigned char c = (unsigned char)(exp(log((float)i/255.)*gamma) * 255);
        lut1.at<unsigned char>(0, i) = c;
        lut3.at<cv::Vec3b>(i) = cv::Vec3b(c, c+1, c+2);
    }
    std::cout << "lut3: " << lut3 << std::endl;
    cv::Mat src = (cv::Mat3b(2,2) << cv::Vec3b(1,1,3), \
                                       cv::Vec3b(4,8,9), \
                                       cv::Vec3b(65,4,4), \
                                       cv::Vec3b(253,253,253));
    std::cout << "src:" << src << std::endl;

    cv::Mat dst;
    cv::LUT(src, lut1, dst);
    std::cout << "dst1: " << dst << std::endl;
   
    cv::LUT(src, lut3, dst);
    std::cout << "dst3: " << dst << std::endl;  
    /** output
     * lut1 在253处对应的值为246
     * lut3 在253处对应的CV——8UC3为 246,247,248
     * src:
        [  1,   1,   3,   4,   8,   9;
        65,   4,   4, 253, 253, 253]
    dst1: 
        [  0,   0,   0,   0,   0,   0;
        0,   0,   0, 246, 246, 246]
    dst3: 
        [  0,   1,   2,   0,   1,   2;
        0,   1,   2, 246, 247, 248]
    
    */   
}

此外,OpenCV中伪彩色变换也通过类似LUT的方式实现,如下代码通过createTrackBar回调实现不同类型的applyColorMap (opens new window)

static void onTrackBarChanged(int value, void *userdata) 
{
    const auto &data = *static_cast<UserData*>(userdata);
    cv::Mat mask_image = cv::Mat::zeros(data.image->size(), CV_8UC3);
    mask_image = cv::Scalar((uint8_t)value, (uint8_t)value, (uint8_t)value);
    cv::add(*data.image, mask_image, mask_image);
    cv::applyColorMap(*data.image, mask_image, value);
    cv::imshow("COLORMAP_LUT", mask_image);
}

void show() const
{
    cv::Mat image = cv::imread(m_image_name);
    printf("Image %s\n", m_image_name);
    cv::Mat mask_image;
    if(image.empty())
        printf("%s is empty\n", m_image_name);
    int colormap = 1;
    cv::namedWindow("COLORMAP_LUT", cv::WINDOW_AUTOSIZE);
    char trackerBarName[50];
    sprintf(trackerBarName, "colormap %d", 1);
    UserData userData;
    userData.image = &image;
    cv::imshow("COLORMAP_LUT", image);
    cv::createTrackbar(trackerBarName, "COLORMAP_LUT", &colormap, \
                        11, onTrackBarChanged, &userData);
    cv::waitKey(0);
    cv::destroyAllWindows();    
}

(adsbygoogle = window.adsbygoogle || []).push({});

# 参考资料