zynq_7010/zynq_7010_code/correct_ultis.cpp

475 lines
14 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 "CImageMerge.h"
#define USE_NEWFLAT
using namespace cv;
//设置一面的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;
}
}
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<u_char>(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
#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;
}
void initLut(const std::string lutpath, bool iscolor)
{
if (!lutpath.empty() && (access(lutpath.c_str(), F_OK) == 0))
{
if (iscolor)
{
lutColorMat = loadLUT(lutpath); //彩色校正值
}
else
lutGrayMat = loadLUT(lutpath); //灰色校正值
}
}
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;
}
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 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)));
}
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");
}
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
}
FPGAConfigParam GetFpgaparam(int dpi, int mode)
{
return correctparam.GetFpgaparam(dpi, mode);
}
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 0
void fittingLUT(const std::vector<u_char> &points, u_char min_value, u_char max_value, u_char *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)));
}
}
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;
}
#ifdef G400
#define CHANNEL 408
#else
#define CHANNEL 432
#endif
cv::Mat calcLUT(const cv::Mat &black, const cv::Mat &white, bool isTextCorrection)
{
std::vector<cv::Mat> w;
w.push_back(black);
w.push_back(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;
}
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");
}
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)
{
// return CImageMerge().MergeImage(type == CV_8UC3, mat, dstwidth, dstheight);
}