# cv::LUT API (Look Up Table)
# 1.介绍
cv::LUT
是OpenCV
中实现的自带颜色表操作,实现数组的查表变换。将输入数组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>
中
值得注意的是,lut
是256
个元素的数组,当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 = ℑ
cv::imshow("COLORMAP_LUT", image);
cv::createTrackbar(trackerBarName, "COLORMAP_LUT", &colormap, \
11, onTrackBarChanged, &userData);
cv::waitKey(0);
cv::destroyAllWindows();
}