316 lines
9.7 KiB
C++
316 lines
9.7 KiB
C++
|
#include "hgutils.h"
|
||
|
#include <unistd.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <iostream>
|
||
|
#include "CImageMerge.h"
|
||
|
|
||
|
using namespace cv;
|
||
|
|
||
|
cv::Mat extractRepresentRow(const cv::Mat &src)
|
||
|
{
|
||
|
printf("extractRepresentRow2 enter \n");
|
||
|
Mat src_temp(src.rows, src.step, CV_8UC1, src.data);
|
||
|
Mat dst(1, src.cols, CV_8UC(src.channels()));
|
||
|
Mat dst_temp(1, src.step, CV_8UC1, dst.data);
|
||
|
|
||
|
for (int i = 0, length = src.step; i < length; i++)
|
||
|
{
|
||
|
Mat col = src_temp(Rect(i, 0, 1, src_temp.rows));
|
||
|
float value = 0;
|
||
|
for (int j = 0, rows = col.rows; j < rows; j++)
|
||
|
{
|
||
|
value += (float)col.at<unsigned char>(Point(0, j)) / rows;
|
||
|
}
|
||
|
dst_temp.data[i] = (int)value;
|
||
|
}
|
||
|
printf("extractRepresentRow2 exit \n");
|
||
|
return dst;
|
||
|
}
|
||
|
|
||
|
cv::Mat flipRightHalf(Mat &src, int papertype)
|
||
|
{
|
||
|
Mat left = src(cv::Rect(0, 0, src.cols / 2, src.rows));
|
||
|
Mat right = src(cv::Rect(src.cols / 2, 0, src.cols / 2, src.rows));
|
||
|
Mat rightFlip;
|
||
|
if (papertype == (int)(PaperSize::G400_A4R))
|
||
|
{
|
||
|
flip(right, rightFlip, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
flip(right, rightFlip, 1);
|
||
|
}
|
||
|
|
||
|
Mat dst;
|
||
|
hconcat(left, rightFlip, dst);
|
||
|
return dst;
|
||
|
}
|
||
|
|
||
|
float curve_coffes[2][3][3] = {
|
||
|
{{-6e-5, 0.9928, 0.289},
|
||
|
{4e-5, 1.0045, -0.0338},
|
||
|
{3e-5, 1.0028, -0.2547}},
|
||
|
{{0.00025215105482649316, 0.9162675232424231, 2.2064225897716527},
|
||
|
{-6.242394612635725e-05, 1.0212590446315797, -0.7470581333124157},
|
||
|
{-0.0002324551311266845, 1.072239346671703, -1.7099159032971474}}};
|
||
|
|
||
|
cv::Mat create_lut(const cv::Mat &black, const cv::Mat &white, bool colormode, CISVendor vendor)
|
||
|
{
|
||
|
printf("create_lut enter \n");
|
||
|
int channel = 4896 / 12; // 1632*3
|
||
|
|
||
|
const int rows = black.cols / channel; // 408
|
||
|
const int cols = 256;
|
||
|
printf("LUT White width: %d height :%d channels:%d \n", white.cols, white.rows, white.channels());
|
||
|
printf("LUT black width: %d height :%d channels:%d \n", black.cols, black.rows, black.channels());
|
||
|
Mat lut(rows, cols, CV_8UC(channel));
|
||
|
float *cisCoffoes;
|
||
|
float *coffoes;
|
||
|
if (vendor == CISVendor::DUNNAN_CIS_V0)
|
||
|
cisCoffoes = &curve_coffes[0][0][0];
|
||
|
else if (vendor == CISVendor::HUALIN_CIS_V0)
|
||
|
cisCoffoes = &curve_coffes[1][0][0];
|
||
|
else
|
||
|
{
|
||
|
cisCoffoes = &curve_coffes[1][0][0];
|
||
|
printf("warnning!!! unknown cis type,use hualin CIS cisCoffoes params \n");
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
printf("ptr_black[%d] >= ptr_white[%d]", k, k);
|
||
|
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
|
||
|
{
|
||
|
if (white.channels() == 3)
|
||
|
{
|
||
|
float val = 255.0 * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]) * 1.2;
|
||
|
// float val = 255.0 * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]);
|
||
|
// coffoes = cisCoffoes + 3 * (k % 3);
|
||
|
// val = coffoes[0] * val * val + coffoes[1] * val + coffoes[2];
|
||
|
if (val > 255)
|
||
|
val = 255;
|
||
|
|
||
|
if (val < 0)
|
||
|
val = 0;
|
||
|
ptr_buffer[j * channel + k] = (unsigned char)val;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// float val = 255 * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]);
|
||
|
float val = 255 * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]) * 1.2;
|
||
|
if (val > 255)
|
||
|
val = 255;
|
||
|
|
||
|
if (val < 0)
|
||
|
val = 0;
|
||
|
ptr_buffer[j * channel + k] = (unsigned char)val;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
printf("create_lut exit \n");
|
||
|
return lut;
|
||
|
}
|
||
|
|
||
|
void initLut()
|
||
|
{
|
||
|
if (access(LUT_GRAY_LUT_PATH, F_OK) != -1)
|
||
|
lutGrayMat_old = cv::imread(LUT_GRAY_LUT_PATH, IMREAD_GRAYSCALE); // 灰色校正值
|
||
|
if (access(LUT_COLOR_LUT_PATH, F_OK) != -1)
|
||
|
lutColorMat_old = cv::imread(LUT_COLOR_LUT_PATH, IMREAD_GRAYSCALE); // 彩色校正值
|
||
|
}
|
||
|
|
||
|
void correctColor(cv::Mat src, bool enhance)
|
||
|
{
|
||
|
Mat tSrc;
|
||
|
Mat lutMat;
|
||
|
int patch = 0;
|
||
|
int SIZE = src.cols / 12;
|
||
|
// printf("lutMat.empty() src.width::%d SIZE: %d \n", src.cols, SIZE);
|
||
|
|
||
|
if (src.type() == CV_8UC3)
|
||
|
{
|
||
|
patch = (src.cols * 3) / SIZE;
|
||
|
if (lutColorMat_old.empty())
|
||
|
{
|
||
|
if (access(LUT_COLOR_LUT_PATH, F_OK) != -1)
|
||
|
{
|
||
|
lutColorMat_old = imread(LUT_COLOR_LUT_PATH, IMREAD_GRAYSCALE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// printf("error error error %s NOT FOUND \n", LUT_COLOR_LUT_PATH);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
lutMat = lutColorMat_old;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
patch = (src.cols) / SIZE;
|
||
|
if (lutGrayMat_old.empty())
|
||
|
{
|
||
|
if (access(LUT_GRAY_LUT_PATH, F_OK) != -1)
|
||
|
{
|
||
|
lutGrayMat_old = imread(LUT_GRAY_LUT_PATH, IMREAD_GRAYSCALE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// printf("error error error %s NOT FOUND", LUT_GRAY_LUT_PATH);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
lutMat = lutGrayMat_old;
|
||
|
}
|
||
|
if (lutMat.empty())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
lutMat = cv::Mat(patch, 256, CV_8UC(SIZE), lutMat.data);
|
||
|
tSrc = cv::Mat(src.rows, patch, CV_8UC(SIZE), src.data);
|
||
|
for (int i = 0; i < patch; i++)
|
||
|
{
|
||
|
LUT(tSrc(cv::Rect(i, 0, 1, src.rows)), lutMat(cv::Rect(0, i, 256, 1)), tSrc(cv::Rect(i, 0, 1, src.rows)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void creatLUTData(int mode, CISVendor vendor)
|
||
|
{
|
||
|
printf("eneter creatLUTData \n");
|
||
|
auto colormode = mode == IMAGE_COLOR ? IMREAD_COLOR : IMREAD_GRAYSCALE;
|
||
|
std::string blackPath = mode == IMAGE_COLOR ? LUT_COLOR_BLACK_PATH : LUT_GRAY_BLACK_PATH;
|
||
|
std::string whitePath = mode == IMAGE_COLOR ? LUT_COLOR_WHITE_PATH : LUT_GRAY_WHITE_PATH;
|
||
|
std::string lutsavePath = mode == IMAGE_COLOR ? LUT_COLOR_LUT_PATH : LUT_GRAY_LUT_PATH;
|
||
|
cv::Mat lut;
|
||
|
cv::Mat twMat = cv::imread(whitePath, colormode);
|
||
|
cv::Mat tbMat = cv::imread(blackPath, colormode);
|
||
|
cv::Mat wMat, bMat;
|
||
|
if (mode == IMAGE_COLOR)
|
||
|
{
|
||
|
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(extractRepresentRow(bMat), extractRepresentRow(wMat), mode, vendor); // add by liuyong: 刘丁维提供 2019/4/12
|
||
|
Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1);
|
||
|
memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256);
|
||
|
cv::imwrite(lutsavePath, dst);
|
||
|
printf("exit creatLUTData \n");
|
||
|
}
|
||
|
static int num = 0;
|
||
|
cv::Mat GetMergeMat(void *data, int width, int height, int type)
|
||
|
{
|
||
|
if (!data)
|
||
|
return cv::Mat();
|
||
|
|
||
|
cv::Mat mat;
|
||
|
cv::Mat saveMat;
|
||
|
std::vector<cv::Mat> ch_mats(3);
|
||
|
int dstwidth, dstheight;
|
||
|
dstwidth = width * 3;
|
||
|
dstheight = height / 3 - 1;
|
||
|
|
||
|
if (type == CV_8UC3)
|
||
|
{
|
||
|
mat = cv::Mat(height / 3 - 1, width * 9, CV_8UC1, data);
|
||
|
saveMat = cv::Mat(dstheight, dstwidth, CV_8UC3);
|
||
|
}
|
||
|
else
|
||
|
{ // gray
|
||
|
saveMat = cv::Mat(height, width * 3, CV_8UC1, data);
|
||
|
}
|
||
|
static int savenum;
|
||
|
if (type == CV_8UC3)
|
||
|
{
|
||
|
for (int i = 0; i < 3; i++)
|
||
|
{ // B G R
|
||
|
cv::Mat mattemp = mat(cv::Rect(dstwidth * i, 0, dstwidth, dstheight));
|
||
|
// ch_mats.push_back(mattemp);
|
||
|
ch_mats[i] = mattemp;
|
||
|
}
|
||
|
swap(ch_mats[1], ch_mats[2]);
|
||
|
cv::merge(ch_mats, saveMat);
|
||
|
}
|
||
|
return saveMat.clone();
|
||
|
}
|
||
|
|
||
|
// 3399 旧版本 华凌cis拼接算法
|
||
|
cv::Mat GetMergeMat(cv::Mat &mat, int width, int height, int type)
|
||
|
{
|
||
|
if (mat.empty())
|
||
|
return cv::Mat();
|
||
|
cv::Mat saveMat;
|
||
|
std::vector<cv::Mat> ch_mats(3);
|
||
|
int dstwidth, dstheight;
|
||
|
dstwidth = width * 3;
|
||
|
dstheight = height / 3 - 1;
|
||
|
|
||
|
if (type == CV_8UC3)
|
||
|
{
|
||
|
saveMat = cv::Mat(dstheight, dstwidth, CV_8UC3);
|
||
|
for (int i = 0; i < 3; i++)
|
||
|
{ // B G R
|
||
|
cv::Mat mattemp = mat(cv::Rect(dstwidth * i, 0, dstwidth, dstheight));
|
||
|
// ch_mats.push_back(mattemp);
|
||
|
ch_mats[i] = mattemp;
|
||
|
}
|
||
|
swap(ch_mats[1], ch_mats[2]);
|
||
|
cv::merge(ch_mats, saveMat);
|
||
|
return saveMat;
|
||
|
}
|
||
|
return mat;
|
||
|
}
|
||
|
|
||
|
// 3399 敦南cis 300 600 拼接算法
|
||
|
cv::Mat GetMergeMat(int dstwidth, int dstheight, int type, cv::Mat &mat, unsigned int fpgaversion)
|
||
|
{
|
||
|
return CImageMerge().MergeImage(type == CV_8UC3, mat, dstwidth, dstheight, fpgaversion);
|
||
|
}
|
||
|
|
||
|
void savescannerinfo(ScannerNativeParam params)
|
||
|
{
|
||
|
Get_static_jsonconfig().savescannerinfo(params);
|
||
|
}
|
||
|
|
||
|
ScannerNativeParam getscannerinfo()
|
||
|
{
|
||
|
return Get_static_jsonconfig().getscannerinfo();
|
||
|
}
|
||
|
|
||
|
void savecisparams(HGCorrectConfigs cfgs)
|
||
|
{
|
||
|
Get_static_jsonconfig().savecisconfig(cfgs);
|
||
|
}
|
||
|
|
||
|
HGCorrectConfigs getcisparams()
|
||
|
{
|
||
|
return Get_static_jsonconfig().getcorrectconfigs();
|
||
|
}
|