在上一篇文章中,介绍了用于加快图片转换速度的Look Up Table,官方也提倡使用这种方式
并提供了OpenCV的标准接口:cv::LUT()
[opencv4]调用 LUT实现图片基于LookUpTable的快速转换-目录
1.Look Up Table 的原理及手动实现
https://blog.csdn.net/chenhanxuan1999/article/details/98859125#Look%20Up%20Table
2.官方文档
https://docs.opencv.org/4.1.0/d2/de8/group__core__array.html#gab55b8d062b7f5587720ede032d34156f
#include <opencv2/core.hpp>
3.使用方法
3.1 公式解释
首先理解上面的公式
3.1.1 第一个
LUT函数的作用是将源图片src(I)加上一个offset->b之后去look_up_table
查表并得到结果,接着将这个结果写入目标数组dst(I)中,depth和参数CV_8U & CV_8S的解释参考:
https://blog.csdn.net/chenhanxuan1999/article/details/98859125#t3
3.1.2 第二个
这里signed类型要加上128是很好理解的
因为signed char的对应整数范围是(补码表示)
[1000 0000, 0111 1111]
即 [,
],即[-128, +127]
加上128之后,对应的范围就在[0, 255]
此时去查Look Up Table(一个长度为256的一维数组,下标范围0-255)
就不会发生越界访问
3.2 参数说明
void cv::LUT(InputArray src, InputArray lut, OutputArray dst)
3.2.1 src:
input array of 8-bit elements.
输入的图像颜色通道为8bit
3.2.2 lut:
look-up table of 256 elements; in case of multi-channel input array, the table should either have a single channel (in this case the same table is used for all channels) or the same number of channels as in the input array.
Look Up Table支持两种数组:
1.单通道,如果输入的数组有多个颜色通道,共用这个一维的LookUpTable
2.多通道,每个通道和输入的图片一一对应,可以做到不同的颜色的单独处理
3.2.3 dst:
output array of the same size and number of channels as src, and the same depth as lut.
输出的图片的通道数和尺寸与输入图片相同,编码规则与lut相同
3.3 Demo
3.3.1 main.cpp
#include <iostream>
#include <cstdlib>
#include <sstream>
#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
uchar lookup_table[256];
void init_lookup_table(char* divide_factor) {
for (int i = 0 ; i < 256 ; ++i) {
lookup_table[i] = i;
}
stringstream ss;
int compression_rate = 10;
if (divide_factor != NULL) {
ss << divide_factor;
ss >> compression_rate;
}
if (!compression_rate) {
cerr << "Error: No compreesion rate given" << endl;
exit(1);
}
for (int i = 0 ; i < 256 ; ++i) {
lookup_table[i] = (uchar)((compression_rate) * (lookup_table[i] / compression_rate));
}
}
int main(int argc, char ** argv) {
// Default
String img_name = "../media/cat.jpeg";
char* p_com = NULL;
// Arguments detection
if (argc < 3) {
cerr << "Usage: " << argv[0] << " pic_path compression_rate [G]" << endl;
cerr << "Hint : [] means optional" << endl;
cerr << "Now use default img at '../media/cat.jpeg' " << endl;
cerr << "Now use default compressing rate = 10" << endl;
// exit(1);
}
else {
img_name = argv[1];
p_com = argv[2];
}
init_lookup_table(p_com);
// Read the img
Mat source_img = imread(img_name, IMREAD_COLOR);
namedWindow("Original", WINDOW_AUTOSIZE);
imshow("Original", source_img);
Mat des_img = source_img.clone();
// Create standard LUT for function cv :: lut()
// Here, created a one channel lut
Mat table(1, 256, CV_8U);
// Created 1 * 256 matrix, with CV_8U
// It also decide the output format as CV_8U
uchar* p = table.data;
// Can also be written as
// uchar * p_start = table.ptr(); // for the defalt parameter is ptr(int row = 0);
for (int i = 0 ; i < 256 ; ++i) {
p[i] = lookup_table[i];
}
// Call function cv :: LUT([], [], [])
LUT(source_img, table, des_img);
namedWindow("Transformed", WINDOW_AUTOSIZE);
imshow("Transformed", des_img);
waitKey();
return 0;
}
3.3.2 运行结果:
3.3.3 项目完整代码:
Github:https://github.com/youhengchan/learn_opencv4/tree/master/04-lut_implement
Gitee:https://gitee.com/chenhanxuan/learn_opencv4/tree/master/04-lut_implement