twain3.0/huagao/Device/ImageMatQueue.cpp

463 lines
14 KiB
C++
Raw Permalink 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 "StdAfx.h"
#include "ImageMatQueue.h"
#include "PublicFunc.h"
#include "ImageProcess/ImageApplyHeaders.h"
#include "ImageMultiOutput.h"
#include "filetools.h"
#include <math.h>
#include "StopWatch.h"
using namespace cv;
using namespace std;
#define DECODE_COLOR_BGR 1
#define DECODE_GRAY 6
G200Decode::G200Decode(std::shared_ptr<std::vector<char>> buff)
{
#ifdef G200
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);
buff.reset();
#else // G200
m_buffs.push_back(buff);
#endif
}
ImageMatQueue::ImageMatQueue(void)
: bRun(false)
, is_scanning(false)
,fx(1.001)
,fy(1.007)
,DogEar_index(0)
,is_DogEar(false)
{
atm_orgin_image_remains = 0;
m_dogear.reset(new CImageApplyDogEarDetection(40,1.0,200));
}
void ImageMatQueue::run()
{
if (!m_threadProc) {
bRun = true;
m_threadProc.reset(new thread(&ImageMatQueue::proc, this));
}
}
bool ImageMatQueue::get_isDogEar()
{
return is_DogEar;
}
void ImageMatQueue::reset_DogEar()
{
is_DogEar = false;
DogEar_index = 0;
}
int ImageMatQueue::orginimgcount()
{
return atm_orgin_image_remains;
}
void ImageMatQueue::updatefixratio(float& hratio, float& vratio)
{
if (hratio > 0.80f && hratio < 1.2f && vratio >0.80f && vratio < 1.2f) {
this->fx = hratio;
this->fy = vratio;
}
else
{
writelog("error horizental or vertical ratio");
}
}
ImageMatQueue::~ImageMatQueue(void)
{
m_rawBuffs.Clear();
m_imagedata.Clear();
m_rawBuffs.ShutDown();
m_imagedata.ShutDown();
if (m_threadProc) {
bRun = false;
m_threadProc->join();
m_threadProc.reset();
}
}
static int paperIndex = 0;
void ImageMatQueue::pushMat(std::shared_ptr<IDecode> data)
{
Getimagenumber(true);
m_rawBuffs.Put(data);
atm_orgin_image_remains++;
//string paperindexinfo = "Get the index of "+to_string(++paperIndex)+" Paper";
//FileTools::write_log("D:\\1.txt", paperindexinfo);
}
std::shared_ptr<std::vector<unsigned char>> ImageMatQueue::popBmpdata()
{
return m_imagedata.Take();
}
bool ImageMatQueue::valid()
{
return m_imagedata.Size();
}
void ImageMatQueue::clear()
{
m_rawBuffs.Clear();
m_imagedata.Clear();
atm_orgin_image_remains = 0;
}
void ImageMatQueue::rawBuffsclear()
{
m_rawBuffs.Clear();
}
void ImageMatQueue::setparam(const GScanCap& param)
{
paperIndex = 0;
ischeck_dogear = param.is_dogeardetection;
//FileTools::write_log("D:\\1.txt", "RESET PAPER COUNT");
scanParam = param;
//scanParam.is_duplex = 0;
//scanParam.imageRotateDegree = 90.0f;
m_iaList.clear();
if (scanParam.fillhole.is_fillhole) {
float ratio = scanParam.fillhole.fillholeratio / 100.0;
m_iaList.push_back(shared_ptr<CImageApply>(new CImageOutHole(200, ratio, 50)));
} //ȷ<><C8B7><EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ
{
bool islongcustomcrop = param.papertype == TwSS::USStatement;
//bool isautocrop = param.papertype == TwSS::None;
CSize fixedSize;
#ifdef REAL300DPI
fixedSize = papersize.GetPaperSize(param.papertype, param.resolution_dst > 240.0f ? 300.0f : 200.0f, param.paperAlign);
#else // REAL300DPI
fixedSize = papersize.GetPaperSize(param.papertype, 200.0f, param.paperAlign);
#endif
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoCrop(islongcustomcrop ? islongcustomcrop : param.is_autocrop, param.autodescrew, param.fillbackground, cv::Size(fixedSize.cx, fixedSize.cy), param.is_convex,param.AutoCrop_threshold,param.noise,param.indent)));
}
if (param.is_autodiscradblank_normal || param.is_autodiscradblank_vince) {
//m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank()));
CImageApplyDiscardBlank* disBlank = new CImageApplyDiscardBlank();
//<2F><><EFBFBD><EFBFBD><EFBFBD>հ<EFBFBD>ҳ<EFBFBD><D2B3>ֵ
int area = 200;
int intensity = 15;
int maxHeight = 3307;//A3 height
//ҳ<><D2B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶Ȼ<DFB6>ȡ
if (param.papertype == TwSS::MaxSize)
maxHeight = 6614;
//<2F><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
if (param.discardblank_percent < 10) {
area = 70 + (int)((param.discardblank_percent - 1) * 13.33);
intensity = 8 + param.discardblank_percent / 2;
}
else if (param.discardblank_percent < 20) {
area = 190 + (param.discardblank_percent - 10) * 14;
intensity = 15;
}
else if (param.discardblank_percent < 40) {
area = 400 + (param.discardblank_percent - 20) * 10;
intensity = 20;
}
else if (param.discardblank_percent < 60) {
area = 600 + (param.discardblank_percent - 40) * 20;
intensity = 20;
}
else if (param.discardblank_percent < 80) {
area = 1000 + (param.discardblank_percent - 60) * 55;
intensity = 30;
}
else {
area = 2100 + (param.discardblank_percent - 80) * (maxHeight - 2100) / 20;
intensity = 40;
}
//<2F>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>հ<EFBFBD>ҳ<EFBFBD><D2B3>Ʊ
if (param.is_autodiscradblank_vince) {
area *= 1.5;
intensity *= 1.5;
}
//<2F><><EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD>ֵ
disBlank->setMinArea(area);
disBlank->setIntensity(intensity);
m_iaList.push_back(shared_ptr<CImageApply>(disBlank));
//m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank(param.areanum,param.devnmax)));
}
//filter 0 r 1 g 2 b 3 none enhance color 0 none 1 r 2 g 3 b
if (param.filter != 3 || param.enhance_color) {
int channel = 0; //filter none r g b enhance none r g b
if (param.filter != 3) { channel = param.filter; }
else { channel = param.enhance_color + 3; }
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyChannel(static_cast<CImageApplyChannel::Channel>(channel))));
}
if (param.brightness != 0 || param.contrast != 0 || param.gamma != 1.0) {
double aa = (254 / 2000.0) * param.brightness + 0.5;
int bright = ceil(aa);//[-127,128] 0.128=256.0/2000.0
int contrast=0.0; //= (int)(param.contrast * 0.036);;//[-36,36] 0.036=72.0/2000.0;
if(param.contrast<0.0) // <20>ݲ<EFBFBD><DDB2>޸ĶԱȶȣ<C8B6><C8A3><EFBFBD>ɫ<EFBFBD>ĸ<EFBFBD>ɫƫ
contrast = (int)(param.contrast * 0.036);
else
contrast = (int)(param.contrast * 0.018);
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAdjustColors(bright, contrast, param.gamma)));
}
//<2F><><EFBFBD><EFBFBD><E2BFA8><EFBFBD><EFBFBD>
if (scanParam.hsvcorrect)
{
m_iaList.push_back(shared_ptr<CImageApplyHSVCorrect>(new CImageApplyHSVCorrect(CImageApplyHSVCorrect::CorrectOption::Red_Removal)));
}
//<2F><><EFBFBD><EFBFBD>
if (param.sharpen) {
SharpenBlur sb = (SharpenBlur)param.sharpen;
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplySharpen(sb)));
}
//<2F>Զ<EFBFBD><D4B6><EFBFBD>ɫʶ<C9AB><CAB6>
if (param.automaticcolor)
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyColorRecognition(param.automaticcolortype==1? CImageApplyColorRecognition::ColorRecognitionMode::Color_Gray:CImageApplyColorRecognition::ColorRecognitionMode::Color_Mono)));
//<2F><>ֵ<EFBFBD><D6B5>
if (param.pixtype == 0) //threshold
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyBWBinaray(CImageApplyBWBinaray::ThresholdType::THRESH_BINARY)));
//<2F>ڰ׽<DAB0><D7BD><EFBFBD><EFBFBD>Ż<EFBFBD>
if (scanParam.detachnoise.is_detachnoise&&scanParam.pixtype==0)
{
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDetachNoise(scanParam.detachnoise.detachnoise)));
}
if (param.resolution_dst != param.resolution_native)
{
CImageApplyResize* apply;
bool islongcustomcrop = false;
if (param.papertype == TwSS::USStatement)
islongcustomcrop = true;
if (param.is_autocrop || islongcustomcrop) {
double ratio = param.resolution_dst / 200.0;//
apply = new CImageApplyResize(CImageApplyResize::ResizeType::RATIO, cv::Size(0, 0), ratio, ratio);
}
else {
CSize dSize = papersize.GetPaperSize(param.papertype, param.resolution_dst, param.paperAlign);
apply = new CImageApplyResize(CImageApplyResize::ResizeType::DSIZE, cv::Size(dSize.cx, dSize.cy), 1.0, 1.0);
}
m_iaList.push_back(shared_ptr< CImageApply>(apply));
}
if (scanParam.en_fold)
{
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyConcatenation(CImageApplyConcatenation::horizontal)));
}
if (param.imageRotateDegree != 0.0 || param.is_backrotate180 || param.is_autotext)
{
CImageApplyRotation::RotationType type;
if (param.imageRotateDegree > 89.0f && param.imageRotateDegree < 91.0f)
type = CImageApplyRotation::RotationType::Rotate_90_clockwise;
else if (param.imageRotateDegree > 269.0f && param.imageRotateDegree < 271.0f)
type = CImageApplyRotation::RotationType::Rotate_90_anti_clockwise;
else if (param.imageRotateDegree > 179.0f && param.imageRotateDegree < 181.0f)
type = CImageApplyRotation::RotationType::Rotate_180;
else
type = CImageApplyRotation::RotationType::Invalid;
if (param.is_autotext)
type = CImageApplyRotation::RotationType::AutoTextOrientation;
TCHAR szIniFile[MAX_PATH] = { 0 };
SHGetSpecialFolderPath(NULL, szIniFile, CSIDL_WINDOWS, TRUE);
#ifdef LANXUM
_tcscat(szIniFile, _T("\\twain_32\\LANXUMSCAN\\tessdata"));
#else
_tcscat(szIniFile, _T("\\twain_32\\HuaGoScan\\tessdata"));
#endif //
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(type, param.is_backrotate180, param.resolution_dst, chRtn)));
delete[] chRtn;
}
}
void ImageMatQueue::EnqueueBmpBuffer(std::shared_ptr<std::vector<unsigned char>> bmpdata)
{
m_imagedata.Put(bmpdata);
}
void ImageMatQueue::PaniusCount()
{
atm_orgin_image_remains--;
Getimagenumber(false);
}
bool ImageMatQueue::empty()
{
return atm_orgin_image_remains <= 0 && m_imagedata.Size() == 0 && !is_scanning;
}
bool ImageMatQueue::queuesempty()
{
return atm_orgin_image_remains <= 0 && m_imagedata.Size() == 0;
}
static int index = 0;
void ImageMatQueue::proc()
{
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) {
ImreadModes rm;
if (scanParam.filter != 3 || scanParam.enhance_color || scanParam.hsvcorrect)
rm = IMREAD_COLOR;
else
rm = scanParam.pixtype == 2 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
try
{
//StopWatch sw;
cv::Mat mat = cv::imdecode(*buf, rm);
//double epl= sw.elapsed_ms();
//FileTools::write_log("1.txt", to_string(epl)+" img index"+to_string(++index));
buf.reset();
if (mat.empty()) {
writelog("decode image data error");
}
#ifdef G200
cv::resize(mat, mat, cv::Size(), fx,fy);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׶<EFBFBD>
mats.push_back(mat);
mat.release();
#else // G200
//resize(mat, mat, cv::Size(), 1.001, 1.0070);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׶<EFBFBD>
//cv::imwrite("D:\\org"+to_string(++index)+".jpg", mat);
Mat front = mat(Rect(0, 0, mat.cols / 2, mat.rows));
Mat back = mat(Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows));
if (scanParam.imageRotateDegree != 0.0&&scanParam.imageRotateDegree!=180.0) {
cv::flip(front, front, 0);
cv::flip(front, front, 1);
}
FileTools::write_log("scanParam.imageRotateDegree-" + to_string(scanParam.imageRotateDegree));
mats.push_back(back);
mats.push_back(front);
#endif
}
catch (const std::exception& e)
{
writelog(e.what());
}
}
buffs.clear();
DogEar_index++;
StopWatch sw;
sw.reset();
if (ischeck_dogear)
{
m_dogear->apply(mats[0], 0);
if (m_dogear->getResult())
{
DogEarDetection_callback(DogEar_index);
m_rawBuffs.Clear();
atm_orgin_image_remains = 0;
is_DogEar = true;
continue;
}
}
//FileTools::write_log("1.txt", " dogear time " + to_string(sw.elapsed_ms()));
if (scanParam.is_switchfrontback)
swap(mats[0], mats[1]);
for (int j = 0; j < m_iaList.size(); j++) {
m_iaList[j]->apply(mats, scanParam.is_duplex);
}
static int index = 0;
for (int i = 0; i < mats.size(); i++) {
if (!scanParam.is_duplex && i == 1) {
mats[i].release();
break;
}
if (!mats[i].empty()) {
IMat2Bmp idata;
if (scanParam.pixtype == 1 && scanParam.hsvcorrect)
if (mats[i].channels() == 3)
cvtColor(mats[i], mats[i], cv::COLOR_BGR2GRAY);
idata = (scanParam.pixtype == 0 || (((scanParam.automaticcolortype == 0)&&(scanParam.automaticcolor==true)) && (mats[i].channels() == 1))) ? (IMat2Bmp)Mat2BmpBw(mats[i], scanParam.resolution_dst) : Mat2Bmp(mats[i], scanParam.resolution_dst);
if (!scanParam.multi_output_red)
mats[i].release();
auto data = idata.getBmpDataBuffer();
//FILE* fd=fopen("D:\\0.bmp","w+");
//fwrite(data->data(), data->size(),1 , fd);
//fclose(fd);
EnqueueBmpBuffer(data);
data.reset();
}
else
{
writelog("enqueue image is empty " + std::to_string(index++));
}
}
if (scanParam.multi_output_red) {
for (int i = 0; i < mats.size(); i++) {
if (!mats[i].empty()) {
ImageMultiOutput m_mlt;
Mat ret = m_mlt.GetMultiFilterMat(mats[i], 2);
mats[i].release();
if (!ret.empty()) {
if (!scanParam.is_duplex && i == 1) {
ret.release();
break;
}
Mat2Bmp mb(ret, scanParam.resolution_dst);
auto data = mb.getBmpDataBuffer();
ret.release();
EnqueueBmpBuffer(data);
data.reset();
}
}
}
}
mats.clear();
PaniusCount();
}
}
}
GRawDecode::GRawDecode(std::shared_ptr<std::vector<char>> buff)
{
m_buffs.push_back(buff);
}