qt-correction-tool/hgdev/ImageMatQueue.cpp

620 lines
20 KiB
C++

#include <predefine.h>
#include "ImageMatQueue.h"
#include "ImageApplyHeaders.h"
#include "ImageMultiOutput.h"
#include "GScan.h"
//#include "jpeglib.h"
#include "filetools.h"
#include <StopWatch.h>
#ifdef WIN32
#pragma comment(lib, "shell32.lib")
#include <ShlObj.h>
#include <tchar.h>
#endif // WIN32
using namespace cv;
using namespace std;
#define DECODE_COLOR_BGR 1
#define DECODE_GRAY 6
G200Decode::G200Decode(std::shared_ptr<std::vector<char>> buff)
{
const int int_buffer_size = 1024;
int buffer_size = buff->size();
int b_buffer_size = 0;
int f_buffer_size = 0;
std::shared_ptr<std::vector<char>> buffB(new std::vector<char>(buff->size()));
std::shared_ptr<std::vector<char>> buffF(new std::vector<char>(buff->size()));
unsigned char *bbuf = (unsigned char *)(buffB->data());
unsigned char *fbuf = (unsigned char *)(buffF->data());
unsigned char *buf = (unsigned char *)(buff->data());
for (int i = 0; i < (buffer_size / int_buffer_size); i++)
{
if (buf[(i + 1) * int_buffer_size - 1] == 0)
{
memcpy(bbuf + b_buffer_size, buf + i * int_buffer_size, int_buffer_size - 1);
b_buffer_size += (int_buffer_size - 1);
}
else if (buf[(i + 1) * int_buffer_size - 1] == 255)
{
memcpy(fbuf + f_buffer_size, buf + i * int_buffer_size, int_buffer_size - 1);
f_buffer_size += (int_buffer_size - 1);
}
}
buffB->resize(b_buffer_size);
buffF->resize(f_buffer_size);
m_buffs.push_back(buffB);
m_buffs.push_back(buffF);
}
G400Decode::G400Decode(std::shared_ptr<std::vector<char>> buff)
{
m_buffs.push_back(buff);
}
ImageMatQueue::ImageMatQueue(ScannerSerial serial):m_serial(serial),
bRun(false),
is_scanning(false),
atm_orgin_image_remains(0)
{
}
void ImageMatQueue::run()
{
if (!m_threadProc.get())
{
bRun = true;
m_threadProc.reset(new thread(&ImageMatQueue::proc, this));
std::cout << "ImageMat queue start running\n" << std::endl;
}
}
ImageMatQueue::~ImageMatQueue(void)
{
LOG("~ImageMatQueue enter\n");
if (m_rawBuffs.Size() > 0)
{
m_rawBuffs.Clear();
m_rawBuffs.ShutDown();
}
if (m_imagedata.Size() > 0)
{
m_imagedata.Clear();
m_imagedata.ShutDown();
}
if (m_threadProc.get())
{
bRun = false;
this_thread::sleep_for(chrono::milliseconds(200));
if (m_threadProc->joinable())
{
m_threadProc->join();
m_threadProc.reset();
}
}
LOG("~ImageMatQueue exit\n");
}
void ImageMatQueue::pushMat(std::shared_ptr<IDecode> data)
{
m_rawBuffs.Put(data);
atm_orgin_image_remains++;
}
#ifdef TWAIN
std::vector<unsigned char> ImageMatQueue::popBmpdata()
{
std::lock_guard<std::mutex> lock(m_mtxJB);
std::vector<unsigned char> retdata = m_imagedata.Take();
return retdata;
}
#else // TWAIN
MatEx ImageMatQueue::popimage()
{
auto ret = m_imagedata.Take();
return ret;
}
void ImageMatQueue::get_image_front_info(ImageInfo *info)
{
auto tempMat = m_imagedata.Front();
info->Width = tempMat.mat.cols;
info->Height = tempMat.mat.rows;
info->bpp = tempMat.Bpp;
}
#endif
bool ImageMatQueue::valid()
{
return m_imagedata.Size();
}
void ImageMatQueue::clear()
{
m_rawBuffs.Clear();
m_imagedata.Clear();
atm_orgin_image_remains = 0;
}
void ImageMatQueue::setparam(const GScanCap &param)
{
LOG( "---------------Set ScanParam Enter-----------\n");
LOG( "colorMode = %d \n" , param.pixelType);
LOG( "papertype = %d \n" , param.paperSize);
LOG( "paperAlign = %d \n" , param.paperAlign);
LOG( "Resolution = %d \n" , param.resolution);
LOG( "UltrasonicDetect = %d \n" , param.hardwareParam.doubleFeedDetection);
LOG( "BindingDetect = %d \n" , param.hardwareParam.bindingDetection);
LOG( "ScrewDetect = %d \n" , param.hardwareParam.skewDetection.enable);
LOG( "ScrewTopLevel = %d \n" , param.hardwareParam.skewDetection.level);
LOG( "ScanCount = %d \n" , param.scanCount);
LOG( "PixType = %d \n" , param.pixelType);
LOG( "IsDuplex = %d \n" , param.scanSide.duplex);
LOG( "DestResulution = %d \n" , param.resolution);
//LOG( "NativeResulution = %d \n" , param.ImageProcessParam.NativeResulution);
LOG( "AutoDiscardBlank = %d \n" , param.scanSide.discardBlank);
LOG( "AutoDiscardBlankVince = %d \n" , param.scanSide.discardBlankVince);
LOG( "IsFold = %d \n" , param.scanSide.fold);
LOG( "AutoCrop = %d \n" , param.imageProcess.autoCrop);
LOG( "AutoDescrew = %d \n" , param.imageProcess.autoDescrew);
LOG( "FillBlackRect = %d \n" , param.imageProcess.fillBlackRect);
LOG( "Filter = %d \n" , param.imageProcess.filter);
LOG( "OutHoleParam.OutHole = %d \n" , param.imageProcess.fillHole.enable);
LOG( "OutHoleParam.OutHoleValue = %d \n" , param.imageProcess.fillHole.ratio);
LOG( "Orentation = %d \n" , param.imageProcess.orentation);
LOG( "AutoDetctOrentation = %d \n" , param.imageProcess.orentation==Orentation::AUTOTEXT_DETECT);
LOG( "BackRotate180 = %d \n" , param.imageProcess.backRotate180);
LOG( "Brightness = %d \n" , param.imageProcess.brightness);
LOG( "Contrast = %d \n" , param.imageProcess.contrast);
//LOG( "Gamma = %d \n" , setiosflags(ios::fixed) , setprecision(2) , param.ImageProcessParam.Gamma);
LOG( "MultiOutRed = %d \n" , param.imageProcess.multiOutFilterRed);
LOG( "MultiOutputType = %d \n" , param.multiOutput);
LOG( "cropRect.enable = %d \n" , param.cropRect.enable);
LOG( "cropRect.x = %d \n" , param.cropRect.x);
LOG( "cropRect.y = %d \n" , param.cropRect.y);
LOG( "cropRect.width = %d \n" , param.cropRect.width);
LOG( "cropRect.height = %d \n" , param.cropRect.height);
LOG( "customGamma.isDefined = %d \n" , param.imageProcess.customGamma.enable);
//LOG( "imgparams.customGamma.table = " , imgparams.customGamma.table);
//LOG( "imgparams.customGamma.tableLength = " , imgparams.customGamma.tableLength);
LOG( "RefuseInflow = %d \n" , param.imageProcess.refuseInflow);
LOG( "ColorCorrection = %d \n" , param.imageProcess.colorCorrection);
LOG( "ErrorExtention = %d \n" , param.imageProcess.errorExtention);
LOG( "TextureRemove = %d \n" , param.imageProcess.textureRemove);
LOG( "imageSharpen = %d \n" , param.imageProcess.sharpenType);
LOG( "SplitImage = %d \n" , param.imageProcess.splitImage);
LOG( "AnswerSheetFilter = %d \n" , param.imageProcess.answerSheetFilterRed);
LOG( "NosieDetach = %d \n" , param.imageProcess.nosieDetach);
scanParam = param;
ImageProcess imgparams = param.imageProcess;
m_iaList.clear();
if (imgparams.fillHole.enable)
{
LOG("Apply CImageApplyOutHole\n");
float scale = imgparams.fillHole.ratio / 100.0;
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyOutHole(200, scale, 50.0)));
}
bool autocrop;// = param.paperSize == TwSS::None||param.paperSize==TwSS::USStatement;
if(param.paperSize == TwSS::None||param.paperSize==TwSS::USStatement)
autocrop=true;
else {
autocrop=imgparams.autoCrop;
}
/*pixtype 0 colcor; 1 gray; 2 bw*/
hgsize temp_Size = papersize.GetPaperSize((int)param.paperSize, 200, param.paperAlign,m_serial);
cv::Size cvSize(temp_Size.cx, temp_Size.cy);
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoCrop(autocrop,
imgparams.autoDescrew,
imgparams.fillBlackRect,
cvSize)));
if (param.scanSide.discardBlank== 1|| param.scanSide.discardBlankVince== 1)
{
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank(param.scanSide.discardBlank==1 ? true : false)));
}
if (param.resolution != param.resolution_native)
{
CImageApplyResize::ResizeType resizeType;
double ratio = 1.0;
hgsize reSize = papersize.GetPaperSize(param.paperSize, param.resolution, param.paperAlign,m_serial);
cv::Size cvSize(reSize.cx, reSize.cy);
if (imgparams.autoCrop || param.cropRect.enable)
{
resizeType = CImageApplyResize::ResizeType::RATIO;
ratio = param.resolution / (float)param.resolution_native;
}
else
{
resizeType = CImageApplyResize::ResizeType::DSIZE;
}
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyResize(resizeType,
cvSize,
ratio,
ratio)));
}
if (param.cropRect.enable &&
!imgparams.autoCrop)
{
LOG("Apply CImageApplyCustomCrop\n");
int width, height;
width = param.cropRect.width;
height = param.cropRect.height;
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyCustomCrop(cv::Rect(param.cropRect.x, param.cropRect.y, width, height))));
}
if (imgparams.filter != ColorFilter::FILTER_NONE && (param.pixelType == ColorMode::Gray||param.pixelType == ColorMode::BlackWhite))
{
LOG("Apply CImageApplyChannel\n");
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyChannel((CImageApplyChannel::channel)(imgparams.filter))));
}
if (imgparams.customGamma.enable)
{
LOG("Apply CImageApplyCustomGamma\n");
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyCustomGamma(imgparams.customGamma.table, imgparams.customGamma.tableLength)));
}
else
{
if (imgparams.brightness != 128 ||
imgparams.contrast != 4 ||
((imgparams.gamma < (1.0f - 1e-2)) || (imgparams.gamma > (1.0f + 1e-2))))
{
LOG("Apply CImageApplyAdjustColors\n");
int temp_contrast = (imgparams.contrast - 4) * 12;
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAdjustColors(imgparams.brightness - 128, temp_contrast, imgparams.gamma)));
}
}
if (param.pixelType == 2 && imgparams.answerSheetFilterRed)
{
LOG("Apply CImageApplyHSVCorrect\n");
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyHSVCorrect(CImageApplyHSVCorrect::Red_Removal)));
}
if (imgparams.refuseInflow)
{
LOG("Apply CImageApplyRefuseInflow\n");
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyRefuseInflow()));
}
if (imgparams.colorCorrection && param.pixelType != ColorMode::BlackWhite)
{
LOG("Apply CImageApplyAutoContrast\n");
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoContrast()));
}
if (imgparams.orentation !=Orentation::ROTATE_NONE||imgparams.backRotate180)
{
CImageApplyRotation::RotationType rotatetype = CImageApplyRotation::RotationType::Invalid;
switch ((CImageApplyRotation::RotationType)imgparams.orentation)
{
case CImageApplyRotation::RotationType::Rotate_90_clockwise:
rotatetype = CImageApplyRotation::RotationType::Rotate_90_clockwise;
break;
case CImageApplyRotation::RotationType::Rotate_180:
rotatetype = CImageApplyRotation::RotationType::Rotate_180;
break;
case CImageApplyRotation::RotationType::Rotate_90_anti_clockwise:
rotatetype = CImageApplyRotation::RotationType::Rotate_90_anti_clockwise;
break;
default:
break;
}
if (imgparams.orentation==Orentation::AUTOTEXT_DETECT)
rotatetype = CImageApplyRotation::RotationType::AutoTextOrientation;
#ifdef WIN32
TCHAR szIniFile[MAX_PATH] = {0};
SHGetSpecialFolderPath(NULL, szIniFile, CSIDL_WINDOWS, TRUE);
_tcscat(szIniFile, _T("\\twain_32\\HuaGoScan\\tessdata"));
int iLen = WideCharToMultiByte(CP_ACP, 0, szIniFile, -1, NULL, 0, NULL, NULL);
char *chRtn = new char[iLen * sizeof(char)];
WideCharToMultiByte(CP_ACP, 0, szIniFile, -1, chRtn, iLen, NULL, NULL);
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyRotation(rotatetype, imgparams.backRotate180, param.resolution, chRtn)));
delete[] chRtn;
#else // WIN32
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyRotation(rotatetype,
imgparams.backRotate180,
param.resolution_native,
"./tessdata")));
#endif
}
if (imgparams.textureRemove)
{
LOG("Apply CImageApplyTextureRemoval\n");
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyTextureRemoval()));
}
if (imgparams.sharpenType!=SharpenType::STNone)
{
LOG("Apply CImageApplyFilter\n");
CImageApplyFilter::FilterMode sharpenType = (CImageApplyFilter::FilterMode)imgparams.sharpenType;
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyFilter(sharpenType)));
}
if (imgparams.nosieDetach)
{
LOG("Apply CImageApplyDetachNoise\n");
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDetachNoise()));
}
if (param.pixelType == ColorMode::BlackWhite) //黑白图像
{
CImageApplyBWBinaray::ThresholdType thrtype;
if (imgparams.errorExtention)
{
thrtype = CImageApplyBWBinaray::ThresholdType::ERROR_DIFFUSION;
}
else
{
thrtype = CImageApplyBWBinaray::ThresholdType::THRESH_BINARY;
}
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyBWBinaray(thrtype)));
if (imgparams.nosieDetach)
{
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDetachNoise()));
}
}
m_multiprc_list.clear();
if (param.imageProcess.multiOutFilterRed && param.pixelType == ColorMode::RGB)
{
LOG("Apply ImageMultiOutputRed\n");
m_multiprc_list.push_back(shared_ptr<IMulti>(new ImageMultiOutputRed(2)));
}
if (param.multiOutput != MultiOutput::Unused)
{
LOG("Apply IMageMulti\n");
m_multiprc_list.push_back(shared_ptr<IMulti>(new IMageMulti(param.multiOutput)));
}
//if (imgparams.SplitImage) {
// m_multiprc_list.push_back(shared_ptr<IMulti>(new CImageApplySplit()));
//}
}
#ifdef TWAIN
void ImageMatQueue::EnqueueBmpBuffer(std::vector<unsigned char> &bmpdata)
{
//std::lock_guard<std::mutex> lock(m_Locker);
m_imagedata.Put(bmpdata);
}
#else // TWAIN
void ImageMatQueue::EnqueueMat(cv::Mat &mat)
{
//m_imagedata.Put(mat);
}
void ImageMatQueue::EnqueueMatOutPut(MatEx &matoutput)
{
m_imagedata.Put(matoutput);
}
#endif
void ImageMatQueue::PaniusCount()
{
atm_orgin_image_remains--;
}
bool ImageMatQueue::empty()
{
//LOG("atm_orgin_image_remains = %d m_imagedata size = %d is_scanning = %s \n", atm_orgin_image_remains,m_imagedata.Size(),is_scanning?"true":"false");
return atm_orgin_image_remains == 0 && m_imagedata.Size() == 0 && !is_scanning;
}
void ImageMatQueue::proc()
{
// ThreadPool pool(4);
// std::vector< std::future<void> > results;
while (bRun)
{
while (m_imagedata.Size() > 0)
{
this_thread::sleep_for(chrono::milliseconds(1));
}
if (m_rawBuffs.Size() == 0)
{
this_thread::sleep_for(chrono::milliseconds(1));
continue;
}
auto buffs = m_rawBuffs.Take()->getImageBuffs();
if (!m_rawBuffs.IsShutDown() && !buffs.empty())
{
vector<cv::Mat> mats;
for (auto &buf : buffs)
{
int rm;
if (scanParam.imageProcess.filter != ColorFilter::FILTER_NONE || scanParam.multiOutput != MultiOutput::Unused)
{
rm = 1;
}
else
{
rm = scanParam.pixelType == 2 ? 1 : 0;
}
StopWatch sw;
cv::Mat mat = cv::imdecode(*buf, rm);
printf("imdecode time = %0.2f decode color =%s \n",sw.elapsed_ms(),rm==1?"Color":"Gray");
buf.reset();
if (mat.empty())
{
LOG("imdecode failed\n");
}
if(m_serial== ScannerSerial::G200Serial || m_serial == ScannerSerial::G100Serial)
{
mats.push_back(mat);
mat.release();
}
else if(m_serial == ScannerSerial::G400Serial || m_serial == ScannerSerial::G300Serial)
{
cv::Mat front = mat(Rect(0, 0, mat.cols / 2, mat.rows));
cv::Mat back = mat(Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows));
mats.push_back(back);
mats.push_back(front);
back.release();
front.release();
}
}
printf("imageprocess image qqqqqqqqqqqqq \n");
for (int j = 0; j < m_iaList.size(); j++)
{
StopWatch sw1;
m_iaList[j]->apply(mats, scanParam.scanSide.duplex);
printf("imageprocess time = %0.2f \n",sw1.elapsed_ms());
}
static int indexxx = 0;
printf("imageprocess image 222222222222 \n");
if (scanParam.scanSide.fold)
{
CImageApplyConcatenation fold(CImageApplyConcatenation::horizontal);
fold.apply(mats, scanParam.scanSide.duplex);
}
printf("imageprocess image 33333333 \n");
if (!scanParam.scanSide.duplex)
{
printf("imageprocess image 33333333aaaaaaaaaaaaaaa \n");
mats.pop_back();
}
printf("imageprocess image 4444444444 \n");
for (int i = 0; i < mats.size(); i++)
{
// if ((!scanParam.scanSide.duplex) && (i == 1))
// break;
bool multiout_red, multi_type, msplit;
multiout_red = scanParam.imageProcess.multiOutFilterRed;
multi_type = scanParam.multiOutput != -1;
msplit = scanParam.imageProcess.splitImage;
if (multiout_red | multi_type | msplit)
{
vector<cv::Mat> retmats;
for (int j = 0; j < m_multiprc_list.size(); j++)
{
if (!mats[i].empty())
retmats = m_multiprc_list[j]->apply(mats[i]);
}
int colormode = 1;
if (scanParam.imageProcess.filter == ColorFilter::FILTER_NONE)
colormode = scanParam.pixelType;
printf("imageprocess image 555555555 colormode=%d\n",colormode);
CImageApplySplit isp(scanParam.multiOutput, msplit, multiout_red, colormode);
printf("imageprocess image 66666666666 \n");
if (!retmats.size()) //如果没有多流,只有拆分
{
auto matexs = isp.SplitMats(mats, scanParam.scanSide.duplex);
for (auto &matex : matexs)
EnqueueMatOutPut(matex);
break;
}
else
{
auto matexs = isp.SplitMats(retmats, scanParam.scanSide.duplex);
for (auto &matex : matexs)
EnqueueMatOutPut(matex);
}
}
else
{
if (!mats[i].empty())
{
int bpp = (ColorMode)scanParam.pixelType == ColorMode::BlackWhite ? 1 : ((ColorMode)scanParam.pixelType == ColorMode::Gray ? 8 : 24);
if (scanParam.imageProcess.filter != ColorFilter::FILTER_NONE)
{
bpp = 8;
}
MatEx out(mats[i], bpp);
EnqueueMatOutPut(out);
}
}
}
PaniusCount();
}
}
}
void ImageMatQueue::EnqueueCheck(bool multiout_red, int s, std::vector<cv::Mat> &retmats)
{
if (multiout_red)
{
int bpp = s == 0 ? 24 : 8;
MatEx out(retmats[s], bpp); //第一张一定是24位彩色图
EnqueueMatOutPut(out);
}
else
{
int bpp = -1;
switch ((MultiOutput)scanParam.multiOutput)
{
case All:
if (s == 0)
bpp = 24;
else if (s == 1)
bpp = 8;
else
bpp = 1;
break;
case ColorGray:
if (s == 0)
bpp = 24;
else if (s == 1)
bpp = 8;
break;
case ColorBw:
if (s == 0)
bpp = 24;
else if (s == 1)
bpp = 1;
break;
case GrayBw:
if (s == 0)
bpp = 8;
else if (s == 1)
bpp = 1;
break;
default:
break;
}
if (bpp != -1)
{
MatEx out(retmats[s], bpp); //第一张一定是24位彩色图
EnqueueMatOutPut(out);
}
}
}
GRawDecode::GRawDecode(std::shared_ptr<std::vector<char>> buff)
{
m_buffs.push_back(buff);
}