rk3399_arm_lvds/capimage/correct_ultis.cpp

658 lines
20 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 &param)
{
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;
}