twain3.0/huagao/Device/ImageMatQueue.cpp

586 lines
18 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 "StdAfx.h"
#include "ImageMatQueue.h"
#include "PublicFunc.h"
#include "ImageProcess/ImageApplyHeaders.h"
#include "ImageMultiOutput.h"
#include "filetools.h"
#include <math.h>
#include "StopWatch.h"
//#include "JpegBuffer.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)
{
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();
}
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.10f && hratio < 3.0f && vratio >0.10f && vratio < 3.0f) {
this->fx = hratio;
this->fy = vratio;
}
else
{
FileTools::writelog(log_ERROR,"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,false,param.AutoCrop_threshold,param.noise,param.indent)));
/* m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoCrop(true, param.autodescrew, param.fillbackground, cv::Size(fixedSize.cx, fixedSize.cy), param.is_convex, false, param.AutoCrop_threshold, param.noise, param.indent)));
if(!(islongcustomcrop ? islongcustomcrop : param.is_autocrop))
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyResize(CImageApplyResize::ResizeType::DSIZE, cv::Size(fixedSize.cx, fixedSize.cy), 1.0, 1.0)));*/
}
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 + 4; }
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><EFBFBD>
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));
}
//<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 (scanParam.en_fold)
{
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyConcatenation(CImageApplyConcatenation::horizontal,cv::Scalar(255,255,255))));
}
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;
return m_imagepath.empty()&&(m_imagedata.Size()==0 )&& !is_scanning&&m_data.empty();
}
bool ImageMatQueue::queuesempty()
{
return atm_orgin_image_remains <= 0 && m_imagedata.Size() == 0;
}
static int index = 0;
void ImageMatQueue::proc()
{
//int dwnumber = std::thread::thread::hardware_concurrency();
//std::unique_ptr<ThreadPool> m_threadpool;
//m_threadpool.reset(new ThreadPool(dwnumber < 4 ? 1 : dwnumber / 2));
std::ios::sync_with_stdio(false);
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;
//}
//if (m_imagepath.empty())
//{
// this_thread::sleep_for(chrono::milliseconds(1));
// continue;
//}
if (m_data.empty())
{
this_thread::sleep_for(chrono::milliseconds(1));
continue;
}
if (m_data.size() > 0)
{
string path = FileTools::get_appdata_path() + "image" + to_string(index++) + ".tmp";
if (!access(path.c_str(), 0))
remove(path.c_str());
auto buff = m_data.front();
//if (!fw.get())
// fw.reset(new fstream());
//fw->open(path, std::ios::binary | std::ios::out);
//if (fw->is_open())
//{
// if ((*buff)[0] != -1 && (*buff)[1] != -40 && (*buff)[2] != -1 && (*buff)[3] != -32)
// {
// fw->write(buff->data() + 12, buff->size() - 12);
// FileTools::writelog(log_ERROR, "usb data error -image data");
// }
// else
// fw->write(buff->data(), buff->size());
// fw->flush();
// fw->close();
// m_imagepath.push(path);
// buff.reset(); m_data.pop();
// fw.reset();
//}
CFile frb;
if (frb.Open(CString(path.c_str()), CFile::modeWrite | CFile::modeCreate | CFile::typeBinary))
{
if ((*buff)[0] != -1 && (*buff)[1] != -40 && (*buff)[2] != -1 && (*buff)[3] != -32)
{
frb.Write(buff->data() + 12, buff->size() - 12);
FileTools::writelog(log_ERROR, "usb data error -image data");
}
else
frb.Write(buff->data(), buff->size());
frb.Flush();
frb.Close();
m_imagepath.push(path);
buff.reset(); m_data.pop();
}
}
std::string path = m_imagepath.front();
long lenght= FileTools::get_file_size(path.c_str());
std::shared_ptr<std::vector<char>> buf(new std::vector<char>);
buf->resize(lenght);
StopWatch sw;
if (!access(path.c_str(),0))
{
//if (!fr.get())
// fr.reset(new fstream());
//fr->open(path, std::ios::binary | std::ios::in);
//if (fr->is_open())
//{
// fr->read(buf->data(), lenght);
// fr->close();
// fr.reset();
// remove(path.c_str());
//}
CFile fwb;
if (fwb.Open(CString(path.c_str()), CFile::modeRead |CFile::typeBinary))
{
fwb.Read(buf->data(), lenght);
fwb.Close();
remove(path.c_str());
}
}
else
FileTools::writelog(log_ERROR, "open file error filename:" + path);
FileTools::writelog(log_INFO, " <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ͼƬ<CDBC><C6AC><EFBFBD>ݺ<EFBFBD>ʱ " + to_string(sw.elapsed_ms())+" data size "+to_string(lenght));
sw.reset();
#ifdef G200
auto& buffs = G200Decode(buf).getImageBuffs();
#else
auto& buffs = G400Decode(buf).getImageBuffs();
#endif // G200
//auto& buffs = m_rawBuffs.Take()->getImageBuffs();
if (!m_rawBuffs.IsShutDown() && !buffs.empty()) {
//m_threadpool->enqueue(&ImageMatQueue::imageproceing, this, buffs);
//try {
// imageproceing(buffs);
//}
//catch (std::exception& e)
//{
// FileTools::writelog(log_ERROR, " image proc error " + std::string(e.what()));
//}
imageproceing(buffs);
}
m_imagepath.pop();
}
//m_threadpool.reset();
}
void ImageMatQueue::imageproceing(std::vector<std::shared_ptr<std::vector<char>>>& buffs)
{
vector<cv::Mat> mats;
for (auto& buf : buffs) {
ImreadModes rmc;
//int rm;
if (scanParam.filter != 3 || scanParam.enhance_color || scanParam.hsvcorrect) {
rmc = IMREAD_COLOR;
//rm = 1;
}
else {
rmc = scanParam.pixtype == 2 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
//rm = scanParam.pixtype == 2 ? 1 : 6;
}
try
{
cv::Mat mat = cv::imdecode(*buf, rmc);
if (mat.empty()) {
FileTools::writelog(log_ERROR,"decode image data error");
}
buf.reset();
#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
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());
FileTools::writelog(log_ERROR, e.what());
}
}
buffs.clear();
if (mats[0].empty() || mats[1].empty())
{
mats.clear();
PaniusCount();
return;
}
//DogEar_index++; //<2F><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> 2021.3.18
//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;
// return;
// }
//}
//FileTools::write_log("1.txt", " dogear time " + to_string(sw.elapsed_ms()));
if (scanParam.is_switchfrontback)
swap(mats[0], mats[1]);
if (scanParam.en_fold != 0) {
cv::flip(mats[0], mats[0], 1);
cv::flip(mats[0], mats[0], 0);
}
StopWatch sw;
for (int j = 0; j < m_iaList.size(); j++) {
m_iaList[j]->apply(mats, scanParam.is_duplex);
}
FileTools::writelog(log_INFO, "ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ " + to_string(sw.elapsed_ms()));
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
{
FileTools::writelog(log_ERROR,"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();
}
G400Decode::G400Decode(std::shared_ptr<std::vector<char>> buff)
{
m_buffs.push_back(buff);
}