目录
[1.1 原理](#1.1 原理)
[1.2. 函数参数与限制 (cv::LUT)](#1.2. 函数参数与限制 (cv::LUT))
[2.1. 色彩校正与调色(滤镜)](#2.1. 色彩校正与调色(滤镜))
[2.2. 图像增强(突现缺陷 / 特征)](#2.2. 图像增强(突现缺陷 / 特征))
[2.3. 动态范围压缩(伪彩色成像)](#2.3. 动态范围压缩(伪彩色成像))
[2.4. 实时二值化 / 阈值处理](#2.4. 实时二值化 / 阈值处理)
一、LUT(查表法)基本概念

1.1 原理
它是一种空间映射机制。将原始的像素值(0~255)作为 "索引",去查找一个预先定义好的 "表格"(数组),表格里存的是 "变换后的值"。
- 公式 :
dst[i] = lut[src[i]] - 举例 (对应图中表格):
- 原图灰度值
100→ 查表找到位置 100,值为1→ 输出1。 - 原图灰度值
102→ 查表找到位置 102,值为1→ 输出1。 - 这实际上是把 0~255 的范围进行了降采样 / 分段(每 100 个值合并为 1 个大类)。
- 原图灰度值
1.2. 函数参数与限制 (cv::LUT)
void cv::LUT(InputArray src, InputArray lut, OutputArray dst);
src(输入) :必须是CV_8U类型(即 0~255 的 8 位图像)。这是 LUT 的特性,它只能索引 0~255。lut(查找表) :这是关键的映射规则。- 大小 :必须是 256 个元素(对应 0~255 的索引)。
- 通道 :
- 单通道 LUT :
1x256或256x1的矩阵。无论输入图像是几通道,所有通道都共用这一个映射规则。 - 多通道 LUT:输入是 3 通道 BGR 图时,LUT 可以是 3x256,分别对应 B、G、R 三个通道的独立映射。
- 单通道 LUT :
dst(输出) :输出图像,尺寸和类型与输入src一致。lut单 / 输入多通道 :当 LUT 是单通道(1 个规则),输入如果是 3 通道图,3 个通道会被统一按这个规则映射。lut多 / 各个通道与输入映射 :当 LUT 是多通道(比如 3 通道),输入是 3 通道图时,B 通道用 LUT 的 B 通道映射,G 通道用 LUT 的 G 通道映射,独立控制。
二、核心应用场景
LUT 法在工业视觉和图像处理中极其常用,主要应用在以下 4 个场景:
2.1. 色彩校正与调色(滤镜)
- 场景:想要给图像添加复古风、胶片风,或者校正摄像头偏色。
- 原理:预制一套符合该风格的 LUT 表,对每张图直接套用,速度极快。
- 价值 :效率极高 。OpenCV 内部是用 optimized 代码实现 LUT 的,执行效率远高于你手动写
for循环遍历每一个像素。
2.2. 图像增强(突现缺陷 / 特征)
- 场景:工业检测中,背景和目标的灰度值相近,难以区分。
- 方法 :
- 对数变换:用于压缩高亮度范围(比如处理过曝的图像)。
- 幂次变换 (Gamma):用于提亮暗部细节。
- 分段线性变换 :比如将某一段很窄的灰度范围拉伸到 0~255,精准提取缺陷区域。
2.3. 动态范围压缩(伪彩色成像)
- 场景:医学影像(X 光、CT)或者红外热成像。这些图像灰度级很少变化,人眼看不清。
- 方法:建立 LUT,将原始的 100 个不同灰度值,映射成 100 种不同的鲜艳颜色(伪彩色),从而让人眼轻松看出差异。
2.4. 实时二值化 / 阈值处理
- 场景:Otsu 二值化后的结果如果不满意,可以手动调整阈值,并把调整后的规则存入 LUT 直接复用。
- 优势:一次计算阈值,后续所有图像毫秒级处理,适合在 Qt 上位机中通过滑动条(Slider)实时调参。
三、使用举例
3.1过曝光图片处理
通过对数或幂变化进行过曝光图片增强处理。
cpp
void createOverexposedImg(const std::string& inputPath, Mat& overexposed, int brightnessGain = 100) {
Mat img = imread(inputPath);
if (img.empty()) { printf("图片读取失败!\n"); return; }
Mat imgHsv;
cvtColor(img, imgHsv, COLOR_BGR2HSV);
// 提亮亮度通道(V)并截断到255,模拟过曝
for (int i = 0; i < imgHsv.rows; i++) {
for (int j = 0; j < imgHsv.cols; j++) {
imgHsv.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(imgHsv.at<Vec3b>(i, j)[2] + brightnessGain);
}
}
cvtColor(imgHsv, overexposed, COLOR_HSV2BGR);
}
// 构建对数变换的LUT对数变换公式:s = c * log(1 + r),归一化到0~255
void createLogLUT(Mat& lut, double c = 1.0) {
lut.create(1, 256, CV_8U);
uchar* p = lut.data;
//
for (int i = 0; i < 256; i++) {
double logVal = c * log(1 + i);
// 归一化:把log结果映射回0~255
double normalized = (logVal / log(256)) * 255;
p[i] = saturate_cast<uchar>(normalized);
}
}
// 构建伽马校正的LUT(γ<1 压缩高光,适合过曝图)伽马变换公式:s = 255 * (r/255)^γ
void createGammaLUT(Mat& lut, double gamma = 0.5) {
lut.create(1, 256, CV_8U);
uchar* p = lut.data;
for (int i = 0; i < 256; i++) {
double normalized = (double)i / 255.0;
double gammaVal = pow(normalized, gamma);
p[i] = saturate_cast<uchar>(gammaVal * 255);
}
}
int testLUT() {
Mat ColorMat;
createOverexposedImg(R"(D:\Study\OpenCvStudy\lean.jpg)", ColorMat,150);
if (ColorMat.empty()) {
cout << "过曝图读取失败!" << endl;
return -1;
}
// 构建LUT
Mat logLUT, gammaLUT;
createLogLUT(logLUT, 1.0); // c=45 调节对数变换强度
createGammaLUT(gammaLUT, 0.6); // γ=0.6 压缩高光、提亮暗部
// 应用LUT(支持彩色图,自动对所有通道生效)
Mat logResult, gammaResult;
LUT(ColorMat, logLUT, logResult);
LUT(ColorMat, gammaLUT, gammaResult);
// 显示对比结果
imshow("0. 原始过曝图", ColorMat);
imshow("1. 对数变换修复(LUT)", logResult);
imshow("2. 伽马校正修复(LUT)", gammaResult);
waitKey(0);
destroyAllWindows();
return 0;
}

3.2图片添加滤镜
复古滤镜(经典黄调 + 低饱和)
效果原理
- 蓝色通道(B):压低亮度(旧照片偏黄);
- 绿色通道(G):适度提亮(保留细节);
- 红色通道(R):轻微提亮(暖调);
- 整体降低高亮度区间的对比度,模拟胶片质感。
cpp
void createRetroLUT(Mat & lut) {
lut.create(256, 1, CV_8UC3); // 256个像素值,3通道(B/G/R)
for (int i = 0; i < 256; i++) {
// 蓝色通道:压低亮度(i*0.8),模拟旧照片黄调
uchar b = saturate_cast<uchar>(i * 0.8);
// 绿色通道:适度提亮(i*1.1)
uchar g = saturate_cast<uchar>(i * 1.1);
// 红色通道:轻微提亮(i*1.05)
uchar r = saturate_cast<uchar>(i * 1.05);
// 赋值到LUT(OpenCV是BGR顺序)
lut.at<Vec3b>(i, 0) = Vec3b(b, g, r);
}
}
int testLUT2()
{
Mat img = imread(R"(D:\Study\OpenCvStudy\lean.jpg)");
if (img.empty()) {
printf("图片读取失败!\n");
return -1;
}
// 2. 构建复古滤镜LUT
Mat retroLUT;
createRetroLUT(retroLUT);
// 3. 应用LUT
Mat retroImg;
LUT(img, retroLUT, retroImg);
// 4. 显示对比
imshow("原图", img);
imshow("复古滤镜效果", retroImg);
waitKey(0);
destroyAllWindows();
return 0;
}
