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

845 lines
25 KiB
C++
Raw Permalink Normal View History

2023-04-08 00:56:20 +00:00
#include "Capturer.h"
#include "DevUtil.h"
#include <thread>
#include <time.h>
#include <sstream>
#include "Gpio.h"
#include "FpgaComm.h"
#include "gvideoisp1.h"
#include "config.h"
#include <iostream>
#include <functional>
#include "applog.h"
#include "stringex.hpp"
#include <opencv2/opencv.hpp>
#include "filetools.h"
#include "CameraParam.h"
#include "correct_ultis.h"
2023-04-08 00:56:20 +00:00
using namespace std;
#define LOG_PATH "/usr/local/correct.log"
FileTools ft(LOG_PATH);
static std::string loggername = "Capturer";
bool isAutoCorrect = true;
double Radio = 1;
2023-04-08 00:56:20 +00:00
cv::Mat mBuffMat;
cv::Mat out;
Capturer::Capturer()
2023-05-02 01:50:55 +00:00
: vdd_cis_3voff_pin(new GpioOut(CIS_3v3_Off)),
vdd_vis_5ven_pin(new GpioOut(CIS_5v_En)),
reset_pin(new GpioOut(Fpga_Reset)),
image_in_transfer_pin(new Gpio(Image_In_Transfer)),
initDone_pin(new Gpio(Fpga_InitDone)),
fpgaLoad(new GpioOut(Fpga_Load)),
2023-04-08 00:56:20 +00:00
bcorrecting(false)
{
LOG_INIT();
fpgaComm.reset(new FpgaComm());
fpga_reset();
fpgaComm->resetADC();
fpgaComm->setDelayTime(0X3e8);
video.reset(new VIDEO_CLASS());
}
Capturer::~Capturer()
{
}
2023-05-02 01:50:55 +00:00
void Capturer::Fpga_regsAccess_reset(bool enable){
}
2023-04-08 00:56:20 +00:00
void Capturer::open()
{
cisconfigs = getcisparams();
int height = 6000;
set_sp(0x0208);
fpgaComm->setColorMode(1);
// int height = 2000;
// set_sp(0x0bf0);
// fpgaComm->setColorMode(0);
fpgaComm->setDpi(1);
fpgaComm->setSample(256);
fpgaComm->enableLed(true);
//设置曝光值等
int exp[2][3];
int gains[2][6];
int offsets[2][6];
for (int i = 0; i < 3; i++)
set_expo(i, 0x300); //0x1b0);
for (int i = 0; i < 2; i++)
{
set_gain(i, 300);
set_offset(i, 150);
}
fpgaComm->setFrameHeight(12);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
fpgaComm->capture();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
video.reset(new VIDEO_CLASS());
video->open(1632, height);
fpgaComm->setFrameHeight(12);
for (int i = 0; i < 1; i++)
{
fpgaComm->capture();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
fpgaComm->setFrameHeight(height);
}
static int val = 0;
static double exp_ratio = 0.1;
void Capturer::open(HGScanConfig config,FPGAConfigParam fpgaparam)
2023-04-08 00:56:20 +00:00
{
if (val > 4000)
val = 0;
if (exp_ratio > 2.0)
exp_ratio = 0.1;
cisconfigs = getcisparams();
2023-05-02 01:50:55 +00:00
auto hgsize = papersMap[(PaperSize)config.g200params.paper];
int height = hgsize.height;
2023-04-08 00:56:20 +00:00
fpgaComm->setColorMode(config.g200params.color ? 1 : 0);
auto info = jsonconfig().getscannerinfo();
//set_sp(config.g200params.color ? cisconfigs.color.sp : cisconfigs.gray.sp); //0x03fa : 0x0bf0
int clrsp, graysp;
// if (scannerSp.count((SpeedMode)info.speedmode) <= 0)
// {
// #ifdef G200
// clrsp = scannerSp[SpeedMode::PPM100].colorSp;
// graysp = scannerSp[SpeedMode::PPM100].colorSp;
// #else
// clrsp = scannerSp[SpeedMode::PPM70].colorSp;
// graysp = scannerSp[SpeedMode::PPM70].colorSp;
// #endif
// }
// else
// {
// clrsp = scannerSp[(SpeedMode)info.speedmode].colorSp;
// graysp = scannerSp[(SpeedMode)info.speedmode].colorSp;
// }
clrsp=info.color_sp;
graysp = info.gray_sp;
set_sp(config.g200params.color ? clrsp : graysp);
printf("\n capture color sp =%d, gray sp =%d",clrsp,graysp);
2023-04-08 00:56:20 +00:00
//set_sp(config.g200params.color ? 0x335 : 0x99f); //G100 0x438 0xca8 60 ppm 0x335 : 0x99f 100ppm
//G200 SP极限值205 0x27c 0x775 140ppm
fpgaComm->setDpi(config.g200params.dpi); //0 300dpi 1 200dpi
2023-04-08 00:56:20 +00:00
fpgaComm->setSample(256);
fpgaComm->enableLed(true);
//设置曝光值等
configFPGAParam(false, config.g200params.color);
//fpgaComm->setFrameHeight(12);
//std::this_thread::sleep_for(std::chrono::milliseconds(1));
//fpgaComm->capture();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
video->open(1632, config.g200params.color ? height : height / 3);
fpgaComm->setFrameHeight(12);
for (int i = 0; i < 1; i++)
{
fpgaComm->capture();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
fpgaComm->setFrameHeight(config.g200params.color ? height : height / 3);
//fpgaComm->update();
}
void Capturer::close()
{
if (video)
{
video->close();
}
}
void Capturer::start()
{
if (video)
video->start();
}
void Capturer::stop()
{
if (video)
video->stop();
}
void Capturer::reset()
{
fpga_reset();
fpgaComm->resetADC();
fpgaComm->setDelayTime(0X3e8);
fpgaComm->setRegs(0x00, fpgaComm->getRegs(0x00));
fpgaComm->setRegs(0x01, fpgaComm->getRegs(0x01));
}
void Capturer::set_size(int width, int height)
{
if (video)
video->set_size(width, height);
}
void Capturer::snap()
{
fpgaComm->capture();
}
std::shared_ptr<IRegsAccess> Capturer::regs()
{
return fpgaComm;
}
void Capturer::fpga_reset()
{
reset_pin->setValue(Gpio::Low);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
reset_pin->setValue(Gpio::High);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
void Capturer::fpga_reload()
{
//fpga 代码重载
fpgaLoad->setValue(Gpio::Low);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaLoad->setValue(Gpio::High);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaComm->resetADC();
}
2023-04-08 00:56:20 +00:00
void Capturer::set_expo(int ix, int val)
{
switch (ix)
{
case 0:
fpgaComm->setAExposureB(val);
break;
case 1:
fpgaComm->setAExposureG(val); //!< ok
break;
case 2:
fpgaComm->setAExposureR(val); //!< ok
break;
case 3:
fpgaComm->setBExposureB(val);
break;
case 4:
fpgaComm->setBExposureG(val);
break;
case 5:
fpgaComm->setBExposureR(val);
break;
default:
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
void Capturer::set_gain(int ix, int val)
{
for (int i = 0; i < 6; i++)
{
if (ix)
fpgaComm->setAGain(i, val);
else
fpgaComm->setBGain(i, val);
}
}
void Capturer::set_offset(int ix, int val)
{
for (int i = 0; i < 6; i++)
{
if (ix)
fpgaComm->setAOffset(i, val);
else
fpgaComm->setBOffset(i, val);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
void Capturer::configFPGAParam(bool iscorrect, int mode)
{
int exposures[2][3];
int gains[2][6];
int offsets[2][6];
if (iscorrect)
{
memcpy(&exposures[0][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.expF : cisconfigs.grayCorrect.expF, sizeof(int) * 3);
memcpy(&exposures[1][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.expB : cisconfigs.grayCorrect.expB, sizeof(int) * 3);
memcpy(&gains[0][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.gainF : cisconfigs.grayCorrect.gainF, sizeof(int) * 6);
memcpy(&gains[1][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.gainB : cisconfigs.grayCorrect.gainB, sizeof(int) * 6);
memcpy(&offsets[0][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.offsetsF : cisconfigs.grayCorrect.offsetsF, sizeof(int) * 6);
memcpy(&offsets[1][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.offsetsB : cisconfigs.grayCorrect.offsetsB, sizeof(int) * 6);
}
else
{
memcpy(&exposures[0][0], mode == IMAGE_COLOR ? cisconfigs.color.expF : cisconfigs.gray.expF, sizeof(int) * 3);
memcpy(&exposures[1][0], mode == IMAGE_COLOR ? cisconfigs.color.expB : cisconfigs.gray.expB, sizeof(int) * 3);
memcpy(&gains[0][0], mode == IMAGE_COLOR ? cisconfigs.color.gainF : cisconfigs.gray.gainF, sizeof(int) * 6);
memcpy(&gains[1][0], mode == IMAGE_COLOR ? cisconfigs.color.gainB : cisconfigs.gray.gainB, sizeof(int) * 6);
memcpy(&offsets[0][0], mode == IMAGE_COLOR ? cisconfigs.color.offsetsF : cisconfigs.gray.offsetsF, sizeof(int) * 6);
memcpy(&offsets[1][0], mode == IMAGE_COLOR ? cisconfigs.color.offsetsB : cisconfigs.gray.offsetsB, sizeof(int) * 6);
}
//static int val = 0;
//int step = 100;
// for(int i = 0;i<2;i++)
// {
// for(int j =0 ;j<3;j++)
// {
// exposures[i][j] =i==0? cisconfigs.gray.expF[j]*exp_ratio:cisconfigs.gray.expB[j]*exp_ratio;
// printf("exp_ratio = %0.2f \r\n",exp_ratio);
// }
// }
// val+=step;
// exp_ratio += 0.1;
// for (int i = 0; i < 2; i++)
// {
// for (int j = 0; j < 6; j++)
// {
2023-05-02 01:50:55 +00:00
2023-04-08 00:56:20 +00:00
// printf("gains[%d][%d] = %d \r\n", i, j, gains[i][j]);
// printf("offsets[%d][%d] = %d \r\n", i, j, offsets[i][j]);
// if (j < 3)
// {
// printf("exposures[%d][%d] = %d \r\n", i, j, exposures[i][j]);
// }
// }
// }
setFGPAParmas(exposures, gains, offsets);
}
void Capturer::setFGPAParmas(int exposures[2][3], int gains[2][6], int offsets[2][6])
{
//set exposuretime
fpgaComm->setAExposureB(exposures[0][0]);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaComm->setAExposureG(exposures[0][1]);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaComm->setAExposureR(exposures[0][2]);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaComm->setBExposureB(exposures[1][0]);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaComm->setBExposureG(exposures[1][1]);
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaComm->setBExposureR(exposures[1][2]);
// set Gain and offset
for (int i = 0; i < 6; i++)
{
//LOGD("setAGain %d =:%d", i , gains[0][i]);
fpgaComm->setAGain(i, gains[0][i]); // A面增加
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaComm->setBGain(i, gains[1][i]); // B面增益
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaComm->setAOffset(i, offsets[0][i]); // A面偏置
std::this_thread::sleep_for(std::chrono::milliseconds(15));
fpgaComm->setBOffset(i, offsets[1][i]); //B面偏置
}
}
void *Capturer::readFrame(int timeout)
{
auto ret= video->read_frame(timeout);
2023-05-02 01:50:55 +00:00
unsigned int val;
//fpgaComm->update();
2023-04-08 00:56:20 +00:00
return ret;
}
bool Capturer::is_runing()
{
return true;
}
int Capturer::color()
{
return fpgaComm->getColorMode() ? 16 : 0;
}
int Capturer::height()
{
return fpgaComm->getFrameHeight();
}
int Capturer::width()
{
return 1632;
}
void Capturer::set_sp(int sp)
{
fpgaComm->setSp(sp);
}
void Capturer::init_autocorrect(int colormode)
{
std::thread t_correctthread = std::thread(&Capturer::autocorrect, this, colormode);
t_correctthread.detach();
}
void Capturer::autocorrect(int colormode)
{
bcorrecting = true;
cisconfigs = getcisparams();
scannerinfo = getscannerinfo();
ft.clear();
ft.append_log("start correct");
if (m_captureCallback)
{
m_captureCallback(colormode, colormode ? "------开始彩色校正------\r\n" : "------开始灰度校正------\r\n");
}
creatcorrectconfig(colormode ? IMAGE_COLOR : IMAGE_GRAY);
creatLUTData(colormode ? IMAGE_COLOR : IMAGE_GRAY, CISVendor::HUALIN_CIS_V0);
if (colormode)
{
memcpy(cisconfigs.color.offsetsF, cisconfigs.colorCorrect.offsetsF, sizeof(int) * 6);
memcpy(cisconfigs.color.offsetsB, cisconfigs.colorCorrect.offsetsB, sizeof(int) * 6);
memcpy(cisconfigs.color.expF, cisconfigs.colorCorrect.expF, sizeof(int) * 3);
memcpy(cisconfigs.color.expB, cisconfigs.colorCorrect.expB, sizeof(int) * 3);
}
else
{
memcpy(cisconfigs.gray.offsetsF, cisconfigs.grayCorrect.offsetsF, sizeof(int) * 6);
memcpy(cisconfigs.gray.offsetsB, cisconfigs.grayCorrect.offsetsB, sizeof(int) * 6);
memcpy(cisconfigs.gray.expF, cisconfigs.grayCorrect.expF, sizeof(int) * 3);
memcpy(cisconfigs.gray.expB, cisconfigs.grayCorrect.expB, sizeof(int) * 3);
}
savecisparams(cisconfigs);
initLut();
if (m_captureCallback)
m_captureCallback(4, colormode ? "------彩色校正完成------\r\n" : "------灰度校正完成------\r\n");
reset();
bcorrecting = false;
printf("init_autocorrect exit \n");
2023-04-08 00:56:20 +00:00
}
void Capturer::creatcorrectconfig(int mode)
{
std::string msg = mode == IMAGE_COLOR ? "彩色" : "灰度";
//LOG_TRACE("creatcorrectconfig \r\n");
ft.append_log("开始" + msg + "暗场校正");
if (m_captureCallback)
m_captureCallback(mode, "开始" + msg + "暗场校正\r\n");
openDevice(mode);
bool isDone = false;
int i = 1;
initStep();
while (!isDone) //先暗场
{
configFPGAParam(true, mode);
string log = "==============================第" + to_string(i) + "次=============================== \r\n";
ft.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
fpgaComm->enableLed(false);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
//fpgaComm->update();
fpgaComm->capture();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
isDone = saveLutImg(mode, mode == IMAGE_COLOR ? 0 : 2); // 0 color_black 1 color_white 2 gray_balck 3 gray_white
i++;
}
i = 1;
isDone = false;
initStep();
ft.append_log("开始" + msg + "明场校正");
if (m_captureCallback)
m_captureCallback(mode, "开始" + msg + "明场校正 \r\n");
while (!isDone) //后明场
{
configFPGAParam(true, mode);
string log = "==============================第" + to_string(i) + "次=============================== \r\n";
ft.append_log(log);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
fpgaComm->enableLed(true);
//fpgaComm->update();
2023-04-08 00:56:20 +00:00
std::this_thread::sleep_for(std::chrono::milliseconds(200));
fpgaComm->capture();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
isDone = saveLutImg(mode, mode == IMAGE_COLOR ? 1 : 3);
//isDone = true;
i++;
}
LOG_TRACE(string_format("creatcorrectconfig %s \r\n", (mode == IMAGE_COLOR ? " Color" : " Gray")));
video->close();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
void Capturer::openDevice(int mode)
{
this->reset();
// #ifdef G00
int width = 1632;
int height = 6000;
// #else
// int width = 1728;
// int height = 6000;
// #endif
video->open(width, mode == IMAGE_COLOR ? height : height / 3);
std::this_thread::sleep_for(std::chrono::milliseconds(20));
fpgaComm->capture();
video->read_frame(200); //丢弃第一张无效图像
LOG_TRACE(string_format("cisconfigs.grayCorrect.sp = %d \r\n", cisconfigs.grayCorrect.sp));
//fpgaComm->setSp(mode == IMAGE_COLOR ? cisconfigs.colorCorrect.sp : cisconfigs.grayCorrect.sp);
auto info = getscannerinfo();
fpgaComm->setSp(mode == IMAGE_COLOR ? info.color_sp : info.gray_sp); //0x438 : 0xca8
fpgaComm->setSample(256);
fpgaComm->setDpi(1);
fpgaComm->setColorMode(mode == IMAGE_COLOR ? 1 : 0);
fpgaComm->setFrameHeight(mode == IMAGE_COLOR ? height : height / 3);
fpgaComm->enableLed(true);
}
static int savelutindex = 0;
bool Capturer::saveLutImg(int mode, int index)
{
int offset_indexs[12] = {0, 1, 2, 5, 4, 3, 3, 4, 5, 2, 1, 0};
int count = 1;
int height = 6000;
int width = 1632;
bool isNeedSave = true;
string log;
for (int i = 0; i < 1; i++)
{
void *data = video->read_frame(1500);
if (data == NULL)
{
log = "图像采集失败!\r\n";
2023-04-08 00:56:20 +00:00
ft.append_log(log);
isNeedSave = false;
if (m_captureCallback)
m_captureCallback(mode, log);
}
if (data && isNeedSave)
{
if (mode == IMAGE_COLOR)
{
cv::Mat mergeMat = GetMergeMat(data, this->width(), this->height(), this->color());
cv::cvtColor(mergeMat, mergeMat, CV_RGB2BGR);
if (i == 0)
{
double values[2][3];
cv::Scalar a = cv::mean(mergeMat(cv::Rect(0, 0, mergeMat.cols / 2, mergeMat.rows)));
cv::Scalar b = cv::mean(mergeMat(cv::Rect(mergeMat.cols / 2, 0, mergeMat.cols / 2, mergeMat.rows)));
for (int j = 0; j < 3; j++)
{
values[0][j] = a.val[2 - j];
values[1][j] = b.val[2 - j];
}
double offValues[12];
for (int n = 0; n < 2; n++)
{
cv::Mat img = mergeMat(cv::Rect(mergeMat.cols * n / 2, 0, mergeMat.cols / 2, mergeMat.rows));
int offset_total = 0;
for (int s = 0; s < 6; s++) //
{
int k = n * 6 + s;
int offset_wdth;
if ((s == 0 && k == 0) || (s == 5 && k == 11))
offset_wdth = 288;
else
offset_wdth = 432;
cv::Scalar mean;
mean = cv::mean(img(cv::Rect(offset_total, 0, offset_wdth, img.rows)));
if ((s == 0 && k == 0) || (s == 5 && k == 11))
offset_total += 288;
else
offset_total += 432;
offValues[k] = mean.val[0];
}
}
log += " 彩色A面RGB值" + std::to_string(values[0][0]) + "," + std::to_string(values[0][1]) + "," + std::to_string(values[0][2]) + "\r\n";
log += " 彩色B面RGB值" + std::to_string(values[1][0]) + "," + std::to_string(values[1][1]) + "," + std::to_string(values[1][2]) + "\r\n";
ft.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
if (index % 2 == 1)
{ //明场
//imwrite(std::to_string(savelutindex++) + "clwh.jpg", mergeMat);
log = "开始彩色明场校正 \r\n";
for (int s = 0; s < 2; s++)
{
int *exposures = (int *)(s == 0 ? cisconfigs.colorCorrect.expF : cisconfigs.colorCorrect.expB);
for (int x = 0; x < 3; x++)
{
int k = (3 * s + x);
int diff = LIGHT_DIFF(scannerinfo.clr_maxbright, *((double *)values + k));
log += " 明场:" + std::to_string(k) + ";diff" + std::to_string(diff) + "\r\n";
double step = diff * Radio;
2023-04-08 00:56:20 +00:00
int preStep = *((int *)expStep + k);
if (step * preStep < 0)
{
step = 0 - preStep / 2;
}
FMT_STEP(step);
bool isMinStep = abs(step) == 1 && step == *((int *)expStep + k);
bool isOutBounds = exposures[x] >= 1770 && step > 0;
isOutBounds |= exposures[x] <= 0 && step < 0;
if (isOutBounds)
log += "" + to_string(x) + "个明场校正异常 \r\n";
else if (abs(diff) >= 1 || isMinStep)
2023-04-08 00:56:20 +00:00
{
*((int *)expStep + k) = (int)(step);
exposures[x] += step;
if (exposures[x] > 1770)
{
exposures[x] = 1770;
}
if (exposures[x] < 0)
exposures[x] = 0;
isNeedSave = false;
}
log += " 曝光值:" + to_string(exposures[x]) + "\r\n";
log += " 调整步长:" + to_string(*((int *)expStep + k)) + "\r\n";
if (isNeedSave)
log += "彩色明场校正完成\r\n";
}
}
ft.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
}
else //彩色暗场
{
int *offsets;
//imwrite(std::to_string(savelutindex++) + "clrblk.jpg", mergeMat);
log = "开始彩色暗场校正";
for (int s = 0; s < 2; s++)
{
offsets = (int *)(s == 0 ? cisconfigs.colorCorrect.offsetsF : cisconfigs.colorCorrect.offsetsB);
for (int j = 0; j < 6; j++)
{
int k = s * 6 + j;
double diff = BLACK_DIFF(offValues[k]);
double step = Radio * diff;
2023-04-08 00:56:20 +00:00
int preStep = offsetStep[k];
if (step * preStep < 0)
{
step = 0 - preStep / 2;
}
else
{
Radio = 1;
2023-04-08 00:56:20 +00:00
}
FMT_STEP(step);
bool isMinStep = abs(step) == 1 && step == offsetStep[k];
bool isOutBounds = offsets[j] >= 255 && step > 0;
isOutBounds |= offsets[j] <= 0 && step < 0;
log += " 暗场校正 :" + std::to_string(k) + ";diff" + std::to_string(diff) + ";light" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n";
if (isOutBounds)
log += "" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n";
else if (abs(step) > 1 || isMinStep)
{
offsetStep[k] = (int)(step);
offsets[offset_indexs[k]] += step;
log += "offsetStep" + std::to_string(k) + " = " + std::to_string(offsetStep[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n";
if (offsets[offset_indexs[k]] < 1)
offsets[offset_indexs[k]] = 1;
if (offsets[offset_indexs[k]] > 255)
offsets[offset_indexs[k]] = 255;
isNeedSave = false;
}
log += (s == 0 ? "彩色正面" : "彩色背面");
log += "偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," + std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "\r\n";
if (isNeedSave)
log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n");
}
}
ft.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
}
if (isNeedSave)
{
mBuffMat.release();
mBuffMat = mergeMat;
}
}
if (isNeedSave && i == 0)
{
if (i > 0)
{
out.release();
cv::vconcat(mBuffMat, mergeMat, out);
}
else
{
mergeMat.copyTo(out);
cv::cvtColor(out, out, CV_BGR2RGB);
}
char buffer[40];
sprintf(buffer, "/usr/local/huago/lut_%d.bmp", index);
imwrite(buffer, out);
LOG_TRACE(string_format("save image %s ", buffer));
}
else if (i != 0)
{
cv::vconcat(mBuffMat, mergeMat, mBuffMat);
}
}
else
{ // 灰色模式
cv::Mat src = GetMergeMat(data, this->width(), this->height(), this->color());
//imwrite(std::to_string(savelutindex++) + "graywh.jpg", src);
char buffer[40];
sprintf(buffer, "/usr/local/huago/lut_%d.bmp", index);
double values[2];
values[0] = cv::mean(src(cv::Rect(0, 0, src.cols / 2, src.rows))).val[0];
values[1] = cv::mean(src(cv::Rect(src.cols / 2, 0, src.cols / 2, src.rows))).val[0];
double offValues[12];
for (int n = 0; n < 2; n++)
{
cv::Mat img = src(cv::Rect(src.cols * n / 2, 0, src.cols / 2, src.rows));
int offset_total = 0;
for (int s = 0; s < 6; s++) //
{
int k = n * 6 + s;
int offset_wdth;
if ((s == 0 && k == 0) || (s == 5 && k == 11))
offset_wdth = 288;
else
offset_wdth = 432;
cv::Scalar mean;
mean = cv::mean(img(cv::Rect(offset_total, 0, offset_wdth, img.rows)));
if ((s == 0 && k == 0) || (s == 5 && k == 11))
offset_total += 288;
else
offset_total += 432;
offValues[k] = mean.val[0];
}
}
if (index % 2 == 1) //灰度明场
{
log = "-----开始灰色明场校正-----\r\n";
log += " 灰色扫描灰度明场均值:" + to_string(values[0]) + "," + to_string(values[1]) + "\r\n";
for (int s = 0; s < 2; s++)
{
int *exposures = (int *)(s == 0 ? cisconfigs.grayCorrect.expF : cisconfigs.grayCorrect.expB);
int diff = LIGHT_DIFF(scannerinfo.gray_maxbright, values[s]);
double step = diff * Radio;
2023-04-08 00:56:20 +00:00
log += " 明场:" + to_string(s) + ";diff" + to_string(diff) + "\r\n";
int preStep = expStep[s][0];
if (step * preStep < 0)
{
step = 0 - preStep / 2;
}
else
{
Radio = 1;
2023-04-08 00:56:20 +00:00
}
FMT_STEP(step);
int exp = *(exposures + 1);
std::string ss1(string_format("exp[%d] = %d step = %.3f \r\n", s, exp, step));
log += ss1;
bool isMinStep = abs(step) == 1 && step == expStep[s][0];
bool isOutBounds = exp >= 1770 && step > 0;
isOutBounds |= exp <= 0 && step < 0;
if (isOutBounds)
log += "" + to_string(s) + "个明场校正异常 \r\n";
else if (abs(diff) > 1 || isMinStep)
2023-04-08 00:56:20 +00:00
{
exp += step;
if (exp < 0)
exp = 0;
if (exp > 1770)
exp = 1770;
float coffe[3] = {1 ,1 ,1}; // 0.2, 1,0.51
for (int k = 0; k < 3; k++)
{
*(exposures + k) = (int)(exp * coffe[k]);
expStep[s][k] = (int)(step);
std::string exps(string_format("expStep[%d][%d] = %.3f\r\n", s, k, step));
log += exps;
std::string ss(string_format("exposures[%d] = %0.3f \r\n", k, exposures[k]));
log += ss;
}
isNeedSave = false;
}
}
ft.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
}
else //灰度暗场
{
log = "开始灰色暗场校正 \r\n";
for (int s = 0; s < 2; s++)
{
int *offsets = (int *)(s == 0 ? cisconfigs.grayCorrect.offsetsF : cisconfigs.grayCorrect.offsetsB);
for (int j = 0; j < 6; j++)
{
int k = s * 6 + j;
double diff = BLACK_DIFF(offValues[k]);
double step = Radio * diff;
2023-04-08 00:56:20 +00:00
int preStep = offsetStep[k];
if (step * preStep < 0)
{
step = 0 - preStep / 2;
}
else
{
Radio = 1;
2023-04-08 00:56:20 +00:00
}
FMT_STEP(step);
bool isMinStep = abs(step) == 1 && step == offsetStep[k];
bool isOutBounds = offsets[j] >= 255 && step > 0;
isOutBounds |= offsets[j] <= 0 && step < 0;
log += " 暗场校正 :" + std::to_string(k) + ";diff" + std::to_string(diff) + ";light" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n";
if (isOutBounds)
log += "" + std::to_string(i) + "面暗场校正异常,暗场值无法降低 \r\n";
else if (abs(step) > 1 || isMinStep)
{
offsetStep[k] = (int)(step);
offsets[offset_indexs[k]] += step;
log += "offsetStep" + std::to_string(k) + " = " + std::to_string(offsetStep[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n";
if (offsets[offset_indexs[k]] < 1)
offsets[offset_indexs[k]] = 1;
if (offsets[offset_indexs[k]] > 255)
offsets[offset_indexs[k]] = 255;
isNeedSave = false;
}
}
log += " 灰度偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," + std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "\r\n";
if (isNeedSave)
log += "灰色暗场校正完成 \r\n";
}
//final report
ft.append_log(log);
if (m_captureCallback)
m_captureCallback(mode, log);
}
if (isNeedSave)
{
LOG_TRACE(string_format("save image path %s", buffer));
imwrite(buffer, src);
}
}
}
}
return isNeedSave;
}