658 lines
20 KiB
C++
658 lines
20 KiB
C++
|
#include <unistd.h>
|
|||
|
#include <sys/types.h>
|
|||
|
#include <sys/stat.h>
|
|||
|
#include <fcntl.h>
|
|||
|
#include "correct_ultis.h"
|
|||
|
#include "CorrectParam.h"
|
|||
|
#include "commondef.h"
|
|||
|
#define USE_NEWFLAT
|
|||
|
using namespace cv;
|
|||
|
|
|||
|
void initStep()
|
|||
|
{
|
|||
|
for (int i = 0; i < 2; i++)
|
|||
|
{
|
|||
|
for (int j = 0; j < 3; j++)
|
|||
|
{
|
|||
|
expStep[i][j] = 600;
|
|||
|
}
|
|||
|
}
|
|||
|
for (int i = 0; i < 12; i++)
|
|||
|
{
|
|||
|
offsetStep[i] = 256;
|
|||
|
printf("offsetStep[%d]=%d \n", i, offsetStep[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat extractRepresentRow2(const cv::Mat &src)
|
|||
|
{
|
|||
|
cv::Mat BWbalenceSrc(1, src.cols * src.channels(), CV_8UC1);
|
|||
|
|
|||
|
cv::Mat temp_imageBW(src.rows, src.cols * src.channels(), CV_8UC1, src.data);
|
|||
|
|
|||
|
for (size_t i = 0; i < BWbalenceSrc.cols; i++)
|
|||
|
BWbalenceSrc.at<uchar>(0, i) = cv::mean(temp_imageBW(cv::Rect(i, 0, 1, temp_imageBW.rows)))[0];
|
|||
|
|
|||
|
return BWbalenceSrc;
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat loadLUT(const std::string &file)
|
|||
|
{
|
|||
|
cv::Mat dataFile = cv::imread(file, cv::IMREAD_ANYCOLOR);
|
|||
|
|
|||
|
long total = dataFile.total();
|
|||
|
int step = total / 256;
|
|||
|
|
|||
|
int channel = 1;
|
|||
|
#ifndef USE_NEWFLAT
|
|||
|
if (step == 4896 || step == 7344)
|
|||
|
channel = 408;
|
|||
|
else if (step == 14688 || step == 22032 || step == 44064)
|
|||
|
channel = 432; // 486
|
|||
|
#else
|
|||
|
channel = 408;
|
|||
|
#endif
|
|||
|
cv::Mat lut(step / channel, 256, CV_8UC(channel));
|
|||
|
memcpy(lut.data, dataFile.data, total);
|
|||
|
return lut;
|
|||
|
}
|
|||
|
|
|||
|
void initLut(const std::string lutpath, bool iscolor)
|
|||
|
{
|
|||
|
printf("\n-----init lutpath =%s------------", lutpath.c_str());
|
|||
|
lutColorMat.release();
|
|||
|
lutGrayMat.release();
|
|||
|
|
|||
|
if (!lutpath.empty() && (access(lutpath.c_str(), F_OK) == 0))
|
|||
|
{
|
|||
|
printf("\n %s", lutpath.c_str());
|
|||
|
if (iscolor)
|
|||
|
lutColorMat = loadLUT(lutpath); // 彩色校正值
|
|||
|
else
|
|||
|
lutGrayMat = loadLUT(lutpath); // 灰色校正值
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void correctColor(cv::Mat &src, int dpi, int mode, bool isText, int is_8478)
|
|||
|
{
|
|||
|
cv::Mat lutMat;
|
|||
|
std::string path;
|
|||
|
if (src.type() == CV_8UC3)
|
|||
|
{
|
|||
|
if (lutColorMat.empty())
|
|||
|
{
|
|||
|
if (is_8478 == 1)
|
|||
|
{
|
|||
|
FPGAConfigParam_8478 param = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode);
|
|||
|
path = isText ? param.TextLutPath : param.LutPath;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
FPGAConfigParam param = GetFpgaparam(dpi, mode);
|
|||
|
path = isText ? param.TextLutPath : param.LutPath;
|
|||
|
}
|
|||
|
printf("\n %s", path.c_str());
|
|||
|
if (access(path.c_str(), F_OK) != -1)
|
|||
|
{
|
|||
|
lutColorMat = loadLUT(path);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
printf("error error error %s NOT FOUND \n", path.c_str());
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
lutMat = lutColorMat;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (lutGrayMat.empty())
|
|||
|
{
|
|||
|
if (is_8478 == 1)
|
|||
|
{
|
|||
|
FPGAConfigParam_8478 param = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode);
|
|||
|
path = isText ? param.TextLutPath : param.LutPath;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
FPGAConfigParam param = GetFpgaparam(dpi, mode);
|
|||
|
path = isText ? param.TextLutPath : param.LutPath;
|
|||
|
}
|
|||
|
printf("\n %s", path.c_str());
|
|||
|
if (access(path.c_str(), F_OK) != -1)
|
|||
|
{
|
|||
|
lutGrayMat = loadLUT(path);
|
|||
|
// brightness(lutGrayMat);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
printf("error error error %s NOT FOUND", path.c_str());
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
lutMat = lutGrayMat;
|
|||
|
}
|
|||
|
if (lutMat.empty())
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat image_temp(src.rows, src.cols * src.channels() / lutMat.channels(), CV_8UC(lutMat.channels()), src.data);
|
|||
|
|
|||
|
for (size_t i = 0; i < image_temp.cols; i++)
|
|||
|
cv::LUT(image_temp(cv::Rect(i, 0, 1, image_temp.rows)), lutMat(cv::Rect(0, i, 256, 1)), image_temp(cv::Rect(i, 0, 1, image_temp.rows)));
|
|||
|
}
|
|||
|
|
|||
|
void creatLUTData(int dpi, int mode, FPGAConfigParam param)
|
|||
|
{
|
|||
|
printf("eneter creatLUTData \n");
|
|||
|
auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
|
|||
|
std::string blackPath = param.Flat_BwPath;
|
|||
|
std::string whitePath = param.Flat_WhitePath;
|
|||
|
std::string lutsavePath = param.LutPath;
|
|||
|
cv::Mat lut;
|
|||
|
cv::Mat twMat = cv::imread(whitePath, IMREAD_ANYCOLOR);
|
|||
|
cv::Mat tbMat = cv::imread(blackPath, IMREAD_ANYCOLOR);
|
|||
|
cv::Mat wMat, bMat;
|
|||
|
if (mode == 1)
|
|||
|
{
|
|||
|
wMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, twMat.data);
|
|||
|
bMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, tbMat.data);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
wMat = twMat;
|
|||
|
bMat = tbMat;
|
|||
|
}
|
|||
|
|
|||
|
// lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode); // add by liuyong: 刘丁维提供 2019/4/12
|
|||
|
lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), false);
|
|||
|
// Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1);
|
|||
|
// memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256);
|
|||
|
cv::imwrite(param.LutPath, lut);
|
|||
|
system(("cp -f " + param.LutPath + " " + param.LutPath + "-back").c_str());
|
|||
|
lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), true);
|
|||
|
cv::imwrite(param.TextLutPath, lut);
|
|||
|
system(("cp -f " + param.TextLutPath + " " + param.TextLutPath + "-back").c_str());
|
|||
|
printf("exit creatLUTData \n");
|
|||
|
}
|
|||
|
|
|||
|
void creatLUTData_gray(int dpi, int mode, FPGAConfigParam param)
|
|||
|
{
|
|||
|
printf("eneter creatLUTData_gray \n");
|
|||
|
auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
|
|||
|
std::string blackPath = param.Flat_BwPath;
|
|||
|
std::string whitePath = param.Flat_WhitePath;
|
|||
|
std::string lutsavePath = param.LutPath;
|
|||
|
cv::Mat lut;
|
|||
|
cv::Mat twMat = cv::imread(whitePath, IMREAD_ANYCOLOR);
|
|||
|
cv::Mat tbMat = cv::imread(blackPath, IMREAD_ANYCOLOR);
|
|||
|
cv::Mat tw_dynamic = cv::imread(param.Flat_WhitePath.substr(0, param.Flat_WhitePath.length() - 4) + "_dynamic.bmp");
|
|||
|
cv::Mat wMat, bMat, w_dynamic;
|
|||
|
if (twMat.empty() && tbMat.empty())
|
|||
|
return;
|
|||
|
if (mode == 1)
|
|||
|
{
|
|||
|
wMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, twMat.data);
|
|||
|
bMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, tbMat.data);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
wMat = twMat;
|
|||
|
bMat = tbMat;
|
|||
|
}
|
|||
|
if (!tw_dynamic.empty())
|
|||
|
{
|
|||
|
w_dynamic = mode == 1 ? cv::Mat(tw_dynamic.rows, tw_dynamic.cols * 3, CV_8UC1, tw_dynamic.data) : tw_dynamic;
|
|||
|
std::vector<cv::Mat> w;
|
|||
|
w.push_back(colMean(bMat));
|
|||
|
w.push_back(colMean(wMat));
|
|||
|
w.push_back(colMean(w_dynamic));
|
|||
|
lut = calcLUT_gray(w);
|
|||
|
}
|
|||
|
else
|
|||
|
lut = calcLUT_gray(bMat, wMat);
|
|||
|
// lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode); // add by liuyong: 刘丁维提供 2019/4/12
|
|||
|
|
|||
|
cv::imwrite(param.LutPath, lut);
|
|||
|
// lut = calcLUT_gray(bMat,wMat);
|
|||
|
// cv::imwrite(param.TextLutPath, lut);
|
|||
|
printf("exit creatLUTData_gray \n");
|
|||
|
}
|
|||
|
|
|||
|
void creatLUTData(int dpi, int mode, FPGAConfigParam_8478 param)
|
|||
|
{
|
|||
|
FPGAConfigParam tmp_{};
|
|||
|
tmp_.Flat_BwPath = param.Flat_BwPath;
|
|||
|
tmp_.Flat_WhitePath = param.Flat_WhitePath;
|
|||
|
tmp_.LutPath = param.LutPath;
|
|||
|
tmp_.TextLutPath = param.TextLutPath;
|
|||
|
creatLUTData(dpi, mode, tmp_);
|
|||
|
}
|
|||
|
|
|||
|
void creatLUTData_gray(int dpi, int mode, FPGAConfigParam_8478 param)
|
|||
|
{
|
|||
|
FPGAConfigParam tmp_{};
|
|||
|
tmp_.Flat_BwPath = param.Flat_BwPath;
|
|||
|
tmp_.Flat_WhitePath = param.Flat_WhitePath;
|
|||
|
tmp_.LutPath = param.LutPath;
|
|||
|
tmp_.TextLutPath = param.TextLutPath;
|
|||
|
creatLUTData_gray(dpi, mode, tmp_);
|
|||
|
}
|
|||
|
|
|||
|
void creatLUTData(int dpi, int mode)
|
|||
|
{
|
|||
|
printf("eneter creatLUTData \n");
|
|||
|
auto param = GetFpgaparam(dpi, mode);
|
|||
|
auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
|
|||
|
std::string blackPath = param.Flat_BwPath;
|
|||
|
std::string whitePath = param.Flat_WhitePath;
|
|||
|
std::string lutsavePath = param.LutPath;
|
|||
|
cv::Mat lut;
|
|||
|
cv::Mat twMat = cv::imread(whitePath, IMREAD_ANYCOLOR);
|
|||
|
cv::Mat tbMat = cv::imread(blackPath, IMREAD_ANYCOLOR);
|
|||
|
cv::Mat wMat, bMat;
|
|||
|
if (twMat.empty() && tbMat.empty())
|
|||
|
return;
|
|||
|
if (mode == 1)
|
|||
|
{
|
|||
|
wMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, twMat.data);
|
|||
|
bMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, tbMat.data);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
wMat = twMat;
|
|||
|
bMat = tbMat;
|
|||
|
}
|
|||
|
|
|||
|
// lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode); // add by liuyong: 刘丁维提供 2019/4/12
|
|||
|
lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), false);
|
|||
|
// Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1);
|
|||
|
// memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256);
|
|||
|
cv::imwrite(param.LutPath, lut);
|
|||
|
lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), true);
|
|||
|
cv::imwrite(param.TextLutPath, lut);
|
|||
|
printf("exit creatLUTData \n");
|
|||
|
}
|
|||
|
|
|||
|
FPGAConfigParam GetFpgaparam(int dpi, int mode)
|
|||
|
{
|
|||
|
FPGAConfigParam param = Get_Static_CorrectParam().GetFpgaparam(dpi, mode);
|
|||
|
return param;
|
|||
|
}
|
|||
|
|
|||
|
void SaveFpgaparam(FPGAConfigParam ¶m)
|
|||
|
{
|
|||
|
Get_Static_CorrectParam().SaveCorrectParam(param);
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat colMean(const cv::Mat &image)
|
|||
|
{
|
|||
|
cv::Mat meanMat(1, image.step, CV_8UC1);
|
|||
|
cv::Mat tempMat(image.rows, image.step, CV_8UC1, image.data);
|
|||
|
for (int i = 0; i < tempMat.step; i++)
|
|||
|
meanMat.data[i] = cv::mean(tempMat(cv::Rect(i, 0, 1, tempMat.rows)))[0];
|
|||
|
|
|||
|
return meanMat;
|
|||
|
}
|
|||
|
|
|||
|
float gamma(float value, float ex)
|
|||
|
{
|
|||
|
return cv::pow(value / 255.0f, 1.0f / ex) * 255.0f + 0.5f;
|
|||
|
}
|
|||
|
|
|||
|
#define GAMMA_EX 1.7f
|
|||
|
#define BLACK_OFFSET 5
|
|||
|
void fittingLUT(const std::vector<uchar> &points, uchar min_value, uchar max_value, uchar *data)
|
|||
|
{
|
|||
|
float step = max_value - min_value + 1;
|
|||
|
memset(data, min_value, 127);
|
|||
|
memset(data + 127, max_value, 129);
|
|||
|
int b = points[0];
|
|||
|
int w = points[1];
|
|||
|
int tb = min_value;
|
|||
|
int tw = max_value;
|
|||
|
|
|||
|
step = cv::max((float)(tw - tb + 1) / (float)(w - b + 1), 0.0f);
|
|||
|
float temp;
|
|||
|
for (int j = 0, length = (255 - b + 1); j < length; j++)
|
|||
|
{
|
|||
|
temp = gamma(tb + step * j, GAMMA_EX) - BLACK_OFFSET;
|
|||
|
data[j + b] = cv::min(255, cv::max(0, static_cast<int>(temp)));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void fittingLUT_gray(const std::vector<uchar> &points, uchar min_value, uchar max_value, uchar *data)
|
|||
|
{
|
|||
|
float step = max_value - min_value + 1;
|
|||
|
memset(data, min_value, 127);
|
|||
|
memset(data + 127, max_value, 129);
|
|||
|
int b = points[0];
|
|||
|
int w = points[1];
|
|||
|
int tb = min_value;
|
|||
|
int tw = max_value;
|
|||
|
|
|||
|
step = cv::max((float)(tw - tb + 1) / (float)(w - b + 1), 0.0f);
|
|||
|
float temp;
|
|||
|
for (int j = 0, length = (255 - b + 1); j < length; j++)
|
|||
|
{
|
|||
|
#if 0
|
|||
|
temp = gamma(tb + step * j, GAMMA_EX) - BLACK_OFFSET;
|
|||
|
#else
|
|||
|
temp = tb + step * j;
|
|||
|
#endif
|
|||
|
data[j + b] = cv::min(255, cv::max(0, static_cast<int>(temp)));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#define CHANNEL 408
|
|||
|
cv::Mat calcLUT(const cv::Mat &black, const cv::Mat &white, bool isTextCorrection)
|
|||
|
{
|
|||
|
std::vector<cv::Mat> w;
|
|||
|
w.push_back(colMean(black));
|
|||
|
w.push_back(colMean(white));
|
|||
|
cv::Mat lut = createLUT(w, isTextCorrection);
|
|||
|
|
|||
|
for (size_t i = 0, block = lut.rows / CHANNEL; i < block; i++)
|
|||
|
{
|
|||
|
cv::Mat lutROI = lut(cv::Rect(0, i * CHANNEL, 256, CHANNEL));
|
|||
|
cv::Mat tran;
|
|||
|
cv::transpose(lutROI, tran);
|
|||
|
memcpy(lutROI.data, tran.data, tran.total());
|
|||
|
}
|
|||
|
return lut;
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat splitJoint(const cv::Mat &staticMat, const cv::Mat &dynamicsMat)
|
|||
|
{
|
|||
|
cv::Mat dst(1, staticMat.cols, staticMat.type());
|
|||
|
|
|||
|
uchar *ptr_dst = dst.data;
|
|||
|
uchar *ptr_mat1 = staticMat.data;
|
|||
|
uchar *ptr_mat2 = dynamicsMat.data;
|
|||
|
|
|||
|
int offset = staticMat.step * 25 / 1000;
|
|||
|
cv::Range range1(offset, staticMat.step / 2 - offset);
|
|||
|
cv::Range range2(staticMat.step / 2 + offset, staticMat.step - offset);
|
|||
|
for (size_t i = 0; i < dst.step; i++)
|
|||
|
{
|
|||
|
// if (i < range1.start || i > range2.end || (i > range1.end && i < range2.start))
|
|||
|
if (ptr_mat1[i] > ptr_mat2[i] + 50)
|
|||
|
ptr_dst[i] = ptr_mat1[i];
|
|||
|
else
|
|||
|
ptr_dst[i] = ptr_mat2[i];
|
|||
|
// else
|
|||
|
// ptr_dst[i] = ptr_mat2[i];
|
|||
|
}
|
|||
|
|
|||
|
return dst;
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat calcLUT_gray(const cv::Mat &black, const cv::Mat &white)
|
|||
|
{
|
|||
|
std::vector<cv::Mat> w;
|
|||
|
w.push_back(colMean(black));
|
|||
|
w.push_back(colMean(white));
|
|||
|
cv::Mat lut = createLUT_gray(w);
|
|||
|
|
|||
|
for (size_t i = 0, block = lut.rows / CHANNEL; i < block; i++)
|
|||
|
{
|
|||
|
cv::Mat lutROI = lut(cv::Rect(0, i * CHANNEL, 256, CHANNEL));
|
|||
|
cv::Mat tran;
|
|||
|
cv::transpose(lutROI, tran);
|
|||
|
memcpy(lutROI.data, tran.data, tran.total());
|
|||
|
}
|
|||
|
return lut;
|
|||
|
|
|||
|
// std::vector<cv::Mat> w;
|
|||
|
// w.push_back(colMean(black));
|
|||
|
// w.push_back(colMean(white));
|
|||
|
// if(!dynamic.empty())
|
|||
|
// w.push_back(colMean(dynamic));
|
|||
|
// if (w.size() == 3)
|
|||
|
// {
|
|||
|
// cv::Mat newWhite = splitJoint(w[1], w[2]);
|
|||
|
// w.erase(w.end() - 1);
|
|||
|
// w[1] = newWhite;
|
|||
|
// }
|
|||
|
|
|||
|
// cv::Mat lut = createLUT_gray(w);
|
|||
|
|
|||
|
// int channel = (lut.rows % CHANNEL == 0) ? CHANNEL : 459;
|
|||
|
// for (size_t i = 0, block = lut.rows / channel; i < block; i++)
|
|||
|
// {
|
|||
|
// cv::Mat lutROI = lut(cv::Rect(0, i * channel, 256, channel));
|
|||
|
// cv::Mat tran;
|
|||
|
// cv::transpose(lutROI, tran);
|
|||
|
// memcpy(lutROI.data, tran.data, tran.total());
|
|||
|
// }
|
|||
|
// return lut;
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat calcLUT_gray(std::vector<cv::Mat> &w)
|
|||
|
{
|
|||
|
if (w.size() == 3)
|
|||
|
{
|
|||
|
cv::Mat newWhite = splitJoint(w[1], w[2]);
|
|||
|
w.erase(w.end() - 1);
|
|||
|
w[1] = newWhite;
|
|||
|
// cv::imwrite("/home/test.bmp",newWhite);
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat lut = createLUT_gray(w);
|
|||
|
|
|||
|
int channel = (lut.rows % CHANNEL == 0) ? CHANNEL : 459;
|
|||
|
for (size_t i = 0, block = lut.rows / channel; i < block; i++)
|
|||
|
{
|
|||
|
cv::Mat lutROI = lut(cv::Rect(0, i * channel, 256, channel));
|
|||
|
cv::Mat tran;
|
|||
|
cv::transpose(lutROI, tran);
|
|||
|
memcpy(lutROI.data, tran.data, tran.total());
|
|||
|
}
|
|||
|
return lut;
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat create_lut(const cv::Mat &black, const cv::Mat &white, int dpi, bool colormode)
|
|||
|
{
|
|||
|
#ifndef USE_NEWFLAT
|
|||
|
if (black.empty() || white.empty() || black.channels() != 1 || white.channels() != 1 || black.step != white.step)
|
|||
|
return cv::Mat();
|
|||
|
|
|||
|
int channel = 1;
|
|||
|
if (black.step == 4896 || black.step == 7344)
|
|||
|
channel = 408;
|
|||
|
else if (black.step == 14688 || black.step == 22032 || black.step == 44064)
|
|||
|
channel = 432; // 486
|
|||
|
|
|||
|
if (channel == 1)
|
|||
|
return cv::Mat();
|
|||
|
|
|||
|
const int rows = black.cols / channel;
|
|||
|
const int cols = 256;
|
|||
|
auto cc = CV_8UC(channel);
|
|||
|
Mat lut(rows, cols, CV_8UC(channel));
|
|||
|
const double gain = 255.0 / ((double)Get_Static_CorrectParam().GetFpgaparam(dpi, colormode).MaxBright);
|
|||
|
for (size_t i = 0; i < rows; i++)
|
|||
|
{
|
|||
|
Mat lut_row = lut(cv::Rect(0, i, cols, 1));
|
|||
|
unsigned char *ptr_buffer = lut_row.data;
|
|||
|
unsigned char *ptr_black = black.data + i * channel;
|
|||
|
unsigned char *ptr_white = white.data + i * channel;
|
|||
|
for (size_t j = 0; j < cols; j++)
|
|||
|
for (size_t k = 0; k < channel; k++)
|
|||
|
{
|
|||
|
if (ptr_black[k] >= ptr_white[k])
|
|||
|
{
|
|||
|
ptr_buffer[j * channel + k] = 0;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (j <= ptr_black[k])
|
|||
|
ptr_buffer[j * channel + k] = 0;
|
|||
|
else if (j >= ptr_white[k])
|
|||
|
ptr_buffer[j * channel + k] = 255;
|
|||
|
else
|
|||
|
{
|
|||
|
float val = 255.0f * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]) * gain;
|
|||
|
ptr_buffer[j * channel + k] = (unsigned char)cv::max(0.0f, cv::min(val, 255.0f));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
cv::Mat saveMat(black.step, 256, CV_8UC1, lut.data);
|
|||
|
return saveMat.clone();
|
|||
|
#else
|
|||
|
return calcLUT(black, white, false);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
std::vector<double> caculate(const std::vector<double> &points_x, const std::vector<double> &points_y)
|
|||
|
{
|
|||
|
int MaxElement = points_x.size() - 1;
|
|||
|
// 计算常数f
|
|||
|
double f = points_y[0];
|
|||
|
// 求解
|
|||
|
int n, m;
|
|||
|
// double a[MaxElement][MaxElement+1];
|
|||
|
std::vector<std::vector<double>> a;
|
|||
|
// a.resize(MaxElement);
|
|||
|
for (int i = 0; i < MaxElement; i++)
|
|||
|
{
|
|||
|
std::vector<double> b;
|
|||
|
b.resize(MaxElement + 1);
|
|||
|
a.push_back(b);
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i < MaxElement; i++)
|
|||
|
{
|
|||
|
for (int j = 0; j < MaxElement; j++)
|
|||
|
a[i][j] = cv::pow(points_x[i + 1], MaxElement - j);
|
|||
|
a[i][MaxElement] = points_y[i + 1] - f;
|
|||
|
}
|
|||
|
|
|||
|
int i, j;
|
|||
|
n = MaxElement;
|
|||
|
|
|||
|
for (j = 0; j < n; j++)
|
|||
|
{
|
|||
|
double max = 0;
|
|||
|
double imax = 0;
|
|||
|
for (i = j; i < n; i++)
|
|||
|
{
|
|||
|
if (imax < cv::abs(a[i][j]))
|
|||
|
{
|
|||
|
imax = cv::abs(a[i][j]);
|
|||
|
max = a[i][j]; // 得到各行中所在列最大元素
|
|||
|
m = i;
|
|||
|
}
|
|||
|
}
|
|||
|
if (cv::abs(a[j][j]) != max)
|
|||
|
{
|
|||
|
double b = 0;
|
|||
|
for (int k = j; k < n + 1; k++)
|
|||
|
{
|
|||
|
b = a[j][k];
|
|||
|
a[j][k] = a[m][k];
|
|||
|
a[m][k] = b;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (int r = j; r < n + 1; r++)
|
|||
|
{
|
|||
|
a[j][r] = a[j][r] / max; // 让该行的所在列除以所在列的第一个元素,目的是让首元素为1
|
|||
|
}
|
|||
|
|
|||
|
for (i = j + 1; i < n; i++)
|
|||
|
{
|
|||
|
double c = a[i][j];
|
|||
|
if (c == 0.0)
|
|||
|
continue;
|
|||
|
for (int s = j; s < n + 1; s++)
|
|||
|
{
|
|||
|
a[i][s] = a[i][s] - a[j][s] * c; // 前后行数相减,使下一行或者上一行的首元素为0
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
for (i = n - 2; i >= 0; i--)
|
|||
|
{
|
|||
|
for (j = i + 1; j < n; j++)
|
|||
|
{
|
|||
|
a[i][n] = a[i][n] - a[j][n] * a[i][j];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
std::vector<double> result;
|
|||
|
for (int k = 0; k < n; k++)
|
|||
|
result.push_back(a[k][n]);
|
|||
|
result.push_back(f);
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat createLUT_gray(const std::vector<cv::Mat> &mats)
|
|||
|
{
|
|||
|
int rows = mats[0].cols;
|
|||
|
cv::Mat lut(rows, 256, CV_8UC1);
|
|||
|
|
|||
|
double max_val, min_val;
|
|||
|
cv::minMaxIdx(mats[0], &min_val, nullptr);
|
|||
|
cv::minMaxIdx(mats[1], nullptr, &max_val);
|
|||
|
for (size_t i = 0; i < rows; i++)
|
|||
|
{
|
|||
|
std::vector<uchar> grayPoints;
|
|||
|
for (size_t j = 0; j < mats.size(); j++)
|
|||
|
grayPoints.push_back(mats[j].data[i]);
|
|||
|
|
|||
|
fittingLUT_gray(grayPoints, static_cast<uchar>(min_val), static_cast<uchar>(max_val), lut.data + i * 256);
|
|||
|
}
|
|||
|
return lut;
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat createLUT(const std::vector<cv::Mat> &mats, bool isTextCorrect)
|
|||
|
{
|
|||
|
int rows = mats[0].cols;
|
|||
|
cv::Mat lut(rows, 256, CV_8UC1);
|
|||
|
|
|||
|
double max_val, min_val;
|
|||
|
cv::minMaxIdx(mats[0], &min_val, nullptr);
|
|||
|
cv::minMaxIdx(mats[1], nullptr, &max_val);
|
|||
|
for (size_t i = 0; i < rows; i++)
|
|||
|
{
|
|||
|
std::vector<uchar> grayPoints;
|
|||
|
for (size_t j = 0; j < mats.size(); j++)
|
|||
|
grayPoints.push_back(mats[j].data[i]);
|
|||
|
|
|||
|
fittingLUT(grayPoints, static_cast<uchar>(min_val), static_cast<uchar>(max_val), lut.data + i * 256);
|
|||
|
}
|
|||
|
if (isTextCorrect)
|
|||
|
{
|
|||
|
// std::vector<double> points_x = {0, 25, 205, 255}, points_y = {0, 0, 230, 255};
|
|||
|
std::vector<double> points_x = {0, 25, 215, 255}, points_y = {0, 0, 250, 255};
|
|||
|
// std::vector<double> points_x = {0, 25, 80, 150, 215}, points_y = {0, 0, 80, 170, 255};
|
|||
|
std::vector<double> coefficient = caculate(points_x, points_y);
|
|||
|
|
|||
|
uchar buffer[256];
|
|||
|
uchar buffer_B[256];
|
|||
|
for (int i = 0; i < 256; i++)
|
|||
|
{
|
|||
|
// int temp = coefficient[0] * i * i * i *i+ coefficient[1] * i * i*i + coefficient[2] * i*i + coefficient[3]*i+coefficient[4];
|
|||
|
int temp = coefficient[0] * i * i * i + coefficient[1] * i * i + coefficient[2] * i + coefficient[3];
|
|||
|
buffer[i] = static_cast<uchar>(cv::min(255, cv::max(0, temp)));
|
|||
|
}
|
|||
|
|
|||
|
coefficient = caculate({0, 25, 220, 255}, {0, 0, 250, 255});
|
|||
|
for (int i = 0; i < 256; i++)
|
|||
|
{
|
|||
|
// int temp = coefficient[0] * i * i * i *i+ coefficient[1] * i * i*i + coefficient[2] * i*i + coefficient[3]*i+coefficient[4];
|
|||
|
int temp = coefficient[0] * i * i * i + coefficient[1] * i * i + coefficient[2] * i + coefficient[3];
|
|||
|
buffer_B[i] = static_cast<uchar>(cv::min(255, cv::max(0, temp)));
|
|||
|
}
|
|||
|
|
|||
|
cv::Mat lut_lut(256, 1, CV_8UC1, buffer);
|
|||
|
cv::Mat lut_lut_B(256, 1, CV_8UC1, buffer_B);
|
|||
|
cv::LUT(lut(cv::Rect(0,0,lut.cols,lut.rows/2)), lut_lut, lut(cv::Rect(0,0,lut.cols,lut.rows/2)));
|
|||
|
cv::LUT(lut(cv::Rect(0,lut.rows/2,lut.cols,lut.rows/2)), lut_lut_B, lut(cv::Rect(0,lut.rows/2,lut.cols,lut.rows/2)));
|
|||
|
|
|||
|
// cv::LUT(lut,lut_lut,lut);
|
|||
|
|
|||
|
}
|
|||
|
return lut;
|
|||
|
}
|