mirror of http://192.168.1.51:8099/lmh188/twain3.0
463 lines
14 KiB
C++
463 lines
14 KiB
C++
#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);
|
||
}
|
||
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);
|
||
} |