#include #include #include #include #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(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 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 &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(temp))); } } void fittingLUT_gray(const std::vector &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(temp))); } } #define CHANNEL 408 cv::Mat calcLUT(const cv::Mat &black, const cv::Mat &white, bool isTextCorrection) { std::vector 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 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 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 &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 caculate(const std::vector &points_x, const std::vector &points_y) { int MaxElement = points_x.size() - 1; // 计算常数f double f = points_y[0]; // 求解 int n, m; // double a[MaxElement][MaxElement+1]; std::vector> a; // a.resize(MaxElement); for (int i = 0; i < MaxElement; i++) { std::vector 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 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 &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 grayPoints; for (size_t j = 0; j < mats.size(); j++) grayPoints.push_back(mats[j].data[i]); fittingLUT_gray(grayPoints, static_cast(min_val), static_cast(max_val), lut.data + i * 256); } return lut; } cv::Mat createLUT(const std::vector &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 grayPoints; for (size_t j = 0; j < mats.size(); j++) grayPoints.push_back(mats[j].data[i]); fittingLUT(grayPoints, static_cast(min_val), static_cast(max_val), lut.data + i * 256); } if (isTextCorrect) { // std::vector points_x = {0, 25, 205, 255}, points_y = {0, 0, 230, 255}; std::vector points_x = {0, 25, 215, 255}, points_y = {0, 0, 250, 255}; // std::vector points_x = {0, 25, 80, 150, 215}, points_y = {0, 0, 80, 170, 255}; std::vector 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(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(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; }