OpenCV4入门039:图像查找表(LUT)

索引地址:系列教程索引地址

LUT指显示查找表(Look-Up-Table),本质上就是一个RAM。它把数据事先写入RAM后,每当输入一个信号就等于输入一个地址进行查表,找出地址对应的内容,然后输出。

LUT的应用范围比较广泛,例如:LUT(Look-Up Table)可以应用到一张像素灰度值的映射表,它将实际采样到的像素灰度值经过一定的变换如阈值、反转、二值化、对比度调整、线性变换等,变成了另外一个与之对应的灰度值,这样可以起到突出图像的有用信息,增强图像的光对比度的作用。

很多PC系列卡具有8/10/12/16甚到32位的LUT,具体在LUT里进行什么样的变换是由软件来定义的。在这里LUT最重要的意义,就在于兼容了普通显示器的高阶显示功能,使得那些不能被普通显示器所显示的宽色域(一般指超过srgb)能够尽量被大致模拟在普通显示器上。然而,lut所模拟的效果,只能作为参考,作为修图时的大致观感。最佳、最完整的呈现,仍然是显示器、显卡以及素材本身的各项指标高度一致,所谓“硬解码”。

原理

函数原型为:

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

参数说明:

  • 该函数的第一个输入参数要求的数据类型必须是CV_8U类型,但是可以是多通道的图像矩阵。
  • 第二个参数根据其参数说明可以知道输入量是一个1×256的矩阵,其中存放着每个像素灰度值映射后的数值,其形式如下表所示。如果第二个参数是单通道,则输入变量中的每个通道都按照一个LUT查找表进行映射;如果第二个参数是多通道,则输入变量中的第i个通道按照第二个参数的第i个通道LUT查找表进行映射。与之前的函数不同,函数输出图像的数据类型不与原图像的数据类型保持一致,而是和LUT查找表的数据类型保持一致,这是因为将原灰度值映射到新的空间中,因此需要与新空间中的数据类型保持一致。
  • dst:输出图像矩阵,其尺寸与src相同,数据类型与lut相同。

比如说:

原灰度值
00
10
20
30
40
0
1000
1011
1021
1031
1
2001
2012
2022
2
2552

如果是普通的三通道彩色图,每个通道都是这种操作

RGB
原R像素值新值原G像素值原B像素值
000000
101010
202020
303030
404040
000
100010001000
101110111011
102110211021
103110311031
111
200120012001
201220122012
202220222022
222
255225522552

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int agrc, char **agrv) {
// LUT查找表第一层
uchar lutFirst[ 256 ];
for (int i = 0; i < 256; i++) {
if (i <= 100)
lutFirst[ i ] = 0;
if (i > 100 && i <= 200)
lutFirst[ i ] = 100;
if (i > 200)
lutFirst[ i ] = 255;
}
Mat lutOne(1, 256, CV_8UC1, lutFirst);

// LUT查找表第二层
uchar lutSecond[ 256 ];
for (int i = 0; i < 256; i++) {
if (i <= 100)
lutSecond[ i ] = 0;
if (i > 100 && i <= 150)
lutSecond[ i ] = 100;
if (i > 150 && i <= 200)
lutSecond[ i ] = 150;
if (i > 200)
lutSecond[ i ] = 255;
}
Mat lutTwo(1, 256, CV_8UC1, lutSecond);

// LUT查找表第三层
uchar lutThird[ 256 ];
for (int i = 0; i < 256; i++) {
if (i <= 100)
lutThird[ i ] = 100;
if (i > 100 && i <= 200)
lutThird[ i ] = 200;
if (i > 200)
lutThird[ i ] = 255;
}
Mat lutThree(1, 256, CV_8UC1, lutThird);

//拥有三通道的LUT查找表矩阵
vector<Mat> mergeMats;
mergeMats.push_back(lutOne);
mergeMats.push_back(lutTwo);
mergeMats.push_back(lutThree);
Mat LutTree;
merge(mergeMats, LutTree);

//计算图像的查找表
Mat img = imread("1.jpg");
if (img.empty()) {
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}

Mat gray, out0, out1, out2;
cvtColor(img, gray, COLOR_BGR2GRAY);
LUT(gray, lutOne, out0);
LUT(img, lutOne, out1);
LUT(img, LutTree, out2);
imshow("out0", out0);
imshow("out1", out1);
imshow("out2", out2);
waitKey(0);
return 0;
}

测试结果:

lut