zynq_7010/zynq_7010_code/correct_ultis.cpp

475 lines
14 KiB
C++
Raw Permalink Normal View History

2023-07-17 03:29:37 +00:00
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "correct_ultis.h"
#include "CImageMerge.h"
#define USE_NEWFLAT
2023-07-20 03:48:38 +00:00
using namespace cv;
2023-07-17 03:29:37 +00:00
//设置一面的offset值
void setOffset(int *config, int step)
{
for (int i = 0; i < 6; i++)
{
int *offset = config + i;
*offset += step;
if (*offset < 0)
*offset = 1;
if (*offset > 255)
*offset = 255;
}
}
2023-08-15 01:50:06 +00:00
cv::Mat extractRepresentRow2(const cv::Mat &src)
{
cv::Mat BWbalenceSrc(1, src.cols * src.channels(), CV_8UC1);
2023-07-17 03:29:37 +00:00
2023-08-15 01:50:06 +00:00
cv::Mat temp_imageBW(src.rows, src.cols * src.channels(), CV_8UC1, src.data);
2023-07-17 03:29:37 +00:00
2023-08-15 01:50:06 +00:00
for (size_t i = 0; i < BWbalenceSrc.cols; i++)
BWbalenceSrc.at<u_char>(0, i) = cv::mean(temp_imageBW(cv::Rect(i, 0, 1, temp_imageBW.rows)))[0];
2023-07-17 03:29:37 +00:00
2023-08-15 01:50:06 +00:00
return BWbalenceSrc;
}
2023-07-17 03:29:37 +00:00
2023-07-20 03:48:38 +00:00
cv::Mat loadLUT(const std::string &file)
{
cv::Mat dataFile = cv::imread(file, cv::IMREAD_ANYCOLOR);
long total = dataFile.total();
int step = total / 256;
2023-07-17 03:29:37 +00:00
2023-07-20 03:48:38 +00:00
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
#ifdef G400
channel = 408;
#else
channel = 432;
#endif
#endif
cv::Mat lut(step / channel, 256, CV_8UC(channel));
memcpy(lut.data, dataFile.data, total);
return lut;
}
2023-07-17 03:29:37 +00:00
void initLut(const std::string lutpath, bool iscolor)
{
2023-07-20 03:48:38 +00:00
if (!lutpath.empty() && (access(lutpath.c_str(), F_OK) == 0))
{
if (iscolor)
{
lutColorMat = loadLUT(lutpath); //彩色校正值
}
else
lutGrayMat = loadLUT(lutpath); //灰色校正值
}
2023-07-17 03:29:37 +00:00
}
2023-07-20 03:48:38 +00:00
void correctColor(cv::Mat &src, int dpi, int mode, bool lutgraghic)
{
cv::Mat lutMat;
#ifdef USE_NEWFLAT
FPGAConfigParam param = GetFpgaparam(dpi, mode);
std::string path = lutgraghic ? param.LutPath : param.TextLutPath;
#else
std::string path = param.LutPath;
#endif
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);
}
else
{
printf("error error error %s NOT FOUND", path.c_str());
return;
}
}
lutMat = lutGrayMat;
}
if (lutMat.empty())
{
return;
}
2023-07-17 03:29:37 +00:00
2023-07-20 03:48:38 +00:00
cv::Mat image_temp(src.rows, src.cols * src.channels() / lutMat.channels(), CV_8UC(lutMat.channels()), src.data);
2023-07-17 03:29:37 +00:00
2023-07-20 03:48:38 +00:00
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)));
}
2023-07-17 03:29:37 +00:00
2023-08-31 08:37:05 +00:00
void correctColor(cv::Mat& src, cv::Mat& lut)
{
cv::Mat image_temp(src.rows, src.cols * src.channels() / lut.channels(), CV_8UC(lut.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)), lut(cv::Rect(0, i, 256, 1)), image_temp(cv::Rect(i, 0, 1, image_temp.rows)));
}
2023-08-15 01:50:06 +00:00
void creatLUTData(int dpi, int mode)
{
FPGAConfigParam param = GetFpgaparam(dpi, mode);
auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
std::string blackPath = param.Flat_BwPath;
std::string whitePath = param.Flat_WhitePath;
cv::Mat lut;
cv::Mat twMat = cv::imread(whitePath, colormode);
cv::Mat tbMat = cv::imread(blackPath, colormode);
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;
}
#ifdef USE_NEWFLAT
//lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), false);
//cv::imwrite(param.LutPath, lut);
lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), true);
cv::imwrite(param.TextLutPath, lut);
#else
lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode);
// Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1);
// memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256);
cv::imwrite(param.LutPath, lut);
#endif
printf("exit creatLUTData \n");
}
2023-07-17 03:29:37 +00:00
2023-08-31 08:37:05 +00:00
cv::Mat creatLUTData_7010(int dpi , int mode)
{
FPGAConfigParam param = GetFpgaparam(dpi, mode);
auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
std::string blackPath = param.Flat_BwPath;
std::string whitePath = param.Flat_WhitePath;
cv::Mat lut;
cv::Mat twMat = cv::imread(whitePath, colormode);
cv::Mat tbMat = cv::imread(blackPath, colormode);
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;
}
#ifdef USE_NEWFLAT
//lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), false);
//cv::imwrite(param.LutPath, lut);
lut = calcLUT(bMat, wMat, true);//
return lut;
#else
lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode);
// Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1);
// memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256);
cv::imwrite(param.LutPath, lut);
#endif
}
2023-07-17 03:29:37 +00:00
FPGAConfigParam GetFpgaparam(int dpi, int mode)
{
return correctparam.GetFpgaparam(dpi, mode);
}
void SaveFpgaparam(FPGAConfigParam &param)
{
correctparam.SaveCorrectParam(param);
}
2023-08-15 01:50:06 +00:00
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];
2023-07-17 03:29:37 +00:00
2023-08-15 01:50:06 +00:00
return meanMat;
}
2023-07-17 03:29:37 +00:00
float gamma(float value, float ex)
{
2023-08-31 08:37:05 +00:00
return cv::pow(value / 255.0f, 1.0f / ex) * 255.0f + 0.5f;
2023-07-17 03:29:37 +00:00
}
#define GAMMA_EX 1.7f
#define BLACK_OFFSET 0
void fittingLUT(const std::vector<u_char> &points, u_char min_value, u_char max_value, u_char *data)
{
2023-08-15 01:50:06 +00:00
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)));
}
2023-07-17 03:29:37 +00:00
}
2023-08-15 01:50:06 +00:00
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<u_char> grayPoints;
for (size_t j = 0; j < mats.size(); j++)
grayPoints.push_back(mats[j].data[i]);
fittingLUT(grayPoints, static_cast<u_char>(min_val), static_cast<u_char>(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);
u_char 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<u_char>(cv::min(255, cv::max(0, temp)));
}
cv::Mat lut_lut(256, 1, CV_8UC1, buffer);
cv::LUT(lut, lut_lut, lut);
}
return lut;
}
2023-07-17 03:29:37 +00:00
#ifdef G400
#define CHANNEL 408
#else
#define CHANNEL 432
#endif
2023-08-15 01:50:06 +00:00
cv::Mat calcLUT(const cv::Mat &black, const cv::Mat &white, bool isTextCorrection)
{
std::vector<cv::Mat> w;
2023-08-31 08:37:05 +00:00
w.push_back(black);
w.push_back(white);
2023-08-15 01:50:06 +00:00
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;
}
2023-08-31 08:37:05 +00:00
void calcLUT(int dpi , int mode, bool isTextCorrection, cv::Mat& lut)
{
FPGAConfigParam param = GetFpgaparam(dpi, mode);
auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
std::string blackPath = param.Flat_BwPath;
std::string whitePath = param.Flat_WhitePath;
cv::Mat twMat = cv::imread(whitePath, colormode);
cv::Mat tbMat = cv::imread(blackPath, colormode);
cv::Mat dataFile = calcLUT(tbMat, twMat, isTextCorrection);
printf("whitePath =%s blackPath = %s \n",whitePath.c_str(),blackPath.c_str());
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
#ifdef G400
channel = 408;
#else
channel = 432;
#endif
#endif
lut = cv::Mat::zeros(step / channel, 256, CV_8UC(channel));
memcpy(lut.data, dataFile.data, total);
printf("!!!!!!!!!!!!!!calc memory lut done \n");
}
2023-08-15 01:50:06 +00:00
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));
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]) * 1.275; //
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
}
cv::Mat GetMergeMat(int dstwidth, int dstheight, int type, cv::Mat &mat)
{
2023-08-31 08:37:05 +00:00
// return CImageMerge().MergeImage(type == CV_8UC3, mat, dstwidth, dstheight);
2023-08-15 01:50:06 +00:00
}