rk3399_arm_lvds/capimage/Capturer.cpp

845 lines
25 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 "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"
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;
cv::Mat mBuffMat;
cv::Mat out;
Capturer::Capturer()
: 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)),
bcorrecting(false)
{
LOG_INIT();
fpgaComm.reset(new FpgaComm());
fpga_reset();
fpgaComm->resetADC();
fpgaComm->setDelayTime(0X3e8);
video.reset(new VIDEO_CLASS());
}
Capturer::~Capturer()
{
}
void Capturer::Fpga_regsAccess_reset(bool enable)
{
}
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)
{
if (val > 4000)
val = 0;
if (exp_ratio > 2.0)
exp_ratio = 0.1;
cisconfigs = getcisparams();
auto hgsize = papersMap[(PaperSize)config.g200params.paper];
int height = hgsize.height;
fpgaComm->setColorMode(config.g200params.color ? 1 : 0);
auto info = Get_static_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);
// 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
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();
}
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++)
// {
// 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);
unsigned int val;
// fpgaComm->update();
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");
}
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();
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";
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;
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)
{
*((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;
int preStep = offsetStep[k];
if (step * preStep < 0)
{
step = 0 - preStep / 2;
}
else
{
Radio = 1;
}
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;
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;
}
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)
{
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;
int preStep = offsetStep[k];
if (step * preStep < 0)
{
step = 0 - preStep / 2;
}
else
{
Radio = 1;
}
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;
}