tx-gxx-linux/device/gxx-linux/capimage/correct_ultis.cpp

420 lines
12 KiB
C++
Raw Permalink 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-----------------------------");
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)
{
Mat lutMat;
FPGAConfigParam param = GetFpgaparam(dpi, mode);
std::string path = isText?param.TextLutPath : param.LutPath;
printf("\n %s",path.c_str());
if (src.type() == CV_8UC3)
{
if (lutColorMat.empty())
{
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 (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);
lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat),true);
cv::imwrite(param.TextLutPath, lut);
printf("exit creatLUTData \n");
}
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 (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 = CorrectParam().GetFpgaparam(dpi, mode);
return param;
}
void SaveFpgaparam(FPGAConfigParam &param)
{
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)));
}
}
#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 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)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(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> coefficient = caculate(points_x, points_y);
uchar buffer[256];
for (int i = 0; i < 256; i++)
{
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)));
}
cv::Mat lut_lut(256, 1, CV_8UC1, buffer);
cv::LUT(lut, lut_lut, lut);
}
return lut;
}