📌 前言
在图像处理过程中,我们经常需要对图像的每个像素进行非线性映射,例如:
-
伽马校正(Gamma Correction)
-
阈值分段增强
-
伪彩色可视化
如果逐像素用 for
循环去操作,不仅代码冗长,而且速度非常慢。这时候 OpenCV 提供的 cv::LUT()
就派上了用场 ------ 它可以用**查找表(Look-Up Table, LUT)**实现极高效的像素值映射。
🧠 什么是 LUT?
LUT(查找表),顾名思义,就是一个数组,预先存放了所有可能输入值对应的输出值。
以 8 位灰度图为例,像素值范围是 0 ~ 255
,那我们可以构建一个长度为 256 的查找表:

然后,处理图像时,只需用像素值作为索引,直接取表里的结果即可 ------ O(1) 查找,速度极快。
📝 cv::LUT()
函数原型
cpp
void cv::LUT(
InputArray src, // 输入图像,通常为 CV_8U 或多通道
InputArray lut, // 查找表,1x256 或 256x1
OutputArray dst // 输出图像
);

💻 示例 1:简单灰度反转
cpp
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
Mat img = imread("lenna.png", IMREAD_GRAYSCALE);
// 构造反转 LUT
Mat lut(1, 256, CV_8U);
for (int i = 0; i < 256; i++)
lut.at<uchar>(0, i) = 255 - i;
Mat result;
LUT(img, lut, result);
imshow("Original", img);
imshow("Inverted", result);
waitKey(0);
return 0;
}
✅ 这里 LUT
会把每个像素值替换成 255 - value
,完成灰度反转。
🎨 示例 2:灰度图伪彩色上色
有时候我们需要把灰度图可视化成彩色图以便观察细节,可以用三通道 LUT 实现:
cpp
Mat gray = imread("lenna.png", IMREAD_GRAYSCALE);
// 构造彩色 LUT
Mat lut(1, 256, CV_8UC3);
for (int i = 0; i < 256; i++) {
lut.at<Vec3b>(0, i) = Vec3b(255 - i, i, i / 2); // B, G, R
}
Mat colored;
LUT(gray, lut, colored);
imshow("Colored", colored);
waitKey(0);
这样就能把灰度值映射到你自定义的彩色梯度上,比 cvtColor(gray, BGR)
更高效,因为直接从单通道变成三通道。
🚀 性能优化建议
-
避免 for 循环逐像素操作 ,
cv::LUT()
内部做了 SIMD/多线程优化,速度远超手写循环。 -
尽量使用单通道输入 + 多通道 LUT ,省去
cvtColor()
复制操作,节省内存。 -
如果 LUT 很简单(如线性缩放),可以考虑用
cv::convertScaleAbs()
,更快。
🔧 对比 applyColorMap
OpenCV 还提供了现成的 applyColorMap()
,可以直接把灰度图转换为常见的伪彩色,比如 JET、TURBO、PLASMA:
cpp
Mat colored;
applyColorMap(gray, colored, COLORMAP_JET);
如果你的需求是标准伪彩色 ,直接用 applyColorMap
更方便;
如果你需要自定义映射规则 ,LUT
是首选。
📚 小结
-
cv::LUT()
是 OpenCV 中处理逐像素非线性映射的利器; -
可以支持单通道、多通道 LUT,自定义各种灰度映射、伽马校正、阈值分段、伪彩色;
-
性能非常高,优先考虑代替手动循环。
💡 建议 :下一次你需要处理像素值变换时,先想想能不能用 LUT()
实现,它会让你的代码更简洁、速度更快。