mirror of http://192.168.1.51:8099/lmh188/twain3.0
1.增加snowflake 随机生成文件名,避免出现重名情况缓存覆盖导致的丢图;
2.代码中增加UV模式,涉及UI 协议 配置类 UV图像合并算法; 3.重构ImageMatQueue 实现,去除冗余接口、类设计、简化代码; 4.为适应UV模式图像处理算法,增加自动裁切以及旋转接口; 5.增加UV json配置记忆功能; 6.去除IScanner接口中没用接口;
This commit is contained in:
parent
61f4917aee
commit
9c02a0c0f0
|
@ -3,7 +3,6 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
/huagao/.vs/huagaotwds/v15
|
/huagao/.vs/huagaotwds/v15
|
||||||
/3rdparty/nick
|
|
||||||
/huagao/debug/qmake
|
/huagao/debug/qmake
|
||||||
/huagao/debug
|
/huagao/debug
|
||||||
/huagao/Win32/Debug
|
/huagao/Win32/Debug
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <chrono>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
class snowflake_nonlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<int64_t Twepoch, typename Lock = snowflake_nonlock>
|
||||||
|
class snowflake
|
||||||
|
{
|
||||||
|
using lock_type = Lock;
|
||||||
|
static constexpr int64_t TWEPOCH = Twepoch;
|
||||||
|
static constexpr int64_t WORKER_ID_BITS = 5L;
|
||||||
|
static constexpr int64_t DATACENTER_ID_BITS = 5L;
|
||||||
|
static constexpr int64_t MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1;
|
||||||
|
static constexpr int64_t MAX_DATACENTER_ID = (1 << DATACENTER_ID_BITS) - 1;
|
||||||
|
static constexpr int64_t SEQUENCE_BITS = 12L;
|
||||||
|
static constexpr int64_t WORKER_ID_SHIFT = SEQUENCE_BITS;
|
||||||
|
static constexpr int64_t DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
|
||||||
|
static constexpr int64_t TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
|
||||||
|
static constexpr int64_t SEQUENCE_MASK = (1 << SEQUENCE_BITS) - 1;
|
||||||
|
|
||||||
|
using time_point = std::chrono::time_point<std::chrono::steady_clock>;
|
||||||
|
|
||||||
|
time_point start_time_point_ = std::chrono::steady_clock::now();
|
||||||
|
int64_t start_millsecond_ = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||||
|
|
||||||
|
int64_t last_timestamp_ = -1;
|
||||||
|
int64_t workerid_ = 0;
|
||||||
|
int64_t datacenterid_ = 0;
|
||||||
|
int64_t sequence_ = 0;
|
||||||
|
lock_type lock_;
|
||||||
|
public:
|
||||||
|
snowflake() = default;
|
||||||
|
|
||||||
|
snowflake(const snowflake&) = delete;
|
||||||
|
|
||||||
|
snowflake& operator=(const snowflake&) = delete;
|
||||||
|
|
||||||
|
void init(int64_t workerid, int64_t datacenterid)
|
||||||
|
{
|
||||||
|
if (workerid > MAX_WORKER_ID || workerid < 0) {
|
||||||
|
throw std::runtime_error("worker Id can't be greater than 31 or less than 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datacenterid > MAX_DATACENTER_ID || datacenterid < 0) {
|
||||||
|
throw std::runtime_error("datacenter Id can't be greater than 31 or less than 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
workerid_ = workerid;
|
||||||
|
datacenterid_ = datacenterid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t nextid()
|
||||||
|
{
|
||||||
|
std::lock_guard<lock_type> lock(lock_);
|
||||||
|
//std::chrono::steady_clock cannot decrease as physical time moves forward
|
||||||
|
auto timestamp = millsecond();
|
||||||
|
if (last_timestamp_ == timestamp)
|
||||||
|
{
|
||||||
|
sequence_ = (sequence_ + 1)&SEQUENCE_MASK;
|
||||||
|
if (sequence_ == 0)
|
||||||
|
{
|
||||||
|
timestamp = wait_next_millis(last_timestamp_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sequence_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_timestamp_ = timestamp;
|
||||||
|
|
||||||
|
return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT)
|
||||||
|
| (datacenterid_ << DATACENTER_ID_SHIFT)
|
||||||
|
| (workerid_ << WORKER_ID_SHIFT)
|
||||||
|
| sequence_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int64_t millsecond() const noexcept
|
||||||
|
{
|
||||||
|
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time_point_);
|
||||||
|
return start_millsecond_ + diff.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t wait_next_millis(int64_t last) const noexcept
|
||||||
|
{
|
||||||
|
auto timestamp = millsecond();
|
||||||
|
while (timestamp <= last)
|
||||||
|
{
|
||||||
|
timestamp = millsecond();
|
||||||
|
}
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
};
|
|
@ -138,6 +138,7 @@ void CBasicPage::DoDataExchange(CDataExchange* pDX)
|
||||||
DDX_Check(pDX, IDC_CKBSIZEDETECT, m_enableSizeCheck);
|
DDX_Check(pDX, IDC_CKBSIZEDETECT, m_enableSizeCheck);
|
||||||
DDX_Control(pDX, IDC_SLIDERDPI, m_Slider_Dpi);
|
DDX_Control(pDX, IDC_SLIDERDPI, m_Slider_Dpi);
|
||||||
DDX_Control(pDX, IDC_EDITDPI, m_Edit_Dpi);
|
DDX_Control(pDX, IDC_EDITDPI, m_Edit_Dpi);
|
||||||
|
DDX_Check(pDX, IDC_CKBENABLEUV, m_bUV);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CBasicPage::OnInitDialog()
|
BOOL CBasicPage::OnInitDialog()
|
||||||
|
@ -166,6 +167,9 @@ BOOL CBasicPage::OnInitDialog()
|
||||||
m_cmBoxColorMode->SetCurSel(0);
|
m_cmBoxColorMode->SetCurSel(0);
|
||||||
m_cmBoxDuplex->SetCurSel(0);
|
m_cmBoxDuplex->SetCurSel(0);
|
||||||
|
|
||||||
|
#ifndef UV
|
||||||
|
GetDlgItem(IDC_CKBENABLEUV)->ShowWindow(FALSE);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ protected:
|
||||||
|
|
||||||
std::function<void()> m_dataChange;
|
std::function<void()> m_dataChange;
|
||||||
public:
|
public:
|
||||||
|
BOOL m_bUV;
|
||||||
afx_msg void OnClickedBtndiscardsetting();
|
afx_msg void OnClickedBtndiscardsetting();
|
||||||
void SetScannerInfo(std::string hdVersion, std::string serialNum);
|
void SetScannerInfo(std::string hdVersion, std::string serialNum);
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -160,6 +160,9 @@ void CTwainUI::UpdateUI()
|
||||||
m_pageBasic->m_cmBoxSS->SetCurSel(getPaparSizeIndex(settings->papertype, settings->paperAlign)); //!< 纸张类型
|
m_pageBasic->m_cmBoxSS->SetCurSel(getPaparSizeIndex(settings->papertype, settings->paperAlign)); //!< 纸张类型
|
||||||
m_pageBasic->m_enableSizeCheck = settings->en_sizecheck==1?TRUE:FALSE;//!< 尺寸检测
|
m_pageBasic->m_enableSizeCheck = settings->en_sizecheck==1?TRUE:FALSE;//!< 尺寸检测
|
||||||
m_pageBasic->m_bswitchfrontback = settings->is_switchfrontback ? TRUE : FALSE; //!< 交换正反面
|
m_pageBasic->m_bswitchfrontback = settings->is_switchfrontback ? TRUE : FALSE; //!< 交换正反面
|
||||||
|
#ifdef UV
|
||||||
|
m_pageBasic->m_bUV = settings->hardwarecaps.en_uv == 1 ? TRUE : FALSE;
|
||||||
|
#endif
|
||||||
m_pageBasic->UpdateData(FALSE);
|
m_pageBasic->UpdateData(FALSE);
|
||||||
if(getCmbDuplexIndex()==2|| getCmbDuplexIndex()==3)
|
if(getCmbDuplexIndex()==2|| getCmbDuplexIndex()==3)
|
||||||
m_pageBasic->GetDlgItem(IDC_BTNDISCARDSETTING)->EnableWindow(true);
|
m_pageBasic->GetDlgItem(IDC_BTNDISCARDSETTING)->EnableWindow(true);
|
||||||
|
@ -403,6 +406,9 @@ void CTwainUI::UpDateScanParam(PCONFIGPARAMS configItem, bool updateDs)
|
||||||
configItem->EnDiscardBlank = configItem->Duplex == 2;//自动跳骨空白页通用
|
configItem->EnDiscardBlank = configItem->Duplex == 2;//自动跳骨空白页通用
|
||||||
configItem->EnDiscardBlankVince = configItem->Duplex == 3;//自动跳骨空白页发票
|
configItem->EnDiscardBlankVince = configItem->Duplex == 3;//自动跳骨空白页发票
|
||||||
configItem->EnFlod = configItem->Duplex == 4;
|
configItem->EnFlod = configItem->Duplex == 4;
|
||||||
|
#ifdef UV
|
||||||
|
configItem->EnUVModel = m_pageBasic->m_bUV;
|
||||||
|
#endif
|
||||||
//configItem->DBlank_AreaNum = m_pageBasic->AreaNum;//!< 分区数
|
//configItem->DBlank_AreaNum = m_pageBasic->AreaNum;//!< 分区数
|
||||||
//configItem->DBlank_DevnMax = m_pageBasic->DevnMax;//!< 跳过阈值
|
//configItem->DBlank_DevnMax = m_pageBasic->DevnMax;//!< 跳过阈值
|
||||||
|
|
||||||
|
@ -470,6 +476,9 @@ void CTwainUI::UpDateScanParam(PCONFIGPARAMS configItem, bool updateDs)
|
||||||
//settings->areanum = configItem->DBlank_AreaNum;
|
//settings->areanum = configItem->DBlank_AreaNum;
|
||||||
//settings->devnmax = configItem->DBlank_DevnMax;
|
//settings->devnmax = configItem->DBlank_DevnMax;
|
||||||
settings->discardblank_percent = m_pageBasic->discardblank_percent;
|
settings->discardblank_percent = m_pageBasic->discardblank_percent;
|
||||||
|
#ifdef UV
|
||||||
|
settings->hardwarecaps.en_uv = configItem->EnUVModel;
|
||||||
|
#endif
|
||||||
//填充黑框
|
//填充黑框
|
||||||
settings->fillbackground = configItem->EnFillBlack;
|
settings->fillbackground = configItem->EnFillBlack;
|
||||||
settings->autodescrew = configItem->EnAutoDescrew;
|
settings->autodescrew = configItem->EnAutoDescrew;
|
||||||
|
|
|
@ -10,7 +10,11 @@ G400ScanConfig::G400ScanConfig(GScanCap& gcap)
|
||||||
cfg.params.isColor = 1;
|
cfg.params.isColor = 1;
|
||||||
else
|
else
|
||||||
cfg.params.isColor = SupPixelTypes[gcap.pixtype];
|
cfg.params.isColor = SupPixelTypes[gcap.pixtype];
|
||||||
cfg.params.enableStable = 0;//gcap.hardwarecaps.en_stapledetect==0?0:1;
|
#ifdef UV
|
||||||
|
cfg.params.enableUV = gcap.hardwarecaps.en_uv;//gcap.hardwarecaps.en_stapledetect==0?0:1;
|
||||||
|
#else
|
||||||
|
cfg.params.enableUV = 0;
|
||||||
|
#endif
|
||||||
cfg.params.isCorrect = 1;//1 机器校正
|
cfg.params.isCorrect = 1;//1 机器校正
|
||||||
PaperStatus ps = { gcap.papertype,gcap.paperAlign };
|
PaperStatus ps = { gcap.papertype,gcap.paperAlign };
|
||||||
cfg.params.pageSize = SupPaperTyps[ps];
|
cfg.params.pageSize = SupPaperTyps[ps];
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
unsigned int isColor : 1;
|
unsigned int isColor : 1;
|
||||||
unsigned int dpi : 2;
|
unsigned int dpi : 2;
|
||||||
unsigned int doubleFeeded : 1;
|
unsigned int doubleFeeded : 1;
|
||||||
unsigned int enableStable : 1;
|
unsigned int enableUV : 1;
|
||||||
unsigned int enableLed : 1;
|
unsigned int enableLed : 1;
|
||||||
unsigned int sizedetect : 1;
|
unsigned int sizedetect : 1;
|
||||||
unsigned int reversed1 : 5;
|
unsigned int reversed1 : 5;
|
||||||
|
|
|
@ -126,7 +126,10 @@ public:
|
||||||
IScanner() {
|
IScanner() {
|
||||||
bFilterMsg = false; aquire_image_count = updata_image_count = updata_image_count = roller_num = lose_image_num = 0; is_AndroidOrLinux = false;
|
bFilterMsg = false; aquire_image_count = updata_image_count = updata_image_count = roller_num = lose_image_num = 0; is_AndroidOrLinux = false;
|
||||||
}
|
}
|
||||||
virtual ~IScanner() { bFilterMsg = true; }
|
virtual ~IScanner()
|
||||||
|
{
|
||||||
|
bFilterMsg = true;
|
||||||
|
}
|
||||||
void ResetMsgFiter() { bFilterMsg = true; }
|
void ResetMsgFiter() { bFilterMsg = true; }
|
||||||
int get_aquire_image_count() { return aquire_image_count; };
|
int get_aquire_image_count() { return aquire_image_count; };
|
||||||
int get_updata_image_count() { return updata_image_count; };
|
int get_updata_image_count() { return updata_image_count; };
|
||||||
|
@ -154,7 +157,6 @@ public:
|
||||||
virtual bool Get_IsImageQueueEmpty() = 0;
|
virtual bool Get_IsImageQueueEmpty() = 0;
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
virtual void clear_hwerror() = 0;
|
virtual void clear_hwerror() = 0;
|
||||||
virtual void setdecodepixtype(int twpixtype) = 0;
|
|
||||||
virtual UINT32 get_ErrorCode() = 0;
|
virtual UINT32 get_ErrorCode() = 0;
|
||||||
virtual void Set_ErrorCode(UINT32 value) = 0;
|
virtual void Set_ErrorCode(UINT32 value) = 0;
|
||||||
virtual int get_scanned_num() = 0;
|
virtual int get_scanned_num() = 0;
|
||||||
|
|
|
@ -111,10 +111,6 @@ void GScan200::clear_hwerror()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GScan200::setdecodepixtype(int twpixtype)
|
|
||||||
{
|
|
||||||
pixType = (twpixtype == 0) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 GScan200::get_ErrorCode()
|
UINT32 GScan200::get_ErrorCode()
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,6 @@ public:
|
||||||
virtual bool Get_IsImageQueueEmpty() override;
|
virtual bool Get_IsImageQueueEmpty() override;
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
virtual void clear_hwerror() override;
|
virtual void clear_hwerror() override;
|
||||||
virtual void setdecodepixtype(int twpixtype) override;
|
|
||||||
virtual UINT32 get_ErrorCode() override;
|
virtual UINT32 get_ErrorCode() override;
|
||||||
virtual void Set_ErrorCode(UINT32 value) override;
|
virtual void Set_ErrorCode(UINT32 value) override;
|
||||||
virtual int get_scanned_num() override;
|
virtual int get_scanned_num() override;
|
||||||
|
|
|
@ -149,7 +149,11 @@ GScanO200::GScanO200() :
|
||||||
is_orginimgcount(true)
|
is_orginimgcount(true)
|
||||||
{
|
{
|
||||||
m_pImages.reset(new ImageMatQueue());
|
m_pImages.reset(new ImageMatQueue());
|
||||||
m_pImages->Getimagenumber = std::bind(&GScanO200::Getimagenumber,this, std::placeholders::_1);
|
auto getimgnum = [&](bool isadd)
|
||||||
|
{
|
||||||
|
isadd ? image_num++ : image_num--;
|
||||||
|
};
|
||||||
|
m_pImages->SetGetimgnumcall(getimgnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
GScanO200::~GScanO200()
|
GScanO200::~GScanO200()
|
||||||
|
@ -159,27 +163,16 @@ GScanO200::~GScanO200()
|
||||||
m_threadUsb->join();
|
m_threadUsb->join();
|
||||||
m_threadUsb.reset();
|
m_threadUsb.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_usb.get())
|
if (m_usb.get())
|
||||||
m_usb.reset();
|
m_usb.reset();
|
||||||
|
|
||||||
}
|
m_pImages.reset();
|
||||||
|
|
||||||
|
|
||||||
void GScanO200::Getimagenumber(bool isadd)
|
|
||||||
{
|
|
||||||
if (isadd)
|
|
||||||
{
|
|
||||||
image_num++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
image_num--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GScanO200::DogEar_callback(std::function<void(int)> fun)
|
void GScanO200::DogEar_callback(std::function<void(int)> fun)
|
||||||
{
|
{
|
||||||
m_pImages->DogEarDetection_callback = fun;
|
m_pImages->SetDogEarCallback(fun);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GScanO200::open(int vid, int pid)
|
void GScanO200::open(int vid, int pid)
|
||||||
|
@ -483,13 +476,7 @@ void GScanO200::ResetScanner()
|
||||||
USBCB usbcb = { INIT_HARDWARE_SYS ,0,0 };
|
USBCB usbcb = { INIT_HARDWARE_SYS ,0,0 };
|
||||||
if (m_usb.get() && m_usb->is_connected())
|
if (m_usb.get() && m_usb->is_connected())
|
||||||
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
||||||
while (!m_pImages->m_imagepath.empty())
|
m_pImages->clear();
|
||||||
{
|
|
||||||
string path = m_pImages->m_imagepath.front();
|
|
||||||
if (isFileExist(path))
|
|
||||||
remove(path.c_str());
|
|
||||||
m_pImages->m_imagepath.pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GScanO200::Get_IsImageQueueEmpty()
|
bool GScanO200::Get_IsImageQueueEmpty()
|
||||||
|
@ -504,10 +491,6 @@ void GScanO200::reset()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GScanO200::setdecodepixtype(int twpixtype)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 GScanO200::get_ErrorCode()
|
UINT32 GScanO200::get_ErrorCode()
|
||||||
{
|
{
|
||||||
return Error_Code;
|
return Error_Code;
|
||||||
|
@ -662,20 +645,8 @@ void GScanO200::usbmain()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m_usb->set_timeout(200);
|
m_usb->set_timeout(200);
|
||||||
//if(!m_pImages->get_isDogEar())
|
if(!m_pImages->get_isDogEar())
|
||||||
// m_pImages->pushMat(std::shared_ptr<IDecode>(new G200Decode(imgData)));
|
m_pImages->pushMat(std::shared_ptr<IDecode>(new G200Decode(imgData)));
|
||||||
//string path = cv::tempfile();
|
|
||||||
m_pImages->m_data.push(imgData);
|
|
||||||
//string path = FileTools::get_appdata_path() + "image"+to_string(get_aquire_image_count())+".tmp";
|
|
||||||
//if (!access(path.c_str(), 0))
|
|
||||||
// remove(path.c_str());
|
|
||||||
//FILE* fd = fopen(path.c_str(), "wb+");
|
|
||||||
//if (fd)
|
|
||||||
//{
|
|
||||||
// fwrite(imgData->data(), imgData->size(), 1, fd);
|
|
||||||
// fclose(fd);
|
|
||||||
// m_pImages->m_imagepath.push(path);
|
|
||||||
//}
|
|
||||||
Pop_Image();
|
Pop_Image();
|
||||||
set_aquire_image_count(get_aquire_image_count() + 1,get_updata_image_count());
|
set_aquire_image_count(get_aquire_image_count() + 1,get_updata_image_count());
|
||||||
FileTools::writelog(log_INFO, "´ÓɨÃèÒǽÓÊÕ"+to_string(get_aquire_image_count())+"·ÝÎļþ¡£");
|
FileTools::writelog(log_INFO, "´ÓɨÃèÒǽÓÊÕ"+to_string(get_aquire_image_count())+"·ÝÎļþ¡£");
|
||||||
|
|
|
@ -27,7 +27,6 @@ public:
|
||||||
virtual void ResetScanner() override;
|
virtual void ResetScanner() override;
|
||||||
virtual bool Get_IsImageQueueEmpty() override;
|
virtual bool Get_IsImageQueueEmpty() override;
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
virtual void setdecodepixtype(int twpixtype) override;
|
|
||||||
virtual UINT32 get_ErrorCode() override;
|
virtual UINT32 get_ErrorCode() override;
|
||||||
virtual void Set_ErrorCode(UINT32 value) override;
|
virtual void Set_ErrorCode(UINT32 value) override;
|
||||||
virtual int get_scanned_num() override;
|
virtual int get_scanned_num() override;
|
||||||
|
|
|
@ -151,7 +151,11 @@ GScanO400::GScanO400() :
|
||||||
m_bread_fixed_ratio_fromDSP(false)
|
m_bread_fixed_ratio_fromDSP(false)
|
||||||
{
|
{
|
||||||
m_pImages.reset(new ImageMatQueue());
|
m_pImages.reset(new ImageMatQueue());
|
||||||
m_pImages->Getimagenumber = std::bind(&GScanO400::Getimagenumber,this, std::placeholders::_1);
|
auto getimgnum = [&](bool isadd)
|
||||||
|
{
|
||||||
|
isadd ? image_num++ : image_num--;
|
||||||
|
};
|
||||||
|
m_pImages->SetGetimgnumcall(getimgnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
GScanO400::~GScanO400()
|
GScanO400::~GScanO400()
|
||||||
|
@ -181,7 +185,7 @@ void GScanO400::Getimagenumber(bool isadd)
|
||||||
|
|
||||||
void GScanO400::DogEar_callback(std::function<void(int)> fun)
|
void GScanO400::DogEar_callback(std::function<void(int)> fun)
|
||||||
{
|
{
|
||||||
m_pImages->DogEarDetection_callback = fun;
|
m_pImages->SetGetimgnumcall(fun);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GScanO400::open(int vid, int pid)
|
void GScanO400::open(int vid, int pid)
|
||||||
|
@ -514,18 +518,8 @@ void GScanO400::reset()
|
||||||
{
|
{
|
||||||
while (!m_pImages->empty())
|
while (!m_pImages->empty())
|
||||||
m_pImages->clear();
|
m_pImages->clear();
|
||||||
while (!m_pImages->m_imagepath.empty())
|
|
||||||
{
|
|
||||||
string path = m_pImages->m_imagepath.front();
|
|
||||||
if (isFileExist(path))
|
|
||||||
remove(path.c_str());
|
|
||||||
m_pImages->m_imagepath.pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GScanO400::setdecodepixtype(int twpixtype)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 GScanO400::get_ErrorCode()
|
UINT32 GScanO400::get_ErrorCode()
|
||||||
{
|
{
|
||||||
|
@ -682,22 +676,9 @@ void GScanO400::usbmain()
|
||||||
{
|
{
|
||||||
FileTools::writelog(log_ERROR," get image data size error totalnum " + to_string(totalNum) + " imgdata size " + to_string(imgData->size()));
|
FileTools::writelog(log_ERROR," get image data size error totalnum " + to_string(totalNum) + " imgdata size " + to_string(imgData->size()));
|
||||||
}
|
}
|
||||||
//if(!m_pImages->get_isDogEar())
|
if(!m_pImages->get_isDogEar())
|
||||||
//m_pImages->pushMat(std::shared_ptr<IDecode>(new G400Decode(imgData)));
|
m_pImages->pushMat(std::shared_ptr<IDecode>(new G400Decode(imgData)));
|
||||||
m_pImages->m_data.push(imgData);
|
|
||||||
//string path = FileTools::get_appdata_path() + "image"+to_string(get_aquire_image_count())+".tmp";
|
|
||||||
//if (!access(path.c_str(), 0))
|
|
||||||
// remove(path.c_str());
|
|
||||||
//FILE* fd = fopen(path.c_str(), "wb+");
|
|
||||||
//if (fd)
|
|
||||||
//{
|
|
||||||
// if ((*imgData)[0] != -1 && (*imgData)[1] != -40 && (*imgData)[2] != -1 && (*imgData)[3] != -32)
|
|
||||||
// fwrite(imgData->data() + 12, imgData->size() - 12, 1, fd);
|
|
||||||
// else
|
|
||||||
// fwrite(imgData->data(), imgData->size(), 1, fd);
|
|
||||||
// fclose(fd);
|
|
||||||
// m_pImages->m_imagepath.push(path);
|
|
||||||
//}
|
|
||||||
set_aquire_image_count(get_aquire_image_count() + 1,get_updata_image_count());
|
set_aquire_image_count(get_aquire_image_count() + 1,get_updata_image_count());
|
||||||
if(!is_AndroidOrLinux)
|
if(!is_AndroidOrLinux)
|
||||||
Pop_Image();
|
Pop_Image();
|
||||||
|
|
|
@ -27,7 +27,6 @@ public:
|
||||||
virtual void ResetScanner() override;
|
virtual void ResetScanner() override;
|
||||||
virtual bool Get_IsImageQueueEmpty() override;
|
virtual bool Get_IsImageQueueEmpty() override;
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
virtual void setdecodepixtype(int twpixtype) override;
|
|
||||||
virtual UINT32 get_ErrorCode() override;
|
virtual UINT32 get_ErrorCode() override;
|
||||||
virtual void Set_ErrorCode(UINT32 value) override;
|
virtual void Set_ErrorCode(UINT32 value) override;
|
||||||
virtual int get_scanned_num() override;
|
virtual int get_scanned_num() override;
|
||||||
|
|
|
@ -148,10 +148,6 @@ void GScanVirtual::reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GScanVirtual::setdecodepixtype(int twpixtype)
|
|
||||||
{
|
|
||||||
pixType = twpixtype;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 GScanVirtual::get_ErrorCode()
|
UINT32 GScanVirtual::get_ErrorCode()
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,6 @@ public:
|
||||||
virtual void ResetScanner() override;
|
virtual void ResetScanner() override;
|
||||||
virtual bool Get_IsImageQueueEmpty() override;
|
virtual bool Get_IsImageQueueEmpty() override;
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
virtual void setdecodepixtype(int twpixtype) override;
|
|
||||||
virtual UINT32 get_ErrorCode() override;
|
virtual UINT32 get_ErrorCode() override;
|
||||||
virtual void Set_ErrorCode(UINT32 value) override;
|
virtual void Set_ErrorCode(UINT32 value) override;
|
||||||
virtual int get_scanned_num() override;
|
virtual int get_scanned_num() override;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "filetools.h"
|
#include "filetools.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "StopWatch.h"
|
#include "StopWatch.h"
|
||||||
//#include "JpegBuffer.h"
|
|
||||||
|
|
||||||
using namespace cv;
|
using namespace cv;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -14,34 +13,6 @@ using namespace std;
|
||||||
#define DECODE_COLOR_BGR 1
|
#define DECODE_COLOR_BGR 1
|
||||||
#define DECODE_GRAY 6
|
#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)
|
ImageMatQueue::ImageMatQueue(void)
|
||||||
: bRun(false)
|
: bRun(false)
|
||||||
, is_scanning(false)
|
, is_scanning(false)
|
||||||
|
@ -49,15 +20,46 @@ ImageMatQueue::ImageMatQueue(void)
|
||||||
,fy(1.007)
|
,fy(1.007)
|
||||||
,DogEar_index(0)
|
,DogEar_index(0)
|
||||||
,is_DogEar(false)
|
,is_DogEar(false)
|
||||||
|
,benablecache(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
atm_orgin_image_remains = 0;
|
atm_orgin_image_remains = 0;
|
||||||
m_dogear.reset(new CImageApplyDogEarDetection(40,1.0,200));
|
m_dogear.reset(new CImageApplyDogEarDetection(40,1.0,200));
|
||||||
|
m_snowflake.init(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageMatQueue::~ImageMatQueue(void)
|
||||||
|
{
|
||||||
|
m_rawBuffs.Clear();
|
||||||
|
m_rawBuffs.ShutDown();
|
||||||
|
clear_cachefiles();
|
||||||
|
m_imgCacheinfo.ShutDown();
|
||||||
|
m_imagedata.Clear();
|
||||||
|
m_imagedata.ShutDown();
|
||||||
|
|
||||||
|
|
||||||
|
if (m_threadProc.get()) {
|
||||||
|
bRun = false;
|
||||||
|
m_threadProc->join();
|
||||||
|
m_threadProc.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_threadcache.get())
|
||||||
|
{
|
||||||
|
benablecache = false;
|
||||||
|
if (m_threadcache->joinable())
|
||||||
|
{
|
||||||
|
m_threadcache->join();
|
||||||
|
m_threadcache.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageMatQueue::run()
|
void ImageMatQueue::run()
|
||||||
{
|
{
|
||||||
if (!m_threadProc) {
|
init_cachethread();
|
||||||
|
|
||||||
|
if (!m_threadProc.get()) {
|
||||||
bRun = true;
|
bRun = true;
|
||||||
m_threadProc.reset(new thread(&ImageMatQueue::proc, this));
|
m_threadProc.reset(new thread(&ImageMatQueue::proc, this));
|
||||||
}
|
}
|
||||||
|
@ -91,24 +93,22 @@ void ImageMatQueue::updatefixratio(float& hratio, float& vratio)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageMatQueue::~ImageMatQueue(void)
|
void ImageMatQueue::SetGetimgnumcall(std::function<void(bool)> getimgnumcall)
|
||||||
{
|
{
|
||||||
m_rawBuffs.Clear();
|
m_Getimagenumber = getimgnumcall;
|
||||||
m_imagedata.Clear();
|
|
||||||
m_rawBuffs.ShutDown();
|
|
||||||
m_imagedata.ShutDown();
|
|
||||||
if (m_threadProc) {
|
|
||||||
bRun = false;
|
|
||||||
m_threadProc->join();
|
|
||||||
m_threadProc.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageMatQueue::SetDogEarCallback(std::function<void(int)> dogearcall)
|
||||||
|
{
|
||||||
|
m_DogEarDetection_callback = dogearcall;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int paperIndex = 0;
|
static int paperIndex = 0;
|
||||||
void ImageMatQueue::pushMat(std::shared_ptr<IDecode> data)
|
void ImageMatQueue::pushMat(std::shared_ptr<IDecode> data)
|
||||||
{
|
{
|
||||||
Getimagenumber(true);
|
if(m_Getimagenumber)
|
||||||
|
m_Getimagenumber(true);
|
||||||
m_rawBuffs.Put(data);
|
m_rawBuffs.Put(data);
|
||||||
atm_orgin_image_remains++;
|
atm_orgin_image_remains++;
|
||||||
//string paperindexinfo = "Get the index of "+to_string(++paperIndex)+" Paper";
|
//string paperindexinfo = "Get the index of "+to_string(++paperIndex)+" Paper";
|
||||||
|
@ -128,6 +128,7 @@ bool ImageMatQueue::valid()
|
||||||
void ImageMatQueue::clear()
|
void ImageMatQueue::clear()
|
||||||
{
|
{
|
||||||
m_rawBuffs.Clear();
|
m_rawBuffs.Clear();
|
||||||
|
clear_cachefiles();
|
||||||
m_imagedata.Clear();
|
m_imagedata.Clear();
|
||||||
atm_orgin_image_remains = 0;
|
atm_orgin_image_remains = 0;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +163,7 @@ void ImageMatQueue::setparam(const GScanCap& param)
|
||||||
fixedSize = papersize.GetPaperSize(param.papertype, 200.0f, param.paperAlign);
|
fixedSize = papersize.GetPaperSize(param.papertype, 200.0f, param.paperAlign);
|
||||||
#endif
|
#endif
|
||||||
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoCrop(islongcustomcrop ? islongcustomcrop : param.is_autocrop,
|
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)));
|
param.autodescrew, param.fillbackground, cv::Size(fixedSize.cx, fixedSize.cy), param.is_convex,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)));
|
/* 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))
|
if(!(islongcustomcrop ? islongcustomcrop : param.is_autocrop))
|
||||||
|
@ -312,17 +313,94 @@ void ImageMatQueue::setparam(const GScanCap& param)
|
||||||
void ImageMatQueue::EnqueueBmpBuffer(std::shared_ptr<std::vector<unsigned char>> bmpdata)
|
void ImageMatQueue::EnqueueBmpBuffer(std::shared_ptr<std::vector<unsigned char>> bmpdata)
|
||||||
{
|
{
|
||||||
m_imagedata.Put(bmpdata);
|
m_imagedata.Put(bmpdata);
|
||||||
|
int aa = 0;
|
||||||
}
|
}
|
||||||
void ImageMatQueue::PaniusCount()
|
void ImageMatQueue::PaniusCount(int count)
|
||||||
{
|
{
|
||||||
atm_orgin_image_remains--;
|
atm_orgin_image_remains-=count;
|
||||||
Getimagenumber(false);
|
if(m_Getimagenumber)
|
||||||
|
m_Getimagenumber(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageMatQueue::init_cachethread()
|
||||||
|
{
|
||||||
|
if(!m_threadcache.get())
|
||||||
|
{
|
||||||
|
benablecache = true;
|
||||||
|
m_threadcache.reset(new thread(&ImageMatQueue::cache_run, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int index = 0;
|
||||||
|
void ImageMatQueue::cache_run()
|
||||||
|
{
|
||||||
|
StopWatch sw;
|
||||||
|
std::ios::sync_with_stdio(false);
|
||||||
|
while(benablecache)
|
||||||
|
{
|
||||||
|
if (m_rawBuffs.Size() == 0)
|
||||||
|
{
|
||||||
|
this_thread::sleep_for(chrono::milliseconds(2));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_rawBuffs.Size() > 0)
|
||||||
|
{
|
||||||
|
CacheInfo info;
|
||||||
|
auto buffs = m_rawBuffs.Take()->getImageBuffs();
|
||||||
|
buffs.size() == 2 ? info.scannerType = ScannerSerial::G200Serial : info.scannerType = ScannerSerial::G400Serial;
|
||||||
|
|
||||||
|
for (auto& buf : buffs)
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
string path = FileTools::get_appdata_path() + to_string(m_snowflake.nextid()) + ".jpg";
|
||||||
|
|
||||||
|
if (!access(path.c_str(), 0))
|
||||||
|
{
|
||||||
|
remove(path.c_str());
|
||||||
|
FileTools::writelog(log_ERROR, "exist file "+ path+" maybe lost previous session scanned image");
|
||||||
|
}
|
||||||
|
|
||||||
|
CFile frb;
|
||||||
|
if (frb.Open(CString(path.c_str()), CFile::modeWrite | CFile::modeCreate | CFile::typeBinary))
|
||||||
|
{
|
||||||
|
if (*(buf->data()) != -1 && *(buf->data() + 1) != -40 && *(buf->data() + 2) != -1 && *(buf->data() + 3) != -32)
|
||||||
|
{
|
||||||
|
frb.Write(buf->data() + 12, buf->size() - 12);
|
||||||
|
FileTools::writelog(log_ERROR, "usb data error -image data");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
frb.Write(buf->data(), buf->size());
|
||||||
|
frb.Flush();
|
||||||
|
frb.Close();
|
||||||
|
info.path = path;
|
||||||
|
m_imgCacheinfo.Put(info);
|
||||||
|
buf->clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileTools::writelog(log_ERROR, "error while openning cache file :" + path);
|
||||||
|
}
|
||||||
|
FileTools::writelog(log_INFO, " 磁盘写入图片数据耗时 " + to_string(sw.elapsed_ms()) + " buffer size = " + to_string(buf->size()));
|
||||||
|
sw.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageMatQueue::clear_cachefiles()
|
||||||
|
{
|
||||||
|
while (m_imgCacheinfo.Size() > 0)
|
||||||
|
{
|
||||||
|
auto tpath = m_imgCacheinfo.Take();
|
||||||
|
if (isFileExist(tpath.path))
|
||||||
|
remove(tpath.path.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImageMatQueue::empty()
|
bool ImageMatQueue::empty()
|
||||||
{
|
{
|
||||||
//return atm_orgin_image_remains <= 0 && m_imagedata.Size() == 0 && !is_scanning;
|
return m_imgCacheinfo.Size()==0&&(m_imagedata.Size()==0 )&&(m_rawBuffs.Size()==0)&& !is_scanning&& atm_orgin_image_remains==0;
|
||||||
return m_imagepath.empty()&&(m_imagedata.Size()==0 )&& !is_scanning&&m_data.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImageMatQueue::queuesempty()
|
bool ImageMatQueue::queuesempty()
|
||||||
|
@ -330,261 +408,226 @@ bool ImageMatQueue::queuesempty()
|
||||||
return atm_orgin_image_remains <= 0 && m_imagedata.Size() == 0;
|
return atm_orgin_image_remains <= 0 && m_imagedata.Size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int index = 0;
|
|
||||||
void ImageMatQueue::proc()
|
void ImageMatQueue::proc()
|
||||||
{
|
{
|
||||||
//int dwnumber = std::thread::thread::hardware_concurrency();
|
StopWatch sw;
|
||||||
//std::unique_ptr<ThreadPool> m_threadpool;
|
while (bRun)
|
||||||
//m_threadpool.reset(new ThreadPool(dwnumber < 4 ? 1 : dwnumber / 2));
|
{
|
||||||
std::ios::sync_with_stdio(false);
|
string msg;
|
||||||
while (bRun) {
|
auto info = m_imgCacheinfo.Take();
|
||||||
while (m_imagedata.Size() > 0) {
|
if(info.path.length()==0 || !isFileExist(info.path))
|
||||||
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));
|
msg = "error while checking file :" + info.path + " ,file lost";
|
||||||
|
FileTools::writelog(log_ERROR, msg);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_data.size() > 0)
|
ImreadModes rmc;
|
||||||
{
|
if (scanParam.filter != 3 || scanParam.enhance_color || scanParam.hsvcorrect)
|
||||||
string path = FileTools::get_appdata_path() + "image" + to_string(index++) + ".tmp";
|
rmc = IMREAD_COLOR;
|
||||||
if (!access(path.c_str(), 0))
|
else
|
||||||
remove(path.c_str());
|
rmc = scanParam.pixtype == 2 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
|
||||||
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;
|
std::vector<cv::Mat> mats;
|
||||||
if (frb.Open(CString(path.c_str()), CFile::modeWrite | CFile::modeCreate | CFile::typeBinary))
|
std::vector<Mat> uvmats;
|
||||||
|
if(info.scannerType==ScannerSerial::G200Serial)
|
||||||
|
{
|
||||||
|
auto back= m_imgCacheinfo.Take();
|
||||||
|
if(!isFileExist(back.path))
|
||||||
{
|
{
|
||||||
if ((*buff)[0] != -1 && (*buff)[1] != -40 && (*buff)[2] != -1 && (*buff)[3] != -32)
|
msg = "error while reading g200 back image " + back.path + " ,file not exist";
|
||||||
{
|
FileTools::writelog(log_ERROR,msg);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
sw.reset();
|
||||||
|
auto imgfront= imread(info.path, rmc);
|
||||||
std::string path = m_imagepath.front();
|
msg = "reading image front time elapsed_ms:" + std::to_string(sw.elapsed_ms());
|
||||||
long lenght= FileTools::get_file_size(path.c_str());
|
FileTools::writelog(log_ERROR, msg);
|
||||||
std::shared_ptr<std::vector<char>> buf(new std::vector<char>);
|
sw.reset();
|
||||||
buf->resize(lenght);
|
auto imgback = imread(back.path, rmc);
|
||||||
StopWatch sw;
|
msg = "reading image back time elapsed_ms:" + std::to_string(sw.elapsed_ms());
|
||||||
if (!access(path.c_str(),0))
|
FileTools::writelog(log_ERROR, msg);
|
||||||
{
|
sw.reset();
|
||||||
//if (!fr.get())
|
if(!imgfront.empty()&&!imgback.empty())
|
||||||
// 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);
|
mats.push_back(scanParam.is_switchfrontback? imgback:imgfront);
|
||||||
fwb.Close();
|
mats.push_back(scanParam.is_switchfrontback? imgfront:imgback);
|
||||||
remove(path.c_str());
|
remove(info.path.c_str());
|
||||||
|
remove(back.path.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FileTools::writelog(log_ERROR, "error while opening filename:" + path);
|
msg = "get empty mat! empty ";
|
||||||
|
msg += (imgfront.empty() ? " front image" : " back image");
|
||||||
|
FileTools::writelog(log_ERROR, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mats.size(); i++)
|
||||||
|
{
|
||||||
|
if(!mats[i].empty())
|
||||||
|
cv::resize(mats[i], mats[i], cv::Size(), fx, fy);//用于修正与佳能机器幅面大小不匹配问题 此系数请勿轻易动
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scanParam.en_fold != 0) {
|
||||||
|
cv::flip(mats[0], mats[0], 1);
|
||||||
|
cv::flip(mats[0], mats[0], 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
FileTools::writelog(log_ERROR, "open file error filename:" + path);
|
|
||||||
FileTools::writelog(log_INFO, " 获取磁盘图片数据耗时 " + 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);
|
auto mat= imread(info.path, rmc);
|
||||||
if (mat.empty()) {
|
if(!mat.empty())
|
||||||
FileTools::writelog(log_ERROR,"decode image data error");
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
buf.reset();
|
else
|
||||||
#ifdef G200
|
{
|
||||||
cv::resize(mat, mat, cv::Size(), fx, fy);//用于修正与佳能机器幅面大小不匹配问题 此系数请勿轻易动
|
msg = "g400 get empty mat! empty ";
|
||||||
mats.push_back(mat);
|
FileTools::writelog(log_ERROR, msg);
|
||||||
mat.release();
|
}
|
||||||
#else // G200
|
#ifdef UV
|
||||||
Mat front = mat(Rect(0, 0, mat.cols / 2, mat.rows));
|
if(scanParam.hardwarecaps.en_uv)//EN UV
|
||||||
Mat back = mat(Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows));
|
{
|
||||||
if (scanParam.imageRotateDegree != 0.0 && scanParam.imageRotateDegree != 180.0) {
|
auto uvinfo = m_imgCacheinfo.Take();
|
||||||
cv::flip(front, front, 0);
|
auto matuv = imread(uvinfo.path, IMREAD_COLOR);
|
||||||
cv::flip(front, front, 1);
|
if(!matuv.empty())
|
||||||
|
{
|
||||||
|
Mat front = mat(Rect(0, 0, mat.cols / 2, mat.rows));
|
||||||
|
Mat back = mat(Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows));
|
||||||
|
uvmats.push_back(scanParam.is_switchfrontback ? back : front);
|
||||||
|
uvmats.push_back(scanParam.is_switchfrontback ? front : back);
|
||||||
|
front.release();
|
||||||
|
back.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mats.push_back(back);
|
|
||||||
mats.push_back(front);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}//g400 serials
|
||||||
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++; //暂时屏蔽 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, "图像处理耗时 " + 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();
|
std::vector<cv::RotatedRect> rects;
|
||||||
//FILE* fd=fopen("D:\\0.bmp","w+");
|
std::vector<int> angleResults;
|
||||||
//fwrite(data->data(), data->size(),1 , fd);
|
bool isDesaskew = false;
|
||||||
//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 j = 0; j < m_iaList.size(); j++) {
|
||||||
|
m_iaList[j]->apply(mats, scanParam.is_duplex);
|
||||||
|
CImageApply* ptr = m_iaList[j].get();
|
||||||
|
if (typeid(*ptr) == typeid(CImageApplyAutoCrop))
|
||||||
|
{
|
||||||
|
rects = dynamic_cast<CImageApplyAutoCrop*>(ptr)->rotatedROIs();
|
||||||
|
isDesaskew = dynamic_cast<CImageApplyAutoCrop*>(ptr)->isDesaskew();
|
||||||
|
}
|
||||||
|
else if (typeid(*ptr) == typeid(CImageApplyRotation))
|
||||||
|
angleResults = dynamic_cast<CImageApplyRotation*>(ptr)->angleResults();
|
||||||
|
}
|
||||||
|
#ifdef UV
|
||||||
|
if (!uvmats.empty())
|
||||||
|
{
|
||||||
|
//拼接原图和UV图
|
||||||
|
for (int j = 0; j < mats.size(); j++)
|
||||||
|
{
|
||||||
|
if (!scanParam.is_duplex && j == 1) {
|
||||||
|
mats[j].release();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cv::Mat mergeOrgin_UV = ImageApplyUV::Apply(mats[j], uvmats[j], rects[j], isDesaskew, angleResults.size() > 0 ? angleResults[j] : 0);
|
||||||
|
if (!mergeOrgin_UV.empty())
|
||||||
|
mats[j] = mergeOrgin_UV;
|
||||||
|
}
|
||||||
|
uvmats.clear();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FileTools::writelog(log_INFO, "图像处理耗时 " + to_string(sw.elapsed_ms()));
|
||||||
for (int i = 0; i < mats.size(); i++) {
|
for (int i = 0; i < mats.size(); i++) {
|
||||||
if (!mats[i].empty()) {
|
if (!scanParam.is_duplex && i == 1) {
|
||||||
ImageMultiOutput m_mlt;
|
|
||||||
Mat ret = m_mlt.GetMultiFilterMat(mats[i], 2);
|
|
||||||
mats[i].release();
|
mats[i].release();
|
||||||
if (!ret.empty()) {
|
break;
|
||||||
if (!scanParam.is_duplex && i == 1) {
|
}
|
||||||
|
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();
|
||||||
|
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();
|
ret.release();
|
||||||
break;
|
EnqueueBmpBuffer(data);
|
||||||
|
data.reset();
|
||||||
}
|
}
|
||||||
Mat2Bmp mb(ret, scanParam.resolution_dst);
|
|
||||||
auto data = mb.getBmpDataBuffer();
|
|
||||||
ret.release();
|
|
||||||
EnqueueBmpBuffer(data);
|
|
||||||
data.reset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mats.clear();
|
||||||
|
#ifdef UV
|
||||||
|
PaniusCount(scanParam.hardwarecaps.en_uv ? 2 : 1);
|
||||||
|
#else
|
||||||
|
PaniusCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
mats.clear();
|
|
||||||
PaniusCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
G400Decode::G400Decode(std::shared_ptr<std::vector<char>> buff)
|
G400Decode::G400Decode(std::shared_ptr<std::vector<char>> buff)
|
||||||
{
|
{
|
||||||
m_buffs.push_back(buff);
|
m_buffs.push_back(buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <opencv2\opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
#include "ImageProcess/ImageApplyHeaders.h"
|
#include "ImageProcess/ImageApplyHeaders.h"
|
||||||
#include "PublicFunc.h"
|
#include "PublicFunc.h"
|
||||||
#include "BlockingQueue.h"
|
#include "BlockingQueue.h"
|
||||||
|
@ -9,6 +9,9 @@
|
||||||
//#include "threadpool.hpp"
|
//#include "threadpool.hpp"
|
||||||
#include "PaperSize.h"
|
#include "PaperSize.h"
|
||||||
#include "filetools.h"
|
#include "filetools.h"
|
||||||
|
//创建唯一 uuid
|
||||||
|
#include "snowflake.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
class IMat2Bmp {
|
class IMat2Bmp {
|
||||||
public:
|
public:
|
||||||
|
@ -145,18 +148,38 @@ protected:
|
||||||
class G200Decode : public IDecode{
|
class G200Decode : public IDecode{
|
||||||
public:
|
public:
|
||||||
G200Decode(std::shared_ptr<std::vector<char>> buff);
|
G200Decode(std::shared_ptr<std::vector<char>> buff);
|
||||||
|
virtual ~G200Decode()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class G400Decode : public IDecode {
|
class G400Decode : public IDecode {
|
||||||
public:
|
public:
|
||||||
G400Decode(std::shared_ptr<std::vector<char>> buff);
|
G400Decode(std::shared_ptr<std::vector<char>> buff);
|
||||||
|
virtual ~G400Decode()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ScannerSerial
|
||||||
|
{
|
||||||
|
G200Serial,
|
||||||
|
G400Serial
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CacheInfo
|
||||||
|
{
|
||||||
|
std::string path;
|
||||||
|
ScannerSerial scannerType;
|
||||||
|
};
|
||||||
|
using snowflake_t = snowflake<1534832906275L, std::mutex>;
|
||||||
class ImageMatQueue
|
class ImageMatQueue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageMatQueue(void);
|
ImageMatQueue(void);
|
||||||
virtual ~ImageMatQueue(void);
|
~ImageMatQueue(void);
|
||||||
|
|
||||||
void pushMat(std::shared_ptr<IDecode> buf);
|
void pushMat(std::shared_ptr<IDecode> buf);
|
||||||
std::shared_ptr<std::vector<unsigned char>> popBmpdata();
|
std::shared_ptr<std::vector<unsigned char>> popBmpdata();
|
||||||
|
@ -172,29 +195,36 @@ public:
|
||||||
int orginimgcount();
|
int orginimgcount();
|
||||||
void setscanflags(const bool flags) { is_scanning = flags; }
|
void setscanflags(const bool flags) { is_scanning = flags; }
|
||||||
void updatefixratio(float& hratio, float& vratio);
|
void updatefixratio(float& hratio, float& vratio);
|
||||||
std::function<void(int)> DogEarDetection_callback;
|
void SetGetimgnumcall(std::function<void(bool)> getimgnumcall);
|
||||||
std::function<void(bool)> Getimagenumber;
|
void SetDogEarCallback(std::function<void(int)> dogearcall);
|
||||||
std::queue<std::string> m_imagepath;
|
|
||||||
std::queue<std::shared_ptr<std::vector<char>>> m_data;
|
|
||||||
private:
|
private:
|
||||||
void proc();
|
void proc();
|
||||||
void imageproceing(std::vector<std::shared_ptr<std::vector<char>>>& buffs);
|
|
||||||
void EnqueueBmpBuffer(std::shared_ptr<std::vector<unsigned char>>);
|
void EnqueueBmpBuffer(std::shared_ptr<std::vector<unsigned char>>);
|
||||||
void PaniusCount();
|
void PaniusCount(int count=1);
|
||||||
BlockingQueue<std::shared_ptr<std::vector<unsigned char>>>m_imagedata;
|
void init_cachethread();
|
||||||
std::unique_ptr<thread> m_threadProc;
|
void cache_run();
|
||||||
|
//清除缓存文件
|
||||||
|
void clear_cachefiles();
|
||||||
|
|
||||||
|
BlockingQueue<std::shared_ptr<std::vector<unsigned char>>> m_imagedata;//已处理图像队列
|
||||||
|
BlockingQueue<CacheInfo> m_imgCacheinfo;//缓存图像队列
|
||||||
|
BlockingQueue<std::shared_ptr<IDecode>> m_rawBuffs;//原图队列
|
||||||
|
std::unique_ptr<thread> m_threadProc;//图像处理线程
|
||||||
|
std::unique_ptr<thread> m_threadcache;//缓存线程
|
||||||
bool ischeck_dogear;
|
bool ischeck_dogear;
|
||||||
volatile int DogEar_index;
|
volatile int DogEar_index;
|
||||||
volatile bool is_DogEar;
|
volatile bool is_DogEar;
|
||||||
volatile bool bRun;
|
volatile bool bRun;
|
||||||
|
volatile bool benablecache;
|
||||||
volatile int atm_orgin_image_remains;
|
volatile int atm_orgin_image_remains;
|
||||||
volatile bool is_scanning;
|
volatile bool is_scanning;
|
||||||
std::unique_ptr<fstream> fw;
|
|
||||||
std::unique_ptr<fstream> fr;
|
|
||||||
GScanCap scanParam;
|
GScanCap scanParam;
|
||||||
Device::PaperSize papersize;
|
Device::PaperSize papersize;
|
||||||
std::shared_ptr<CImageApplyDogEarDetection> m_dogear;
|
std::shared_ptr<CImageApplyDogEarDetection> m_dogear;
|
||||||
std::vector<std::shared_ptr<CImageApply>> m_iaList; //ͼÏñ´¦Àíº¯Êý½Ó¿Ú
|
std::vector<std::shared_ptr<CImageApply>> m_iaList; //ͼÏñ´¦Àíº¯Êý½Ó¿Ú
|
||||||
BlockingQueue<std::shared_ptr<IDecode>> m_rawBuffs;
|
|
||||||
float fx, fy;
|
float fx, fy;
|
||||||
|
std::function<void(int)> m_DogEarDetection_callback;
|
||||||
|
std::function<void(bool)> m_Getimagenumber;
|
||||||
|
snowflake_t m_snowflake;
|
||||||
};
|
};
|
|
@ -28,6 +28,9 @@ const std::string CONFIG = "Config";
|
||||||
const std::string PIXTYPE = "iPixType";
|
const std::string PIXTYPE = "iPixType";
|
||||||
const std::string AUTOMATICCOLOR = "bAutoMaticColorDetece";
|
const std::string AUTOMATICCOLOR = "bAutoMaticColorDetece";
|
||||||
const std::string AUTOMATICCOLORTYPR = "iAutoMaticColorDeteceType";
|
const std::string AUTOMATICCOLORTYPR = "iAutoMaticColorDeteceType";
|
||||||
|
#ifdef UV
|
||||||
|
const std::string ENUVMODEL = "bUVmodel";
|
||||||
|
#endif
|
||||||
const std::string PAPARSIZE = "iPaparSize";
|
const std::string PAPARSIZE = "iPaparSize";
|
||||||
const std::string ENSIZECHECK = "iEnSizeCheck";
|
const std::string ENSIZECHECK = "iEnSizeCheck";
|
||||||
const std::string PAPERALIGN = "iPaperAlign";
|
const std::string PAPERALIGN = "iPaperAlign";
|
||||||
|
@ -92,6 +95,9 @@ typedef struct tagCONFIGPARAMS
|
||||||
int PaperSize;
|
int PaperSize;
|
||||||
bool EnSizeCheck;
|
bool EnSizeCheck;
|
||||||
bool EnAutoCrop;
|
bool EnAutoCrop;
|
||||||
|
#ifdef UV
|
||||||
|
bool EnUVModel;
|
||||||
|
#endif
|
||||||
int Resolution;
|
int Resolution;
|
||||||
int Duplex;
|
int Duplex;
|
||||||
bool EnDiscardBlank;
|
bool EnDiscardBlank;
|
||||||
|
@ -168,6 +174,9 @@ typedef struct tagHARDWAREPARAMS
|
||||||
byte en_skrewdetect;
|
byte en_skrewdetect;
|
||||||
byte skrewdetectlevel;
|
byte skrewdetectlevel;
|
||||||
LowPowerMode lowpowermode;
|
LowPowerMode lowpowermode;
|
||||||
|
#ifdef UV
|
||||||
|
byte en_uv;
|
||||||
|
#endif
|
||||||
}HardwareCaps;
|
}HardwareCaps;
|
||||||
|
|
||||||
typedef struct Scan_Rect {
|
typedef struct Scan_Rect {
|
||||||
|
|
|
@ -28,6 +28,10 @@ GScanCap GscanJsonConfig::GetDefaultGscancapValue()
|
||||||
gcap.paperAlign = PaperAlign::Rot0;
|
gcap.paperAlign = PaperAlign::Rot0;
|
||||||
gcap.papertype = 0;//TwSS::NONE
|
gcap.papertype = 0;//TwSS::NONE
|
||||||
gcap.en_sizecheck = FALSE;
|
gcap.en_sizecheck = FALSE;
|
||||||
|
|
||||||
|
#ifdef UV
|
||||||
|
gcap.hardwarecaps.en_uv = FALSE;
|
||||||
|
#endif
|
||||||
gcap.is_autocrop = TRUE;//ĬÈÏ×Ô¶¯²ÃÇÐ
|
gcap.is_autocrop = TRUE;//ĬÈÏ×Ô¶¯²ÃÇÐ
|
||||||
gcap.is_duplex = TRUE;
|
gcap.is_duplex = TRUE;
|
||||||
gcap.is_autodiscradblank_normal = FALSE;
|
gcap.is_autodiscradblank_normal = FALSE;
|
||||||
|
@ -100,6 +104,9 @@ void GscanJsonConfig::SaveGscanCapConfig(const GScanCap & gcap, const std::strin
|
||||||
outJson["Config"].Add(FLOD, (bool)(gcap.en_fold), false);
|
outJson["Config"].Add(FLOD, (bool)(gcap.en_fold), false);
|
||||||
outJson["Config"].Add(SWITCHFRONTBACK, (bool)(gcap.is_switchfrontback), false);
|
outJson["Config"].Add(SWITCHFRONTBACK, (bool)(gcap.is_switchfrontback), false);
|
||||||
|
|
||||||
|
#ifdef UV
|
||||||
|
outJson["Config"].Add(ENUVMODEL, (bool)(gcap.hardwarecaps.en_uv), false);
|
||||||
|
#endif
|
||||||
outJson["Config"].Add(BRIGHTNESS, (int)(gcap.brightness));
|
outJson["Config"].Add(BRIGHTNESS, (int)(gcap.brightness));
|
||||||
outJson["Config"].Add(AUTOCONTRAST, (bool)(gcap.is_autocontrast), false);
|
outJson["Config"].Add(AUTOCONTRAST, (bool)(gcap.is_autocontrast), false);
|
||||||
outJson["Config"].Add(CONTRAST, (int)(gcap.contrast));
|
outJson["Config"].Add(CONTRAST, (int)(gcap.contrast));
|
||||||
|
@ -155,6 +162,9 @@ void GscanJsonConfig::WriteJsonArrayToFile(std::vector<GScanCap> cfgArray, const
|
||||||
root["Config"].AddEmptySubArray(DISCARBLANK);
|
root["Config"].AddEmptySubArray(DISCARBLANK);
|
||||||
root["Config"].AddEmptySubArray(DISCARBLANKVINCE);
|
root["Config"].AddEmptySubArray(DISCARBLANKVINCE);
|
||||||
root["Config"].AddEmptySubArray(DISCARBLANK_VALUE);
|
root["Config"].AddEmptySubArray(DISCARBLANK_VALUE);
|
||||||
|
#ifdef UV
|
||||||
|
root["Config"].AddEmptySubArray(ENUVMODEL);
|
||||||
|
#endif
|
||||||
//root["Config"].AddEmptySubArray(DB_AREANUM);
|
//root["Config"].AddEmptySubArray(DB_AREANUM);
|
||||||
//root["Config"].AddEmptySubArray(DB_DEVNMAX);
|
//root["Config"].AddEmptySubArray(DB_DEVNMAX);
|
||||||
root["Config"].AddEmptySubArray(FLOD);
|
root["Config"].AddEmptySubArray(FLOD);
|
||||||
|
@ -215,7 +225,9 @@ void GscanJsonConfig::WriteJsonArrayToFile(std::vector<GScanCap> cfgArray, const
|
||||||
//root["Config"][DB_DEVNMAX].Add(cfgArray[i].DBlank_DevnMax);
|
//root["Config"][DB_DEVNMAX].Add(cfgArray[i].DBlank_DevnMax);
|
||||||
root["Config"][FLOD].Add(i, (bool)cfgArray[i].en_fold);
|
root["Config"][FLOD].Add(i, (bool)cfgArray[i].en_fold);
|
||||||
root["Config"][SWITCHFRONTBACK].Add(i,(bool)cfgArray[i].is_switchfrontback);
|
root["Config"][SWITCHFRONTBACK].Add(i,(bool)cfgArray[i].is_switchfrontback);
|
||||||
|
#ifdef UV
|
||||||
|
root["Config"][ENUVMODEL].Add(i, cfgArray[i].hardwarecaps.en_uv);
|
||||||
|
#endif
|
||||||
root["Config"][BRIGHTNESS].Add((int)cfgArray[i].brightness);
|
root["Config"][BRIGHTNESS].Add((int)cfgArray[i].brightness);
|
||||||
root["Config"][AUTOCONTRAST].Add(i, (bool)cfgArray[i].is_autocontrast);
|
root["Config"][AUTOCONTRAST].Add(i, (bool)cfgArray[i].is_autocontrast);
|
||||||
root["Config"][CONTRAST].Add((int)cfgArray[i].contrast);
|
root["Config"][CONTRAST].Add((int)cfgArray[i].contrast);
|
||||||
|
@ -378,8 +390,10 @@ std::vector<GScanCap> GscanJsonConfig::parseJsonFromString(const std::string str
|
||||||
root["Config"].Get(SWITCHFRONTBACK, itmEnSwitchFrontBack);
|
root["Config"].Get(SWITCHFRONTBACK, itmEnSwitchFrontBack);
|
||||||
neb::CJsonObject itmdiscarbrank_value;
|
neb::CJsonObject itmdiscarbrank_value;
|
||||||
root["Config"].Get(DISCARBLANK_VALUE, itmdiscarbrank_value);
|
root["Config"].Get(DISCARBLANK_VALUE, itmdiscarbrank_value);
|
||||||
|
#ifdef UV
|
||||||
|
neb::CJsonObject itmEnUV;
|
||||||
|
root["Config"].Get(ENUVMODEL, itmEnUV);
|
||||||
|
#endif
|
||||||
neb::CJsonObject itmBrtnes;
|
neb::CJsonObject itmBrtnes;
|
||||||
root["Config"].Get(BRIGHTNESS, itmBrtnes);
|
root["Config"].Get(BRIGHTNESS, itmBrtnes);
|
||||||
neb::CJsonObject itmAutoCrnt;
|
neb::CJsonObject itmAutoCrnt;
|
||||||
|
@ -489,7 +503,10 @@ std::vector<GScanCap> GscanJsonConfig::parseJsonFromString(const std::string str
|
||||||
cfp.en_fold = b_value ? 1 : 0;
|
cfp.en_fold = b_value ? 1 : 0;
|
||||||
itmEnSwitchFrontBack.Get(i, b_value);
|
itmEnSwitchFrontBack.Get(i, b_value);
|
||||||
cfp.is_switchfrontback = b_value ? 1 : 0;
|
cfp.is_switchfrontback = b_value ? 1 : 0;
|
||||||
|
#ifdef UV
|
||||||
|
root["Config"].Get(ENUVMODEL, b_value);
|
||||||
|
cfp.hardwarecaps.en_uv = b_value ? 1 : 0;
|
||||||
|
#endif
|
||||||
itmBrtnes.Get(i, i_value);
|
itmBrtnes.Get(i, i_value);
|
||||||
cfp.brightness = i_value;
|
cfp.brightness = i_value;
|
||||||
itmAutoCrnt.Get(i, b_value);
|
itmAutoCrnt.Get(i, b_value);
|
||||||
|
|
|
@ -8,17 +8,17 @@ CImageApplyAutoCrop::CImageApplyAutoCrop()
|
||||||
, m_isConvexHull(true)
|
, m_isConvexHull(true)
|
||||||
, m_isFillColor(false)
|
, m_isFillColor(false)
|
||||||
, m_threshold(40)
|
, m_threshold(40)
|
||||||
, m_noise(8)
|
, m_noise(2)
|
||||||
, m_indent(5)
|
, m_indent(5)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor, double threshold, int noise, int indent)
|
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, double threshold, int noise, int indent)
|
||||||
: m_isCrop(isCrop)
|
: m_isCrop(isCrop)
|
||||||
, m_isDesaskew(isDesaskew)
|
, m_isDesaskew(isDesaskew)
|
||||||
, m_isFillBlank(isFillBlank)
|
, m_isFillBlank(isFillBlank)
|
||||||
, m_isConvexHull(isConvex)
|
, m_isConvexHull(isConvex)
|
||||||
, m_isFillColor(isFillColor)
|
, m_isFillColor(false)
|
||||||
, m_threshold(threshold)
|
, m_threshold(threshold)
|
||||||
, m_noise(noise)
|
, m_noise(noise)
|
||||||
, m_indent(indent)
|
, m_indent(indent)
|
||||||
|
@ -54,11 +54,18 @@ void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
|
||||||
|
|
||||||
if (m_maxContour.size() == 0)
|
if (m_maxContour.size() == 0)
|
||||||
{
|
{
|
||||||
|
thre.release();
|
||||||
|
#ifdef LOG
|
||||||
|
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply");
|
||||||
|
#endif // LOG
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
thre.release();
|
thre.release();
|
||||||
|
dst.release();
|
||||||
|
|
||||||
cv::RotatedRect rect = hg::getBoundingRect(m_maxContour);
|
cv::RotatedRect rect = hg::getBoundingRect(m_maxContour);
|
||||||
|
m_rect = rect;
|
||||||
|
|
||||||
cv::Rect boudingRect = cv::boundingRect(m_maxContour);
|
cv::Rect boudingRect = cv::boundingRect(m_maxContour);
|
||||||
boudingRect.x -= 1;
|
boudingRect.x -= 1;
|
||||||
boudingRect.y -= 1;
|
boudingRect.y -= 1;
|
||||||
|
@ -70,14 +77,18 @@ void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
|
||||||
cv::Point2f srcTri[4];
|
cv::Point2f srcTri[4];
|
||||||
cv::Point2f dstTri[3];
|
cv::Point2f dstTri[3];
|
||||||
rect.points(srcTri);
|
rect.points(srcTri);
|
||||||
|
for (cv::Point2f& p : srcTri)
|
||||||
|
{
|
||||||
|
p.x -= 0.5;
|
||||||
|
p.y -= 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
dstTri[0] = cv::Point2f(0, rect.size.height - 1);
|
dstTri[0] = cv::Point2f(0, rect.size.height - 1);
|
||||||
dstTri[1] = cv::Point2f(0, 0);
|
dstTri[1] = cv::Point2f(0, 0);
|
||||||
dstTri[2] = cv::Point2f(rect.size.width - 1, 0);
|
dstTri[2] = cv::Point2f(rect.size.width - 1, 0);
|
||||||
cv::Mat warp_mat;
|
cv::Mat warp_mat;
|
||||||
warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
||||||
//cv::warpAffine(src, dst, warp_mat, rect.size,cv::INTER_LANCZOS4);
|
cv::warpAffine(src, dst, warp_mat, rect.size, cv::INTER_NEAREST);
|
||||||
cv::warpAffine(src, dst, warp_mat, rect.size);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dst = src(boudingRect & cv::Rect(0, 0, src.cols, src.rows));
|
dst = src(boudingRect & cv::Rect(0, 0, src.cols, src.rows));
|
||||||
|
@ -149,9 +160,12 @@ void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
|
||||||
|
|
||||||
void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||||
{
|
{
|
||||||
|
m_rects.clear();
|
||||||
if (mats.empty()) return;
|
if (mats.empty()) return;
|
||||||
if (!mats[0].empty()) {
|
if (!mats[0].empty()) {
|
||||||
apply(mats[0], 0);
|
apply(mats[0], 0);
|
||||||
|
m_rects.push_back(m_rect);
|
||||||
|
//cv::imwrite("1.bmp", mats[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTwoSide && mats.size() > 1)
|
if (isTwoSide && mats.size() > 1)
|
||||||
|
@ -159,8 +173,11 @@ void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||||
cv::Size dSize = m_fixedSize;
|
cv::Size dSize = m_fixedSize;
|
||||||
if (!mats[0].empty())
|
if (!mats[0].empty())
|
||||||
m_fixedSize = mats[0].size();
|
m_fixedSize = mats[0].size();
|
||||||
|
|
||||||
if (!mats[1].empty()) {
|
if (!mats[1].empty()) {
|
||||||
apply(mats[1], 1);
|
apply(mats[1], 1);
|
||||||
|
m_rects.push_back(m_rect);
|
||||||
|
//cv::imwrite("1.bmp", mats[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mats[0].empty())
|
if (!mats[0].empty())
|
||||||
|
|
|
@ -21,23 +21,23 @@
|
||||||
|
|
||||||
#include "ImageApply.h"
|
#include "ImageApply.h"
|
||||||
|
|
||||||
class CImageApplyAutoCrop : public CImageApply
|
class CImageApplyAutoCrop : public CImageApply
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CImageApplyAutoCrop();
|
CImageApplyAutoCrop();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* isCrop [in]:自动幅面裁剪使能,true自动裁剪,false为固定裁剪
|
* isCrop [in]:自动幅面裁剪使能,true自动裁剪,false为固定裁剪
|
||||||
* isDesaskew [in]:自动纠偏使能,true自动纠偏,false为不纠偏
|
* isDesaskew [in]:自动纠偏使能,true自动纠偏,false为不纠偏
|
||||||
* isFillBlank [in]:黑底填充使能,true为填充,false为不填充
|
* isFillBlank [in]:黑底填充使能,true为填充,false为不填充
|
||||||
* fixedSize [in]:固定幅面尺寸,当isCrop为false时生效,结果尺寸按fixedSize大小输出,单位像素
|
* fixedSize [in]:固定幅面尺寸,当isCrop为false时生效,结果尺寸按fixedSize大小输出,单位像素
|
||||||
* isConvex [in]:黑底填充时的填充方式,true为凸多边形填充,false为凹多边形填充,默认true
|
* isConvex [in]:黑底填充时的填充方式,true为凸多边形填充,false为凹多边形填充,默认true
|
||||||
* isFillColor [in]:黑底填充时采用自适应色彩填充,false为白色填充,true为自适应文稿底色填充,默认false
|
* isFillColor [in]:黑底填充时采用自适应色彩填充,false为白色填充,true为自适应文稿底色填充,默认false
|
||||||
* threshold [in]:二值化阈值,取值范围(0, 255),默认40
|
* threshold [in]:二值化阈值,取值范围(0, 255),默认40
|
||||||
* noise [in]:除噪像素,能够消除noise宽度的背景竖条纹干扰,默认40
|
* noise [in]:除噪像素,能够消除noise宽度的背景竖条纹干扰,默认40
|
||||||
* indent [in]:轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默认5
|
* indent [in]:轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默认5
|
||||||
*/
|
*/
|
||||||
CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true, bool isFillColor = false, double threshold = 40, int noise = 8, int indent = 5);
|
CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true, double threshold = 40, int noise = 8, int indent = 5);
|
||||||
|
|
||||||
virtual ~CImageApplyAutoCrop();
|
virtual ~CImageApplyAutoCrop();
|
||||||
|
|
||||||
|
@ -55,6 +55,10 @@ public:
|
||||||
|
|
||||||
double threshold() { return m_threshold; }
|
double threshold() { return m_threshold; }
|
||||||
|
|
||||||
|
const cv::RotatedRect& rotatedROI() { return m_rect; }
|
||||||
|
|
||||||
|
const std::vector<cv::RotatedRect>& rotatedROIs() { return m_rects; }
|
||||||
|
|
||||||
int noise() { return m_noise; }
|
int noise() { return m_noise; }
|
||||||
|
|
||||||
int indent() { return m_indent; }
|
int indent() { return m_indent; }
|
||||||
|
@ -95,7 +99,9 @@ private:
|
||||||
int m_noise;
|
int m_noise;
|
||||||
int m_indent;
|
int m_indent;
|
||||||
cv::Size m_fixedSize;
|
cv::Size m_fixedSize;
|
||||||
|
cv::RotatedRect m_rect;
|
||||||
std::vector<cv::Point> m_maxContour;
|
std::vector<cv::Point> m_maxContour;
|
||||||
|
std::vector<cv::RotatedRect> m_rects;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !IMAGE_APPLY_AUTO_CROP_H
|
#endif // !IMAGE_APPLY_AUTO_CROP_H
|
||||||
|
|
|
@ -17,5 +17,5 @@
|
||||||
#include "ImageApplyHSVCorrect.h"
|
#include "ImageApplyHSVCorrect.h"
|
||||||
#include "ImageApplyDetachNoise.h"
|
#include "ImageApplyDetachNoise.h"
|
||||||
#include "ImageApplyColorRecognition.h"
|
#include "ImageApplyColorRecognition.h"
|
||||||
|
#include "ImageApplyUV.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,8 +28,9 @@ CImageApplyRotation::~CImageApplyRotation()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CImageApplyRotation::apply(cv::Mat & pDib, int side)
|
void CImageApplyRotation::apply(cv::Mat& pDib, int side)
|
||||||
{
|
{
|
||||||
|
m_angleResult = 0;
|
||||||
#ifdef LOG
|
#ifdef LOG
|
||||||
FileTools::write_log("imgprc.txt", "enter CImageApplyRotation apply");
|
FileTools::write_log("imgprc.txt", "enter CImageApplyRotation apply");
|
||||||
#endif // LOG
|
#endif // LOG
|
||||||
|
@ -44,44 +45,48 @@ void CImageApplyRotation::apply(cv::Mat & pDib, int side)
|
||||||
if (m_rotation == RotationType::AutoTextOrientation) //<2F>Զ<EFBFBD><D4B6>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><CAB6>
|
if (m_rotation == RotationType::AutoTextOrientation) //<2F>Զ<EFBFBD><D4B6>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><CAB6>
|
||||||
{
|
{
|
||||||
#ifdef USE_TESSERCAT
|
#ifdef USE_TESSERCAT
|
||||||
if (osd)
|
if (osd)
|
||||||
{
|
{
|
||||||
cv::Mat temp;
|
cv::Mat temp;
|
||||||
if (m_dpi != 200)
|
if (m_dpi != 200)
|
||||||
{
|
{
|
||||||
double scale = 200 / static_cast<double>(m_dpi);
|
double scale = 200 / static_cast<double>(m_dpi);
|
||||||
int new_w = static_cast<int>(pDib.cols * scale) / 4 * 4;
|
int new_w = (pDib.cols * scale + 3) / 4 * 4;
|
||||||
int new_h = pDib.rows * scale;
|
int new_h = pDib.rows * scale;
|
||||||
cv::resize(pDib, temp, cv::Size(new_w, new_h));
|
cv::resize(pDib, temp, cv::Size(new_w, new_h));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
temp = pDib(cv::Rect(0, 0, pDib.cols / 4 * 4, pDib.rows)).clone();
|
temp = pDib(cv::Rect(0, 0, pDib.cols / 4 * 4, pDib.rows)).clone();
|
||||||
|
|
||||||
if (temp.channels() == 3)
|
if (temp.channels() == 3)
|
||||||
cv::cvtColor(temp, temp, cv::COLOR_BGR2GRAY);
|
cv::cvtColor(temp, temp, cv::COLOR_BGR2GRAY);
|
||||||
cv::threshold(temp, temp, 180, 255, cv::THRESH_OTSU);
|
cv::threshold(temp, temp, 180, 255, cv::THRESH_OTSU);
|
||||||
|
|
||||||
HG_OCR* ptr_osd = reinterpret_cast<HG_OCR*>(osd);
|
HG_OCR* ptr_osd = reinterpret_cast<HG_OCR*>(osd);
|
||||||
int orientation = ptr_osd->orientation(temp.data, temp.cols, temp.rows, temp.channels(), 200);
|
int orientation = ptr_osd->orientation(temp.data, temp.cols, temp.rows, temp.channels(), 200);
|
||||||
|
|
||||||
switch (orientation)
|
switch (orientation)
|
||||||
{
|
{
|
||||||
case 90:
|
case 90:
|
||||||
cv::transpose(pDib, pDib);
|
cv::transpose(pDib, pDib);
|
||||||
cv::flip(pDib, pDib, 0);
|
cv::flip(pDib, pDib, 0);
|
||||||
break;
|
m_angleResult = 90;
|
||||||
case 180:
|
break;
|
||||||
|
case 180:
|
||||||
cv::flip(pDib, pDib, 0);
|
cv::flip(pDib, pDib, 0);
|
||||||
cv::flip(pDib, pDib, 1);
|
cv::flip(pDib, pDib, 1);
|
||||||
break;
|
m_angleResult = 180;
|
||||||
case 270:
|
break;
|
||||||
|
case 270:
|
||||||
cv::transpose(pDib, pDib);
|
cv::transpose(pDib, pDib);
|
||||||
cv::flip(pDib, pDib, 1);
|
cv::flip(pDib, pDib, 1);
|
||||||
break;
|
m_angleResult = 270;
|
||||||
default:
|
break;
|
||||||
break;
|
default:
|
||||||
}
|
m_angleResult = 0;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (m_backTranspose && side == 1) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת180
|
else if (m_backTranspose && side == 1) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת180
|
||||||
|
@ -92,11 +97,13 @@ void CImageApplyRotation::apply(cv::Mat & pDib, int side)
|
||||||
{
|
{
|
||||||
transpose(pDib, pDib);
|
transpose(pDib, pDib);
|
||||||
flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 0 : 1);
|
flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 0 : 1);
|
||||||
|
m_angleResult = m_rotation == RotationType::Rotate_90_clockwise ? 270 : 90;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
flip(pDib, pDib, 1);
|
|
||||||
flip(pDib, pDib, 0);
|
flip(pDib, pDib, 0);
|
||||||
|
flip(pDib, pDib, 1);
|
||||||
|
m_angleResult = 180;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,11 +113,13 @@ void CImageApplyRotation::apply(cv::Mat & pDib, int side)
|
||||||
{
|
{
|
||||||
transpose(pDib, pDib);
|
transpose(pDib, pDib);
|
||||||
flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 1 : 0);
|
flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 1 : 0);
|
||||||
|
m_angleResult = m_rotation == RotationType::Rotate_90_clockwise ? 90 : 270;
|
||||||
}
|
}
|
||||||
else if (m_rotation == RotationType::Rotate_180)
|
else if (m_rotation == RotationType::Rotate_180)
|
||||||
{
|
{
|
||||||
flip(pDib, pDib, 0);
|
flip(pDib, pDib, 0);
|
||||||
flip(pDib, pDib, 1);
|
flip(pDib, pDib, 1);
|
||||||
|
m_angleResult = 180;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef LOG
|
#ifdef LOG
|
||||||
|
@ -120,11 +129,13 @@ void CImageApplyRotation::apply(cv::Mat & pDib, int side)
|
||||||
|
|
||||||
void CImageApplyRotation::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
void CImageApplyRotation::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||||
{
|
{
|
||||||
(void)isTwoSide;
|
(void)isTwoSide;
|
||||||
|
m_angleResults.clear();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (cv::Mat& var : mats) {
|
for (cv::Mat& var : mats) {
|
||||||
if (!var.empty()) {
|
if (!var.empty()) {
|
||||||
apply(var, i);
|
apply(var, i);
|
||||||
|
m_angleResults.push_back(m_angleResult);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,3 @@
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
|
|
||||||
* 功能:旋转图像
|
|
||||||
* 作者:刘丁维
|
|
||||||
* 生成时间:2020/4/21
|
|
||||||
* 最近修改时间:v1.0 2020/4/21
|
|
||||||
v1.1 2020/8/12 修复文稿方向自动识别导致崩溃的BUG
|
|
||||||
* 版本号:v1.1
|
|
||||||
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMAGE_APPLY_ROTATION_H
|
#ifndef IMAGE_APPLY_ROTATION_H
|
||||||
#define IMAGE_APPLY_ROTATION_H
|
#define IMAGE_APPLY_ROTATION_H
|
||||||
|
|
||||||
|
@ -21,27 +8,21 @@ class CImageApplyRotation : public CImageApply
|
||||||
public:
|
public:
|
||||||
enum class RotationType
|
enum class RotationType
|
||||||
{
|
{
|
||||||
Invalid, //无效
|
Invalid,
|
||||||
Rotate_90_clockwise, //顺时针90°
|
Rotate_90_clockwise,
|
||||||
Rotate_180, //180°
|
Rotate_180,
|
||||||
Rotate_90_anti_clockwise, //逆时针90°,即270°
|
Rotate_90_anti_clockwise,
|
||||||
|
|
||||||
AutoTextOrientation //自动文稿方向识别旋转
|
AutoTextOrientation
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/*
|
|
||||||
* rotation [in]:旋转类型
|
|
||||||
* isBackTransposed [in]:true为背面180°旋转,反之亦然
|
|
||||||
* dpi [in]:当前图像的DPI,该参数在rotation为AutoTextOrientation时生效。在识别文稿方向时,会默认将图像变换为200DPI进行识别
|
|
||||||
* tessadataPath [in]:训练库文件路径,该参数在rotation为AutoTextOrientation时生效
|
|
||||||
*/
|
|
||||||
CImageApplyRotation(RotationType rotation, bool isBackTransposed = false, int dpi = 200, const char* tessdataPath = nullptr);
|
CImageApplyRotation(RotationType rotation, bool isBackTransposed = false, int dpi = 200, const char* tessdataPath = nullptr);
|
||||||
|
|
||||||
virtual ~CImageApplyRotation();
|
virtual ~CImageApplyRotation();
|
||||||
|
|
||||||
virtual void apply(cv::Mat & pDib, int side) override;
|
virtual void apply(cv::Mat& pDib, int side) override;
|
||||||
|
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||||
|
|
||||||
|
@ -49,6 +30,10 @@ public:
|
||||||
|
|
||||||
int getDPI() { return m_dpi; }
|
int getDPI() { return m_dpi; }
|
||||||
|
|
||||||
|
int angleResult() { return m_angleResult; }
|
||||||
|
|
||||||
|
const std::vector<int>& angleResults() { return m_angleResults; }
|
||||||
|
|
||||||
RotationType getRotationType() { return m_rotation; }
|
RotationType getRotationType() { return m_rotation; }
|
||||||
|
|
||||||
void setBackTransposed(bool enabled) { m_backTranspose = enabled; }
|
void setBackTransposed(bool enabled) { m_backTranspose = enabled; }
|
||||||
|
@ -63,6 +48,9 @@ private:
|
||||||
int m_dpi;
|
int m_dpi;
|
||||||
|
|
||||||
void* osd;
|
void* osd;
|
||||||
|
|
||||||
|
int m_angleResult;
|
||||||
|
std::vector<int> m_angleResults;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !IMAGE_APPLY_ROTATION_H
|
#endif // !IMAGE_APPLY_ROTATION_H
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
#include "ImageApplyUV.h"
|
||||||
|
using namespace cv;
|
||||||
|
#define SCA 50
|
||||||
|
|
||||||
|
ImageApplyUV::ImageApplyUV(): lut(1, 256, CV_8UC1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageApplyUV::~ImageApplyUV()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageApplyUV::update_lutData(int contrast)
|
||||||
|
{
|
||||||
|
unsigned char* ptr = lut.data;
|
||||||
|
int m_contrast = cv::max(-127, cv::min(contrast, 127));
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
//update contrast
|
||||||
|
if (i < 128)
|
||||||
|
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(i - m_contrast, 127)));
|
||||||
|
else
|
||||||
|
ptr[i] = static_cast<unsigned char>(cv::max(127, cv::min(i + m_contrast, 255)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageApplyUV::Apply(cv::Mat& image, const cv::Mat& uv, int dpi, int thresh)
|
||||||
|
{
|
||||||
|
update_lutData(12);
|
||||||
|
cv::LUT(uv, lut, uv);
|
||||||
|
Mat uv_resize;
|
||||||
|
cv::resize(uv, uv_resize, cv::Size(uv.cols * SCA / dpi, uv.rows * SCA / dpi));
|
||||||
|
if (uv_resize.channels() == 3)
|
||||||
|
cv::cvtColor(uv_resize, uv_resize, cv::COLOR_BGR2GRAY);
|
||||||
|
cv::threshold(uv_resize, uv_resize, 0, 255, THRESH_OTSU);
|
||||||
|
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1500 / dpi, 1500 / dpi));
|
||||||
|
cv::dilate(uv_resize, uv_resize, element);
|
||||||
|
std::vector<std::vector<cv::Point>> contours;
|
||||||
|
std::vector<cv::Vec4i> hierarchy;
|
||||||
|
findContours1(uv_resize, contours, hierarchy, cv::RETR_EXTERNAL);
|
||||||
|
|
||||||
|
std::map<int, cv::Scalar> map_color;
|
||||||
|
for (int i = 0; i < contours.size(); i++)
|
||||||
|
{
|
||||||
|
cv::Rect roi = cv::boundingRect(contours[i]);
|
||||||
|
roi.x *= dpi / SCA;
|
||||||
|
roi.y *= dpi / SCA;
|
||||||
|
roi.width *= dpi / SCA;
|
||||||
|
roi.height *= dpi / SCA;
|
||||||
|
|
||||||
|
purgeQR_kernal(image, roi, map_color, dpi, thresh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Mat ImageApplyUV::Apply(const cv::Mat& image, const cv::Mat& uv, const cv::RotatedRect& uvRoi, bool isDesaskew, int angle)
|
||||||
|
{
|
||||||
|
if (uvRoi.size.width == 0) return cv::Mat();
|
||||||
|
|
||||||
|
cv::RotatedRect uvRoi_clone = uvRoi;
|
||||||
|
cv::Mat dst = cv::Mat::zeros(image.rows > image.cols ? image.rows : (image.rows * 2), image.cols > image.rows ? image.cols : (image.cols * 2), image.type());
|
||||||
|
image.copyTo(dst(cv::Rect(0, 0, image.cols, image.rows)));
|
||||||
|
|
||||||
|
cv::Mat dst_uv = dst(cv::Rect(image.rows > image.cols ? image.cols : 0, image.rows > image.cols ? 0 : image.rows, image.cols, image.rows));
|
||||||
|
if (isDesaskew)
|
||||||
|
{
|
||||||
|
cv::Point2f srcTri[4];
|
||||||
|
cv::Point2f dstTri[3];
|
||||||
|
uvRoi_clone.points(srcTri);
|
||||||
|
|
||||||
|
|
||||||
|
if (angle == 90)
|
||||||
|
{
|
||||||
|
dstTri[0] = cv::Point2f(0, 0);
|
||||||
|
dstTri[1] = cv::Point2f(dst_uv.cols - 1, 0);
|
||||||
|
dstTri[2] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1);
|
||||||
|
}
|
||||||
|
else if (angle == 180)
|
||||||
|
{
|
||||||
|
dstTri[0] = cv::Point2f(dst_uv.cols - 1, 0);
|
||||||
|
dstTri[1] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1);
|
||||||
|
dstTri[2] = cv::Point2f(0, dst_uv.rows - 1);
|
||||||
|
}
|
||||||
|
else if (angle == 270)
|
||||||
|
{
|
||||||
|
dstTri[0] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1);
|
||||||
|
dstTri[1] = cv::Point2f(0, dst_uv.rows - 1);
|
||||||
|
dstTri[2] = cv::Point2f(0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstTri[0] = cv::Point2f(0, dst_uv.rows - 1);
|
||||||
|
dstTri[1] = cv::Point2f(0, 0);
|
||||||
|
dstTri[2] = cv::Point2f(dst_uv.cols - 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
||||||
|
if (uv.channels() == 1 && dst_uv.channels() == 3)
|
||||||
|
{
|
||||||
|
cv::Mat uv_temp;
|
||||||
|
cv::warpAffine(uv, uv_temp, warp_mat, dst_uv.size());
|
||||||
|
cv::cvtColor(uv_temp, dst_uv, cv::COLOR_GRAY2BGR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cv::warpAffine(uv, dst_uv, warp_mat, dst_uv.size());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cv::Rect uvBoundingRect = uvRoi_clone.boundingRect();
|
||||||
|
|
||||||
|
cv::Rect roi_dst_right;
|
||||||
|
roi_dst_right.x = dst_uv.cols > uvBoundingRect.width ? (dst_uv.cols - uvBoundingRect.width) / 2 : 0;
|
||||||
|
roi_dst_right.width = cv::min(dst_uv.cols, uvBoundingRect.width);
|
||||||
|
roi_dst_right.y = dst_uv.rows > uvBoundingRect.height ? (dst_uv.rows - uvBoundingRect.height) / 2 : 0;
|
||||||
|
roi_dst_right.height = cv::min(dst_uv.rows, uvBoundingRect.height);
|
||||||
|
|
||||||
|
cv::Rect roi_uv_BoundingRect((uvBoundingRect.width - roi_dst_right.width) / 2,
|
||||||
|
(uvBoundingRect.height - roi_dst_right.height) / 2, roi_dst_right.width, roi_dst_right.height);
|
||||||
|
|
||||||
|
Mat uvCrop = (uv(uvBoundingRect))(roi_uv_BoundingRect);
|
||||||
|
if (uvCrop.channels() == 1 && dst_uv.channels() == 3)
|
||||||
|
cv::cvtColor(uvCrop, uvCrop, cv::COLOR_GRAY2BGR);
|
||||||
|
uvCrop.copyTo(dst_uv(roi_dst_right));
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ImageApplyUV::purgeQR_kernal(cv::Mat& image, const cv::Rect& roi, std::map<int, cv::Scalar> map_color, int dpi, int threshold)
|
||||||
|
{
|
||||||
|
cv::Mat image_roi = image(roi);
|
||||||
|
cv::Mat mask;
|
||||||
|
cv::cvtColor(image_roi, mask, cv::COLOR_BGR2GRAY);
|
||||||
|
cv::threshold(mask, mask, 127, 255, cv::THRESH_OTSU);
|
||||||
|
cv::Mat image_resize;
|
||||||
|
cv::resize(image, image_resize, cv::Size(image.cols, 800));
|
||||||
|
|
||||||
|
for (int i = 0, cols = image_roi.cols, rows = image_roi.rows; i < cols; i++)
|
||||||
|
{
|
||||||
|
cv::Scalar color_fill;
|
||||||
|
if (map_color.find(i + roi.x) == map_color.end())
|
||||||
|
{
|
||||||
|
color_fill = getColor(image_resize, roi.x + i, threshold);
|
||||||
|
map_color[i + roi.x] = color_fill;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
color_fill = map_color[i + roi.x];
|
||||||
|
|
||||||
|
for (int j = 0; j < rows; j++)
|
||||||
|
{
|
||||||
|
if (*mask.ptr<uchar>(j, i))
|
||||||
|
{
|
||||||
|
uchar* color = image_roi.ptr<uchar>(j, i);
|
||||||
|
color[0] = color_fill[0];
|
||||||
|
color[1] = color_fill[1];
|
||||||
|
color[2] = color_fill[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageApplyUV::findContours1(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset)
|
||||||
|
{
|
||||||
|
CvMat c_image = src;
|
||||||
|
cv::MemStorage storage(cvCreateMemStorage());
|
||||||
|
CvSeq* _ccontours = nullptr;
|
||||||
|
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset));
|
||||||
|
|
||||||
|
if (!_ccontours)
|
||||||
|
{
|
||||||
|
contours.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
|
||||||
|
size_t total = all_contours.size();
|
||||||
|
contours.resize(total);
|
||||||
|
|
||||||
|
cv::SeqIterator<CvSeq*> it = all_contours.begin();
|
||||||
|
for (size_t i = 0; i < total; i++, ++it)
|
||||||
|
{
|
||||||
|
CvSeq* c = *it;
|
||||||
|
reinterpret_cast<CvContour*>(c)->color = static_cast<int>(i);
|
||||||
|
int count = c->total;
|
||||||
|
int* data = new int[static_cast<size_t>(count * 2)];
|
||||||
|
cvCvtSeqToArray(c, data);
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1]));
|
||||||
|
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
hierarchy.resize(total);
|
||||||
|
it = all_contours.begin();
|
||||||
|
for (size_t i = 0; i < total; i++, ++it)
|
||||||
|
{
|
||||||
|
CvSeq* c = *it;
|
||||||
|
int h_next = c->h_next ? reinterpret_cast<CvContour*>(c->h_next)->color : -1;
|
||||||
|
int h_prev = c->h_prev ? reinterpret_cast<CvContour*>(c->h_prev)->color : -1;
|
||||||
|
int v_next = c->v_next ? reinterpret_cast<CvContour*>(c->v_next)->color : -1;
|
||||||
|
int v_prev = c->v_prev ? reinterpret_cast<CvContour*>(c->v_prev)->color : -1;
|
||||||
|
hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
storage.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Scalar ImageApplyUV::getColor(const cv::Mat& image, int col, int threshold)
|
||||||
|
{
|
||||||
|
cv::Scalar color(0, 0, 0);
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
for (int i = 0, length = image.rows; i < length; i++)
|
||||||
|
{
|
||||||
|
const uchar* ptr = image.ptr<uchar>(i, col);
|
||||||
|
int gray = (ptr[0] * 30 + ptr[1] * 59 + ptr[2] * 11) / 100;
|
||||||
|
if (gray > threshold)
|
||||||
|
{
|
||||||
|
color[0] += ptr[0];
|
||||||
|
color[1] += ptr[1];
|
||||||
|
color[2] += ptr[2];
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num)
|
||||||
|
color /= num;
|
||||||
|
else
|
||||||
|
color[0] = color[1] = color[2] = 255;
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include "ImageProcess/ImageProcess_Public.h"
|
||||||
|
|
||||||
|
class ImageApplyUV
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageApplyUV();
|
||||||
|
~ImageApplyUV();
|
||||||
|
void Apply(cv::Mat& image, const cv::Mat& uv, int dpi = 200, int thresh = 100);
|
||||||
|
|
||||||
|
static cv::Mat Apply(const cv::Mat& image, const cv::Mat& uv, const cv::RotatedRect& uvRoi, bool isDesaskew, int angle);
|
||||||
|
private:
|
||||||
|
void purgeQR_kernal(cv::Mat& image, const cv::Rect& roi, std::map<int, cv::Scalar> map_color, int dpi, int threshold);
|
||||||
|
void findContours1(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy,
|
||||||
|
int retr = cv::RETR_LIST, int method = cv::CHAIN_APPROX_SIMPLE, cv::Point offset = cv::Point(0, 0));
|
||||||
|
cv::Scalar getColor(const cv::Mat& image, int col, int threshold);
|
||||||
|
void update_lutData(int contrast);
|
||||||
|
cv::Mat lut;
|
||||||
|
};
|
||||||
|
|
|
@ -1867,6 +1867,32 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
|
||||||
m_scanparam->hardwarecaps.lowpowermode, LowPowerMode::Min_30, (BYTE)m_scanparam->hardwarecaps.lowpowermode, 4);
|
m_scanparam->hardwarecaps.lowpowermode, LowPowerMode::Min_30, (BYTE)m_scanparam->hardwarecaps.lowpowermode, 4);
|
||||||
};
|
};
|
||||||
#endif // LANXUM
|
#endif // LANXUM
|
||||||
|
|
||||||
|
#ifdef UV
|
||||||
|
m_query[(CapType)(CapTypeEx::TwEx_UVModel)] = msgSupportGetAllSetReset;
|
||||||
|
m_caps[(CapType)(CapTypeEx::TwEx_UVModel)] = [this](Msg msg, Capability& data)->Result {
|
||||||
|
switch (msg) {
|
||||||
|
case Msg::Get:
|
||||||
|
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_UVModel), { Bool(),Bool(true) }, Bool(m_scanparam->hardwarecaps.en_uv), 0);
|
||||||
|
return success();
|
||||||
|
case Msg::Reset:
|
||||||
|
m_scanparam->hardwarecaps.en_uv = false;
|
||||||
|
case Msg::GetCurrent:
|
||||||
|
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_UVModel), m_scanparam->hardwarecaps.en_uv);
|
||||||
|
return success();
|
||||||
|
case Msg::GetDefault:
|
||||||
|
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_UVModel), Bool(false));
|
||||||
|
return success();
|
||||||
|
case Msg::Set: {
|
||||||
|
auto mech = data.currentItem<Bool>();
|
||||||
|
m_scanparam->hardwarecaps.en_uv = mech;
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return capBadOperation();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
BIN
huagao/stdafx.h
BIN
huagao/stdafx.h
Binary file not shown.
Loading…
Reference in New Issue