OpenCv之查表法LUT

目录

一、LUT(查表法)基本概念

[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. 实时二值化 / 阈值处理)

三、使用举例

3.1过曝光图片处理

3.2图片添加滤镜


一、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 的索引)。
    • 通道
      • 单通道 LUT1x256256x1 的矩阵。无论输入图像是几通道,所有通道都共用这一个映射规则。
      • 多通道 LUT:输入是 3 通道 BGR 图时,LUT 可以是 3x256,分别对应 B、G、R 三个通道的独立映射。
  • 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;
}
相关推荐
AI攻城狮1 小时前
OpenClaw 的 reserveTokensFloor 到底怎么影响 auto-compaction?
人工智能·云原生·aigc
badhope1 小时前
GitHub热门AI技能Top20实战指南
前端·javascript·人工智能·git·python·github·电脑
Learn Forever2 小时前
【OpenClaw】OpenClaw 在windows下的安装及飞书的接入
人工智能·openclaw
磊磊落落2 小时前
当下人人都在养龙虾,这龙虾(OpenClaw)为啥突然就火了?
人工智能
KOYUELEC光与电子努力加油2 小时前
AMAZINGIC晶焱科技推出小体积、高耐压:AZKN6129N专为无人机严苛环境而生
人工智能·科技·无人机
Alexa20772 小时前
openclaw介绍
人工智能
天地沧海2 小时前
项目的框架架构
人工智能
墨染天姬2 小时前
【AI】TensorFlow 框架
人工智能·python·tensorflow
飞哥数智坊2 小时前
微信全面接入龙虾了?我来帮你验证下
人工智能