OpenCV4入门系列教程34:图像查找表(LUT)

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

上一篇:OpenCV4入门系列教程测试4:简单文字切割

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
...0...0...0
100010001000
101110111011
102110211021
103110311031
...1...1...1
200120012001
201220122012
202220222022
...2...2...2
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

下一篇:OpenCV4入门系列教程35:图像通道合并与分离