From 6d233d10be326f0b47e8a27a52e5b3d033a167e1 Mon Sep 17 00:00:00 2001 From: masayume <1936714878@qq.com> Date: Tue, 20 Sep 2022 09:08:11 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=A9=BF=E5=AD=94UI=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.txt | 8 +- huagao/CFillHoleDlg.cpp | 142 +++++++++ huagao/CFillHoleDlg.h | 44 +++ huagao/CImageProcPage.cpp | 21 +- huagao/CImageProcPage.h | 9 + huagao/CTwainUI.cpp | 17 ++ huagao/Device/GScanO1003399.cpp | 5 + huagao/Device/IConfig.h | 2 + huagao/Device/ImageMatQueue.cpp | 55 +--- huagao/Device/PublicFunc.h | 20 ++ huagao/Device/UsbScanEx.cpp | 1 - huagao/GscanJsonConfig.cpp | 109 +++++++ .../ImageProcess/ImageApplyDiscardBlank.cpp | 271 ++++++------------ huagao/ImageProcess/ImageApplyDiscardBlank.h | 60 ++-- huagao/ImageProcess/ImageApplyOutHole.cpp | 127 ++++++-- huagao/ImageProcess/ImageApplyOutHole.h | 24 +- huagao/huagaods.cpp | 5 +- huagao/huagaotwds.rc | Bin 50828 -> 54242 bytes huagao/resource.h | Bin 19246 -> 20900 bytes huagao/stdafx.h | Bin 25538 -> 25538 bytes 20 files changed, 605 insertions(+), 315 deletions(-) create mode 100644 huagao/CFillHoleDlg.cpp create mode 100644 huagao/CFillHoleDlg.h diff --git a/changelog.txt b/changelog.txt index 726674f5..88bd9c0d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -38,7 +38,7 @@ 6.添加待纸扫描协议 7.开放G300最大尺寸和最大尺寸自动裁切 8.修复上批次图像未上传,下次扫描多上传问题 -2020年4月18日 +2022年4月18日 版本:3.3.5.8 1.折角检测默认值设置为70 2.dpi输入框添加 @@ -58,7 +58,9 @@ 16.协议问题排查 17.完成安卓3399适配 18.取消UI置顶 -2020年8月10日 +2022年8月10日 版本:3.3.5.9 1.调整usb通信,加长readbulk超时时间 - 2.屏蔽3288 自适应幅面功能 \ No newline at end of file + 2.屏蔽3288 自适应幅面功能 + 3.修复显示UI时通过协议reset停止扫描时按钮未正常复位问题 + 4.更新除穿孔以及跳过空白页算法 \ No newline at end of file diff --git a/huagao/CFillHoleDlg.cpp b/huagao/CFillHoleDlg.cpp new file mode 100644 index 00000000..6b294b51 --- /dev/null +++ b/huagao/CFillHoleDlg.cpp @@ -0,0 +1,142 @@ +// CFillHoleDlg.cpp: 实现文件 +// +#include "stdafx.h" +#include "CFillHoleDlg.h" +#include "afxdialogex.h" +#include "resource.h" + +// CFillHoleDlg 对话框 + +IMPLEMENT_DYNAMIC(CFillHoleDlg, CDialogEx) + +CFillHoleDlg::CFillHoleDlg(int up, int down, int left, int right, bool en_up, bool en_down, bool en_left, bool en_right, CWnd* pParent /*=nullptr*/) + : CDialogEx(IDD_FILLHOLE, pParent),m_up(up),m_down(down),m_left(left),m_right(right) + ,m_en_up(en_up),m_en_down(en_down),m_en_left(en_left),m_en_right(en_right) +{ + +} + +CFillHoleDlg::~CFillHoleDlg() +{ +} + +void CFillHoleDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); + DDX_Control(pDX, IDC_EDITHOLE_UP, m_Edit_Up); + DDX_Control(pDX, IDC_EDITHOLE_DOWN, m_Edit_Down); + DDX_Control(pDX, IDC_EDITHOLE_LEFT, m_Edit_Left); + DDX_Control(pDX, IDC_EDITHOLE_RIGHT, m_Edit_Right); + DDX_Control(pDX, IDC_SLDHOLE_UP, m_Slider_Up); + DDX_Control(pDX, IDC_SLDHOLE_DOWN, m_Slider_Down); + DDX_Control(pDX, IDC_SLDHOLE_LEFT, m_Slider_Left); + DDX_Control(pDX, IDC_SLDHOLE_RIGHT, m_Slider_Right); +} + +BOOL CFillHoleDlg::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + m_Edit_Up.SetSlideLink(this, IDC_SLDHOLE_UP); + m_Edit_Up.SetParams(0.0, 0.49, 10, _T("%0.2f"), 20); + m_Edit_Up.SetValue(m_en_up ? m_up/100.0f : 0.0); + + m_Edit_Down.SetSlideLink(this, IDC_SLDHOLE_DOWN); + m_Edit_Down.SetParams(0.0, 0.49, 10, _T("%0.2f"), 20); + m_Edit_Down.SetValue(m_en_down ? m_down/100.0f : 0.0); + + // setup third slider-edit box - floating point + m_Edit_Left.SetSlideLink(this, IDC_SLDHOLE_LEFT); + m_Edit_Left.SetParams(0.0, 0.49, 10, _T("%0.2f"), 20); + m_Edit_Left.SetValue(m_en_left ? m_left/100.0f : 0.0); + + m_Edit_Right.SetSlideLink(this, IDC_SLDHOLE_RIGHT); + m_Edit_Right.SetParams(0.0, 0.49, 10, _T("%0.2f"), 20); + m_Edit_Right.SetValue(m_en_right ? m_right/100.0f : 0.0); + + ((CButton*)GetDlgItem(IDC_CKHOLE_UP))->SetCheck(m_en_up); + m_Edit_Up.EnableWindow(m_en_up); + m_Slider_Up.EnableWindow(m_en_up); + + ((CButton*)GetDlgItem(IDC_CKHOLE_DOWN))->SetCheck(m_en_down); + m_Edit_Down.EnableWindow(m_en_down); + m_Slider_Down.EnableWindow(m_en_down); + + ((CButton*)GetDlgItem(IDC_CKHOLE_RIGHT))->SetCheck(m_en_right); + m_Edit_Right.EnableWindow(m_en_right); + m_Slider_Right.EnableWindow(m_en_right); + + ((CButton*)GetDlgItem(IDC_CKHOLE_LEFT))->SetCheck(m_en_left); + m_Edit_Left.EnableWindow(m_en_left); + m_Slider_Left.EnableWindow(m_en_left); + + return true; +} + +void CFillHoleDlg::OnClose(){ + CString text; + m_Edit_Up.GetWindowText(text); + m_up = _wtof(text.GetBuffer()) * 100.0; + m_Edit_Down.GetWindowText(text); + m_down = _wtof(text.GetBuffer()) * 100.0; + m_Edit_Left.GetWindowText(text); + m_left = _wtof(text.GetBuffer()) * 100.0; + m_Edit_Right.GetWindowText(text); + m_right = _wtof(text.GetBuffer()) * 100.0; + CDialogEx::OnClose(); +} + + +BEGIN_MESSAGE_MAP(CFillHoleDlg, CDialogEx) + ON_WM_CLOSE() + ON_BN_CLICKED(IDC_CKHOLE_UP, &CFillHoleDlg::OnBnClickedCkholeUp) + ON_BN_CLICKED(IDC_CKHOLE_DOWN, &CFillHoleDlg::OnBnClickedCkholeDown) + ON_BN_CLICKED(IDC_CKHOLE_LEFT, &CFillHoleDlg::OnBnClickedCkholeLeft) + ON_BN_CLICKED(IDC_CKHOLE_RIGHT, &CFillHoleDlg::OnBnClickedCkholeRight) +END_MESSAGE_MAP() + + +// CFillHoleDlg 消息处理程序 + + +void CFillHoleDlg::OnBnClickedCkholeUp() +{ + // TODO: 在此添加控件通知处理程序代码 + m_en_up = ((CButton*)GetDlgItem(IDC_CKHOLE_UP))->GetCheck(); + m_Edit_Up.EnableWindow(m_en_up); + m_Slider_Up.EnableWindow(m_en_up); + if(!m_en_up) + m_Edit_Up.SetValue(0.0); +} + + +void CFillHoleDlg::OnBnClickedCkholeDown() +{ + // TODO: 在此添加控件通知处理程序代码 + m_en_down = ((CButton*)GetDlgItem(IDC_CKHOLE_DOWN))->GetCheck(); + m_Edit_Down.EnableWindow(m_en_down); + m_Slider_Down.EnableWindow(m_en_down); + if (!m_en_down) + m_Edit_Down.SetValue(0.0); +} + + +void CFillHoleDlg::OnBnClickedCkholeLeft() +{ + // TODO: 在此添加控件通知处理程序代码 + m_en_left = ((CButton*)GetDlgItem(IDC_CKHOLE_LEFT))->GetCheck(); + m_Edit_Left.EnableWindow(m_en_left); + m_Slider_Left.EnableWindow(m_en_left); + if (!m_en_left) + m_Edit_Left.SetValue(0.0); +} + + +void CFillHoleDlg::OnBnClickedCkholeRight() +{ + // TODO: 在此添加控件通知处理程序代码 + m_en_right = ((CButton*)GetDlgItem(IDC_CKHOLE_RIGHT))->GetCheck(); + m_Edit_Right.EnableWindow(m_en_right); + m_Slider_Right.EnableWindow(m_en_right); + if (!m_en_right) + m_Edit_Right.SetValue(0.0); +} diff --git a/huagao/CFillHoleDlg.h b/huagao/CFillHoleDlg.h new file mode 100644 index 00000000..fda1c074 --- /dev/null +++ b/huagao/CFillHoleDlg.h @@ -0,0 +1,44 @@ +#pragma once +#include "Sliders.h" +#include "SmartEdit.h" +// CFillHoleDlg 对话框 + +class CFillHoleDlg : public CDialogEx +{ + DECLARE_DYNAMIC(CFillHoleDlg) +public: + CFillHoleDlg(int up, int down, int left,int right,bool en_up,bool en_down,bool en_left,bool en_right,CWnd* pParent = nullptr); // 标准构造函数 + virtual ~CFillHoleDlg(); + CSmartEdit m_Edit_Up; + CSmartEdit m_Edit_Down; + CSmartEdit m_Edit_Left; + CSmartEdit m_Edit_Right; + CLinkSlider m_Slider_Up; + CLinkSlider m_Slider_Down; + CLinkSlider m_Slider_Left; + CLinkSlider m_Slider_Right; + + bool m_en_up; + bool m_en_down; + bool m_en_left; + bool m_en_right; + int m_up; + int m_down; + int m_left; + int m_right; +// 对话框数据 +#ifdef AFX_DESIGN_TIME + enum { IDD = IDD_FILLHOLE }; +#endif + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 + virtual BOOL OnInitDialog(); + virtual void OnClose(); + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnBnClickedCkholeUp(); + afx_msg void OnBnClickedCkholeDown(); + afx_msg void OnBnClickedCkholeLeft(); + afx_msg void OnBnClickedCkholeRight(); +}; diff --git a/huagao/CImageProcPage.cpp b/huagao/CImageProcPage.cpp index f9ffd43a..bb238060 100644 --- a/huagao/CImageProcPage.cpp +++ b/huagao/CImageProcPage.cpp @@ -6,7 +6,7 @@ #include "afxdialogex.h" #include "resource.h" #include - +#include "CFillHoleDlg.h" static std::vector filters = { @@ -216,6 +216,7 @@ BEGIN_MESSAGE_MAP(CImageProcPage, CTabPageSSL) ON_BN_CLICKED(IDC_CKBACKGROUNDSMOOTH, &CImageProcPage::OnBnClickedCkbackgroundsmooth) ON_BN_CLICKED(IDC_CHMULTIPUT, &CImageProcPage::OnBnClickedChmultiput) ON_BN_CLICKED(IDC_CKMULTIOUTPUT, &CImageProcPage::OnBnClickedCkmultioutput) + ON_BN_CLICKED(IDC_BTNHOLE, &CImageProcPage::OnBnClickedBtnhole) END_MESSAGE_MAP() void CImageProcPage::EnableOutHoleCheckChanged(BOOL enable) @@ -225,6 +226,7 @@ void CImageProcPage::EnableOutHoleCheckChanged(BOOL enable) GetDlgItem(IDC_EDIT_HOLE)->EnableWindow(enable); GetDlgItem(IDC_SLDOUTHOLE)->EnableWindow(enable); GetDlgItem(IDC_EDIT_HOLE)->EnableWindow(enable); + } void CImageProcPage::SetOutHoleValue(int value) @@ -259,6 +261,7 @@ void CImageProcPage::OnCtrlChange() UpdateData(); m_edit_hole.EnableWindow(m_ckbRemoveHole); m_slider_hole.EnableWindow(m_ckbRemoveHole); + GetDlgItem(IDC_BTNHOLE)->EnableWindow(m_ckbRemoveHole); } @@ -380,3 +383,19 @@ void CImageProcPage::OnBnClickedCkmultioutput() } } } + + +void CImageProcPage::OnBnClickedBtnhole() +{ + // TODO: 在此添加控件通知处理程序代码 + CFillHoleDlg holedlg(m_fillhole_up, m_fillhole_down, m_fillhole_left, m_fillhole_right,m_en_fillhole_up,m_en_fillhole_down,m_en_fillhole_left,m_en_fillhole_right, this); + holedlg.DoModal(); + m_fillhole_up = holedlg.m_up; + m_fillhole_down = holedlg.m_down; + m_fillhole_left = holedlg.m_left; + m_fillhole_right = holedlg.m_right; + m_en_fillhole_up = holedlg.m_en_up; + m_en_fillhole_down = holedlg.m_en_down; + m_en_fillhole_left = holedlg.m_en_left; + m_en_fillhole_right = holedlg.m_en_right; +} diff --git a/huagao/CImageProcPage.h b/huagao/CImageProcPage.h index eecd65f6..ba3b851c 100644 --- a/huagao/CImageProcPage.h +++ b/huagao/CImageProcPage.h @@ -35,6 +35,14 @@ public: void EnableOutHoleCheckChanged(BOOL enable); void SetOutHoleValue(int value); void SetMultiOutputEnable(int pixtype, bool enable); + int m_fillhole_up; + int m_fillhole_down; + int m_fillhole_left; + int m_fillhole_right; + int m_en_fillhole_up; + int m_en_fillhole_down; + int m_en_fillhole_left; + int m_en_fillhole_right; int detachnoise; int indent; int noise; @@ -69,4 +77,5 @@ public: afx_msg void OnBnClickedCkbackgroundsmooth(); afx_msg void OnBnClickedChmultiput(); afx_msg void OnBnClickedCkmultioutput(); + afx_msg void OnBnClickedBtnhole(); }; diff --git a/huagao/CTwainUI.cpp b/huagao/CTwainUI.cpp index f06641d1..351752c4 100644 --- a/huagao/CTwainUI.cpp +++ b/huagao/CTwainUI.cpp @@ -283,6 +283,15 @@ void CTwainUI::UpdateUI() m_pageImageProc->m_ckbRemoveHole = settings->fillhole.is_fillhole==TRUE?TRUE:FALSE;//除穿孔可用性 m_pageImageProc->m_edit_hole.SetValue(settings->fillhole.fillholeratio/ 100.0);//穿孔搜索范围比例系数 m_pageImageProc->m_edit_hole.EnableWindow(settings->fillhole.is_fillhole == TRUE ? TRUE : FALSE); + m_pageImageProc->GetDlgItem(IDC_BTNHOLE)->EnableWindow(settings->fillhole.is_fillhole == TRUE ? TRUE : FALSE); + m_pageImageProc->m_fillhole_up = settings->fillholeratio_up; + m_pageImageProc->m_fillhole_down = settings->fillholeratio_down; + m_pageImageProc->m_fillhole_left = settings->fillholeratio_left; + m_pageImageProc->m_fillhole_right = settings->fillholeratio_right; + m_pageImageProc->m_en_fillhole_up = settings->en_fillholeratio_up; + m_pageImageProc->m_en_fillhole_down = settings->en_fillholeratio_down; + m_pageImageProc->m_en_fillhole_left = settings->en_fillholeratio_left; + m_pageImageProc->m_en_fillhole_right = settings->en_fillholeratio_right; m_pageImageProc->GetDlgItem(IDC_SLDOUTHOLE)->EnableWindow(m_pageImageProc->m_ckbRemoveHole); m_pageImageProc->m_ckbfadeback = settings->fadeback; ((CButton*)m_pageImageProc->GetDlgItem(IDC_CKBACKGROUNDSMOOTH))->SetCheck(m_pageImageProc->m_ckbfadeback); @@ -652,6 +661,14 @@ void CTwainUI::UpDateScanParam(PCONFIGPARAMS configItem, bool updateDs) settings->fadeback_range = m_pageImageProc->m_slider_faderange.m_iPosition; settings->fillhole.is_fillhole = configItem->EnOutHole; settings->fillhole.fillholeratio = configItem->OutHoleRatio; + settings->fillholeratio_up = m_pageImageProc->m_fillhole_up; + settings->fillholeratio_down = m_pageImageProc->m_fillhole_down; + settings->fillholeratio_left = m_pageImageProc->m_fillhole_left; + settings->fillholeratio_right = m_pageImageProc->m_fillhole_right; + settings->en_fillholeratio_up = m_pageImageProc->m_en_fillhole_up; + settings->en_fillholeratio_down = m_pageImageProc->m_en_fillhole_down; + settings->en_fillholeratio_left = m_pageImageProc->m_en_fillhole_left; + settings->en_fillholeratio_right = m_pageImageProc->m_en_fillhole_right; settings->multi_output_red = configItem->EnMultiOutPutR; settings->en_multi_output = ((CButton*)m_pageImageProc->GetDlgItem(IDC_CHMULTIPUT))->GetCheck(); settings->multioutput = ((CComboBox*)m_pageImageProc->GetDlgItem(IDC_CMBMULTIOUT))->GetCurSel(); diff --git a/huagao/Device/GScanO1003399.cpp b/huagao/Device/GScanO1003399.cpp index 2ce64a70..de4be307 100644 --- a/huagao/Device/GScanO1003399.cpp +++ b/huagao/Device/GScanO1003399.cpp @@ -356,6 +356,11 @@ void GScanO1003399::config_params(GScanCap& param) param39.fadeback = param.fadeback; param39.fadebackrange = param.fadeback_range; param39.dogeardistabce = param.dogeardistance; + param39.fillholeratio_up = param.fillholeratio_up; + param39.fillholeratio_down = param.fillholeratio_down; + param39.fillholeratio_left = param.fillholeratio_left; + param39.fillholeratio_right = param.fillholeratio_right; + param39.fillhole.fillholeratio = std::max(std::max(std::max(param.fillholeratio_down, param.fillholeratio_up), std::max(param.fillholeratio_left, param.fillholeratio_right)),1); m_usb->write_bulk(¶m39, sizeof(param39)); m_param .resolution_native = param.resolution_dst >= 500.0f ? 300.0f : 200.0f; diff --git a/huagao/Device/IConfig.h b/huagao/Device/IConfig.h index 1dd4a7a9..0bbbdb25 100644 --- a/huagao/Device/IConfig.h +++ b/huagao/Device/IConfig.h @@ -197,6 +197,8 @@ enum Scanner_Reg_Defs SR_SET_AUTOMATICCONTROLFEEDMODE_ENABLE, SR_GET_AUTOMATICCONTROLFEEDMODE_THRESHOLD, SR_SET_AUTOMATICCONTROLFEEDMODE_THRESHOLD, + SR_GET_TRAYPOSITION, + SR_SET_TRAYPOSITION, SR_GET_CUO_ERROR = 0x50, SR_GET_DOU_ERROR, SR_GET_JAM_ERROR, diff --git a/huagao/Device/ImageMatQueue.cpp b/huagao/Device/ImageMatQueue.cpp index 35d572e2..7a8e3988 100644 --- a/huagao/Device/ImageMatQueue.cpp +++ b/huagao/Device/ImageMatQueue.cpp @@ -165,57 +165,18 @@ void ImageMatQueue::setparam(const GScanCap& param) m_iaList.clear(); - if (scanParam.fillhole.is_fillhole && scanParam.resolution_dst < 500) { - float ratio = scanParam.fillhole.fillholeratio / 100.0; - m_iaList.push_back(shared_ptr(new CImageApplyOutHole(25, ratio, 40))); + if (scanParam.fillhole.is_fillhole) { + m_iaList.push_back(shared_ptr(new CImageApplyOutHole(25, + {scanParam.fillholeratio_up/100.0f,scanParam.fillholeratio_down/100.0f,scanParam.fillholeratio_left/100.0f,scanParam.fillholeratio_right/100.0f}, + 40))); } //确保能够获取正反两面图 if (param.is_autodiscradblank_normal || param.is_autodiscradblank_vince) { - //m_iaList.push_back(shared_ptr(new CImageApplyDiscardBlank())); - CImageApplyDiscardBlank* disBlank = new CImageApplyDiscardBlank(); - //跳过空白页阈值 - int area = 200; - int intensity = 15; - int maxHeight = 3307;//A3 height - //页面最大高度获取 - if (param.papertype == TwSS::MaxSize) - maxHeight = 6614; - //阈值参数赋值 - 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; - } - //判断是否为跳过空白页发票 - if (param.is_autodiscradblank_vince) { - area *= 1.5; - intensity *= 1.5; - } - //设置参数阈值 - disBlank->setMinArea(area); - disBlank->setIntensity(intensity); - m_iaList.push_back(shared_ptr(disBlank)); - //m_iaList.push_back(shared_ptr(new CImageApplyDiscardBlank(param.areanum,param.devnmax))); + if (param.is_autodiscradblank_normal) + m_iaList.push_back(shared_ptr(new CImageApplyDiscardBlank(40, 30, param.discardblank_percent, 200))); + else + m_iaList.push_back(shared_ptr(new CImageApplyDiscardBlank(40, 30, param.discardblank_percent * 15 / 10, 150))); } { diff --git a/huagao/Device/PublicFunc.h b/huagao/Device/PublicFunc.h index 9f85b24e..6a2d0b7d 100644 --- a/huagao/Device/PublicFunc.h +++ b/huagao/Device/PublicFunc.h @@ -67,6 +67,14 @@ const std::string EN_MULTIOUT = "bMultiOut"; const std::string MULTIOUTTYPE = "iMultiOut"; const std::string OUTHOLE = "bOutHole"; const std::string OUTHOLERATIO = "iOutHoleRatio"; +const std::string OUTHOLERATIOUP = "iOutHoleRatioup"; +const std::string OUTHOLERATIODOWN = "iOutHoleRatiodown"; +const std::string OUTHOLERATIOLEFT = "iOutHoleRatioleft"; +const std::string OUTHOLERATIORIGHT = "iOutHoleRatioright"; +const std::string EN_OUTHOLERATIOUP = "bOutHoleRatioup"; +const std::string EN_OUTHOLERATIODOWN = "bOutHoleRatiodown"; +const std::string EN_OUTHOLERATIOLEFT = "bOutHoleRatioleft"; +const std::string EN_OUTHOLERATIORIGHT = "bOutHoleRatioright"; const std::string DETACHNOISE = "detachnoise"; const std::string DETACHNOISEVALUE = "detachnoisevalue"; const std::string FADEBACK = "bfadeback"; @@ -282,6 +290,14 @@ struct GScanCap FillHole fillhole; DetachNoise detachnoise; /**< ڰ׽*/ uint8_t is_autotext; /**< Զıʶ*/ + int fillholeratio_up; + int fillholeratio_down; + int fillholeratio_left; + int fillholeratio_right; + bool en_fillholeratio_up; + bool en_fillholeratio_down; + bool en_fillholeratio_left; + bool en_fillholeratio_right; std::string Caption; std::string SavePath; }; @@ -360,6 +376,10 @@ struct GScanCap_3399 bool fadeback; /**< ɫ>*/ int fadebackrange; /**< ɫΧ>*/ bool isuploadexceptionimage; /**< Ƿϴ˫ű쳣ͼ>*/ + int fillholeratio_up; /**< ƳҷΧ>*/ + int fillholeratio_down; + int fillholeratio_left; + int fillholeratio_right; uint32_t reserve[1024]; /**< Ԥ4096ֽЭչ*/ }; diff --git a/huagao/Device/UsbScanEx.cpp b/huagao/Device/UsbScanEx.cpp index 340b781b..a4057dbe 100644 --- a/huagao/Device/UsbScanEx.cpp +++ b/huagao/Device/UsbScanEx.cpp @@ -199,7 +199,6 @@ int UsbScanEx::control_msg(int rtype, int req, int value, int index, int len, vo LPOVERLAPPED lp_overlap = ov + CTRL_IN_OUT; b_ret = DeviceIoControl(m_h_dev, IOCTL_SEND_USB_REQUEST, &irp, sizeof(irp), data, len, &dw_ret, NULL); - FileTools::writelog(log_ERROR, " USB control_msg ret = " + std::to_string(b_ret)); //if (!b_ret) // b_ret = WaitForSingleObject(lp_overlap->hEvent, timeout) == WAIT_OBJECT_0; diff --git a/huagao/GscanJsonConfig.cpp b/huagao/GscanJsonConfig.cpp index 6b9b517f..a8c6b18e 100644 --- a/huagao/GscanJsonConfig.cpp +++ b/huagao/GscanJsonConfig.cpp @@ -126,6 +126,15 @@ void GscanJsonConfig::SaveGscanCapConfig(const GScanCap & gcap, const std::strin outJson["Config"].Add(MULTIOUTTYPE, (int)(gcap.multioutput)); outJson["Config"].Add(OUTHOLE, (bool)(gcap.fillhole.is_fillhole), false); outJson["Config"].Add(OUTHOLERATIO, (int)(gcap.fillhole.fillholeratio)); + outJson["Config"].Add(OUTHOLERATIOUP, (int)(gcap.fillholeratio_up)); + outJson["Config"].Add(OUTHOLERATIODOWN, (int)(gcap.fillholeratio_down)); + outJson["Config"].Add(OUTHOLERATIOLEFT, (int)(gcap.fillholeratio_left)); + outJson["Config"].Add(OUTHOLERATIORIGHT, (int)(gcap.fillholeratio_right)); + outJson["Config"].Add(EN_OUTHOLERATIOUP, (bool)(gcap.fillholeratio_up),true); + outJson["Config"].Add(EN_OUTHOLERATIODOWN, (bool)(gcap.fillholeratio_down), true); + outJson["Config"].Add(EN_OUTHOLERATIOLEFT, (bool)(gcap.fillholeratio_left), true); + outJson["Config"].Add(EN_OUTHOLERATIORIGHT, (bool)(gcap.fillholeratio_right), true); + outJson["Config"].Add(DETACHNOISE, (bool)(gcap.detachnoise.is_detachnoise), false); outJson["Config"].Add(DETACHNOISEVALUE, (int)(gcap.detachnoise.detachnoise)); outJson["Config"].Add(FADEBACK, (bool)(gcap.fadeback), false); @@ -198,6 +207,14 @@ void GscanJsonConfig::WriteJsonArrayToFile(std::vector cfgArray, const root["Config"].AddEmptySubArray(MULTIOUTPUT); root["Config"].AddEmptySubArray(OUTHOLE); root["Config"].AddEmptySubArray(OUTHOLERATIO); + root["Config"].AddEmptySubArray(OUTHOLERATIOUP); + root["Config"].AddEmptySubArray(OUTHOLERATIODOWN); + root["Config"].AddEmptySubArray(OUTHOLERATIOLEFT); + root["Config"].AddEmptySubArray(OUTHOLERATIORIGHT); + root["Config"].AddEmptySubArray(EN_OUTHOLERATIOUP); + root["Config"].AddEmptySubArray(EN_OUTHOLERATIODOWN); + root["Config"].AddEmptySubArray(EN_OUTHOLERATIOLEFT); + root["Config"].AddEmptySubArray(EN_OUTHOLERATIORIGHT); root["Config"].AddEmptySubArray(HSVCORRECT); /*< feeder settings*/ @@ -258,6 +275,15 @@ void GscanJsonConfig::WriteJsonArrayToFile(std::vector cfgArray, const root["Config"][MULTIOUTTYPE].Add((int)cfgArray[i].multioutput); root["Config"][OUTHOLE].Add(i, (bool)cfgArray[i].fillhole.is_fillhole); root["Config"][OUTHOLERATIO].Add((int)cfgArray[i].fillhole.fillholeratio); + root["Config"][OUTHOLERATIOUP].Add ((int)(cfgArray[i].fillholeratio_up)); + root["Config"][OUTHOLERATIODOWN].Add((int)(cfgArray[i].fillholeratio_down)); + root["Config"][OUTHOLERATIOLEFT].Add((int)(cfgArray[i].fillholeratio_left)); + root["Config"][OUTHOLERATIORIGHT].Add((int)(cfgArray[i].fillholeratio_right)); + root["Config"][EN_OUTHOLERATIOUP].Add((int)(cfgArray[i].en_fillholeratio_up)); + root["Config"][EN_OUTHOLERATIODOWN].Add((int)(cfgArray[i].en_fillholeratio_down)); + root["Config"][EN_OUTHOLERATIOLEFT].Add((int)(cfgArray[i].en_fillholeratio_left)); + root["Config"][EN_OUTHOLERATIORIGHT].Add((int)(cfgArray[i].en_fillholeratio_right)); + root["Config"][DETACHNOISE].Add(i, (bool)cfgArray[i].detachnoise.is_detachnoise); root["Config"][DETACHNOISEVALUE].Add((int)cfgArray[i].detachnoise.detachnoise); root["Config"][FADEBACK].Add(i, (bool)cfgArray[i].fadeback); @@ -451,6 +477,24 @@ std::vector GscanJsonConfig::parseJsonFromString(const std::string str root["Config"].Get(OUTHOLE, itmOutHole); neb::CJsonObject itmOutHoleRatio; root["Config"].Get(OUTHOLERATIO, itmOutHoleRatio); + + neb::CJsonObject itmOutHoleRatioUp; + root["Config"].Get(OUTHOLERATIOUP, itmOutHoleRatioUp); + neb::CJsonObject itmOutHoleRatioDown; + root["Config"].Get(OUTHOLERATIODOWN, itmOutHoleRatioDown); + neb::CJsonObject itmOutHoleRatioLeft; + root["Config"].Get(OUTHOLERATIOLEFT, itmOutHoleRatioLeft); + neb::CJsonObject itmOutHoleRatioRight; + root["Config"].Get(OUTHOLERATIORIGHT, itmOutHoleRatioRight); + neb::CJsonObject itmEnOutHoleRatioUp; + root["Config"].Get(EN_OUTHOLERATIOUP, itmEnOutHoleRatioUp); + neb::CJsonObject itmEnOutHoleRatioDown; + root["Config"].Get(EN_OUTHOLERATIODOWN, itmEnOutHoleRatioDown); + neb::CJsonObject itmEnOutHoleRatioLeft; + root["Config"].Get(EN_OUTHOLERATIOLEFT, itmEnOutHoleRatioLeft); + neb::CJsonObject itmENOutHoleRatioRight; + root["Config"].Get(EN_OUTHOLERATIORIGHT, itmENOutHoleRatioRight); + neb::CJsonObject itmDetachNoise; root["Config"].Get(DETACHNOISE, itmDetachNoise); neb::CJsonObject itmDetachNoiseValue; @@ -583,6 +627,23 @@ std::vector GscanJsonConfig::parseJsonFromString(const std::string str cfp.fillhole.is_fillhole = b_value ? 1 : 0; itmOutHoleRatio.Get(i, i_value); cfp.fillhole.fillholeratio = i_value; + itmOutHoleRatioUp.Get(i, i_value); + cfp.fillholeratio_up = i_value; + itmOutHoleRatioDown.Get(i, i_value); + cfp.fillholeratio_down = i_value; + itmOutHoleRatioLeft.Get(i, i_value); + cfp.fillholeratio_left = i_value; + itmOutHoleRatioRight.Get(i, i_value); + cfp.fillholeratio_right = i_value; + itmEnOutHoleRatioUp.Get(i, b_value); + cfp.en_fillholeratio_up = b_value ? 1 : 0; + itmEnOutHoleRatioDown.Get(i, b_value); + cfp.en_fillholeratio_down = b_value ? 1 : 0; + itmEnOutHoleRatioLeft.Get(i, b_value); + cfp.en_fillholeratio_left = b_value ? 1 : 0; + itmENOutHoleRatioRight.Get(i, b_value); + cfp.en_fillholeratio_right = b_value ? 1 : 0; + itmDetachNoise.Get(i, b_value); cfp.detachnoise.is_detachnoise = b_value ? 1 : 0; itmDetachNoiseValue.Get(i, i_value); @@ -714,6 +775,22 @@ std::vector GscanJsonConfig::parseJsonFromString(const std::string str cfp.fillhole.is_fillhole = bvalue?1:0; root["Config"].Get(OUTHOLERATIO, index); cfp.fillhole.fillholeratio = index; + root["Config"].Get(OUTHOLERATIOUP, index); + cfp.fillholeratio_up = index; + root["Config"].Get(OUTHOLERATIODOWN, index); + cfp.fillholeratio_down = index; + root["Config"].Get(OUTHOLERATIOLEFT, index); + cfp.fillholeratio_left = index; + root["Config"].Get(OUTHOLERATIORIGHT, index); + cfp.fillholeratio_right = index; + root["Config"].Get(EN_OUTHOLERATIOUP, bvalue); + cfp.en_fillholeratio_up = bvalue ? 1 : 0; + root["Config"].Get(EN_OUTHOLERATIODOWN, bvalue); + cfp.en_fillholeratio_down = bvalue ? 1 : 0; + root["Config"].Get(EN_OUTHOLERATIOLEFT, bvalue); + cfp.en_fillholeratio_left = bvalue ? 1 : 0; + root["Config"].Get(EN_OUTHOLERATIORIGHT, bvalue); + cfp.en_fillholeratio_right = bvalue ? 1 : 0; root["Config"].Get(DETACHNOISE, bvalue); cfp.detachnoise.is_detachnoise = bvalue ? 1 : 0; root["Config"].Get(DETACHNOISEVALUE, index); @@ -832,6 +909,14 @@ json GscanJsonConfig::GscancapToJson(GScanCap& cap) js[CONFIG][MULTIOUTTYPE] = cap.multioutput; js[CONFIG][OUTHOLE] = cap.fillhole.is_fillhole; js[CONFIG][OUTHOLERATIO] = cap.fillhole.fillholeratio; + js[CONFIG][OUTHOLERATIOUP] = cap.fillholeratio_up; + js[CONFIG][OUTHOLERATIODOWN] = cap.fillholeratio_down; + js[CONFIG][OUTHOLERATIOLEFT] = cap.fillholeratio_left; + js[CONFIG][OUTHOLERATIORIGHT] = cap.fillholeratio_right; + js[CONFIG][EN_OUTHOLERATIOUP] = cap.en_fillholeratio_up; + js[CONFIG][EN_OUTHOLERATIODOWN] = cap.en_fillholeratio_down; + js[CONFIG][EN_OUTHOLERATIOLEFT] = cap.en_fillholeratio_left; + js[CONFIG][EN_OUTHOLERATIORIGHT] = cap.en_fillholeratio_right; js[CONFIG][HSVCORRECT] = cap.hsvcorrect; js[CONFIG][ULTRADETECT] = cap.hardwarecaps.en_doublefeed; js[CONFIG][BINDINGDETECT] = cap.hardwarecaps.en_stapledetect; @@ -900,6 +985,14 @@ GScanCap GscanJsonConfig::JsonToGscancap(json& js) cap.multioutput = json_cast(js[CONFIG][MULTIOUTTYPE]).to_int(); cap.fillhole.is_fillhole = json_cast(js[CONFIG][OUTHOLE]).to_int(); cap.fillhole.fillholeratio = json_cast(js[CONFIG][OUTHOLERATIO]).to_int(); + cap.fillholeratio_up = json_cast(js[CONFIG][OUTHOLERATIOUP]).to_int(); + cap.fillholeratio_down = json_cast(js[CONFIG][OUTHOLERATIODOWN]).to_int(); + cap.fillholeratio_left = json_cast(js[CONFIG][OUTHOLERATIOLEFT]).to_int(); + cap.fillholeratio_right = json_cast(js[CONFIG][OUTHOLERATIORIGHT]).to_int(); + cap.en_fillholeratio_up = json_cast(js[CONFIG][EN_OUTHOLERATIOUP]).to_bool(); + cap.en_fillholeratio_down = json_cast(js[CONFIG][EN_OUTHOLERATIODOWN]).to_bool(); + cap.en_fillholeratio_left = json_cast(js[CONFIG][EN_OUTHOLERATIOLEFT]).to_bool(); + cap.en_fillholeratio_right = json_cast(js[CONFIG][EN_OUTHOLERATIORIGHT]).to_bool(); cap.hsvcorrect = json_cast(js[CONFIG][HSVCORRECT]).to_int(); cap.hardwarecaps.en_doublefeed = json_cast(js[CONFIG][ULTRADETECT]).to_int(); cap.hardwarecaps.en_stapledetect = json_cast(js[CONFIG][BINDINGDETECT]).to_int(); @@ -963,6 +1056,14 @@ json GscanJsonConfig::GetDefaultJson() "iMultiOut": 0 , "bOutHole": false , "iOutHoleRatio": 10 , + "iOutHoleRatioup": 10 , + "iOutHoleRatiodown": 10 , + "iOutHoleRatioleft": 10 , + "iOutHoleRatioright": 10 , + "bOutHoleRatioup": true , + "bOutHoleRatiodown": true , + "bOutHoleRatioleft": true , + "bOutHoleRatioright": true , "bHsvCorrect": false , "bUltrasonicDetect": true , "bBindingDetect": false , @@ -1023,6 +1124,14 @@ json GscanJsonConfig::GetDefaultJson() "iMultiOut": 0 , "bOutHole": false , "iOutHoleRatio": 10 , + "iOutHoleRatioup": 10 , + "iOutHoleRatiodown": 10 , + "iOutHoleRatioleft": 10 , + "iOutHoleRatioright": 10 , + "bOutHoleRatioup": true , + "bOutHoleRatiodown": true , + "bOutHoleRatioleft": true , + "bOutHoleRatioright": true , "bHsvCorrect": false , "bUltrasonicDetect": true , "bBindingDetect": false , diff --git a/huagao/ImageProcess/ImageApplyDiscardBlank.cpp b/huagao/ImageProcess/ImageApplyDiscardBlank.cpp index ef23b506..50feb4df 100644 --- a/huagao/ImageProcess/ImageApplyDiscardBlank.cpp +++ b/huagao/ImageProcess/ImageApplyDiscardBlank.cpp @@ -1,187 +1,22 @@ -#include "ImageApplyDiscardBlank.h" +#include "ImageApplyDiscardBlank.h" #include "ImageProcess_Public.h" -CImageApplyDiscardBlank::CImageApplyDiscardBlank() - : m_res(false) - , m_dSize(20) - , m_devTh(15, 15, 15, 15) -{ -} - -CImageApplyDiscardBlank::CImageApplyDiscardBlank(int blockSize, int devTh) - : m_res(false) - , m_dSize(blockSize) +CImageApplyDiscardBlank::CImageApplyDiscardBlank(double threshold, int edge, double devTh, double meanTh) + : m_threshold(threshold) + , m_edge(edge) , m_devTh(devTh) + , m_meanTh(meanTh) { } -CImageApplyDiscardBlank::CImageApplyDiscardBlank(bool isnormal) - : m_res(false) - , m_isNormalDiscard(isnormal) -{ - m_dSize = m_isNormalDiscard ? 200 : 300; - m_devTh = m_isNormalDiscard ? cv::Scalar::all(8) : cv::Scalar::all(20); -} - CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void) { } -int CImageApplyDiscardBlank::processRectR(const cv::Mat& image, cv::RotatedRect& rotatedRect, std::vector& maxContour, - double scale, double thresh, int blobAreaSize) -{ - cv::Mat gray; - int blockCount = 0; - if (image.channels() == 3) - if (scale != 1.0f) - { - cv::Size ResImgSiz = cv::Size(image.cols * scale, image.rows * scale); - resize(image, gray, cv::Size(), scale, scale, 0); - cvtColor(gray, gray, CV_BGR2GRAY); - } - else - cvtColor(image, gray, CV_BGR2GRAY); - else - if (scale != 1.0f) - resize(image, gray, cv::Size(), scale, scale, 0); - else - gray = image; - - cv::Mat threshold_img; - threshold(gray, threshold_img, thresh, 255.0, CV_THRESH_BINARY); - std::vector> contours; - std::vector h1; - hg::findContours(threshold_img, contours, h1, CV_CHAIN_APPROX_SIMPLE); - threshold_img.release(); - - if (contours.size() == 0) - return blockCount; - - std::vector list_com; - for (int i = 0; i < contours.size(); i++) - { - double area = cv::contourArea(contours[i]); - if (area > blobAreaSize) - { - blockCount++; - for (int j = 0; j < contours[i].size(); j++) - list_com.push_back(contours[i][j]); - } - } - - if (list_com.size() == 0) - return blockCount; - - rotatedRect = cv::minAreaRect(list_com); - rotatedRect.center.x /= (float)scale; - rotatedRect.center.y /= (float)scale; - rotatedRect.size.width /= (float)scale; - rotatedRect.size.height /= (float)scale; - - if (rotatedRect.angle < -45.0f) - { - rotatedRect.angle += 90.0f; - float l_temp = rotatedRect.size.width; - rotatedRect.size.width = rotatedRect.size.height; - rotatedRect.size.height = l_temp; - } - if (rotatedRect.angle > 45.0f) - { - rotatedRect.angle -= 90.0f; - float l_temp = rotatedRect.size.width; - rotatedRect.size.width = rotatedRect.size.height; - rotatedRect.size.height = l_temp; - } - - std::vector hull(list_com.size()); - cv::convexHull(list_com, hull); - - for (int i = 0; i < hull.size(); i++) - { - cv::Point temp = list_com[hull[i]]; - int x = (int)(temp.x / scale); - int y = (int)(temp.y / scale); - maxContour.push_back(cv::Point(x, y)); - } - - return blockCount; -} - -bool CImageApplyDiscardBlank::scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2) -{ - for (int i = 0; i < 3; i++) - if (val1[i] > val2[i]) - return false; - return true; -} - -void CImageApplyDiscardBlank::setIntensity(int val) -{ - val = cv::max(cv::min(100, val), 2); - m_devTh = cv::Scalar::all(val); -} - -cv::Mat CImageApplyDiscardBlank::getRoiMat(const cv::Mat& image) -{ - int gap = 100; - cv::RotatedRect rect; - std::vector contour; - double scale = 0.25; - double thresh = 50; - int blobSize = 200; - processRectR(image, rect, contour, scale, thresh, blobSize); - cv::Rect rect2 = rect.boundingRect(); - cv::Rect inRect = rect2 & cv::Rect(0, 0, image.cols, image.rows); - gap = cv::max(inRect.width - rect.size.width, inRect.height - rect.size.height) + 100; - inRect = cv::Rect(inRect.x + gap, inRect.y + gap, inRect.width - gap * 2, inRect.height - gap * 2); - - if (inRect.width <= 0 || inRect.height <= 0) - return cv::Mat(); - return image(inRect); -} - void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side) { -#ifdef LOG - FileTools::write_log("imgprc.txt", "enter CImageApplyDiscardBlank apply"); -#endif // LOG - - if (pDib.empty()) - { -#ifdef LOG - FileTools::write_log("imgprc.txt", "exit CImageApplyDiscardBlank apply"); -#endif // LOG - return; - } - - cv::Scalar mean; - cv::Scalar dev; - cv::Mat image = getRoiMat(pDib); - cv::Rect rect; - cv::Rect imRect(0, 0, image.cols, image.rows); - for (int i = 0; i < image.cols; i += m_dSize) - for (int j = 0; j < image.rows; j += m_dSize) - { - rect = cv::Rect(i, j, m_dSize, m_dSize) & imRect; - if (rect != cv::Rect()) - { - cv::meanStdDev(image(rect), mean, dev); - if (!scalar_LE(dev, m_devTh)) - { - m_res = false; -#ifdef LOG - FileTools::write_log("imgprc.txt", "exit CImageApplyDiscardBlank apply"); -#endif // LOG - return; - } - } - } - m_res = true; - if (m_res) + if (apply(pDib, m_threshold, m_edge, m_devTh, m_meanTh)) pDib.release(); -#ifdef LOG - FileTools::write_log("imgprc.txt", "exit CImageApplyDiscardBlank apply"); -#endif // LOG } void CImageApplyDiscardBlank::apply(std::vector& mats, bool isTwoSide) @@ -197,30 +32,86 @@ void CImageApplyDiscardBlank::apply(std::vector& mats, bool isTwoSide) } } -bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, int blockSize, int devTh) +bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2) +{ + for (int i = 0; i < 3; i++) + if (val1[i] > val2[i]) + return false; + return true; +} + +bool maxMinCompare(const cv::Mat& img, const cv::Mat& mask, double devTh, double meanTh) +{ + double min, max; + cv::minMaxLoc(img, &min, &max, 0, 0, mask); + if (cv::mean(img, mask)[0] < meanTh) + return false; + return (max - min) < devTh; +} + +bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int edge, double devTh, double meanTh) { if (pDib.empty()) return true; - cv::Scalar mean; - cv::Scalar dev; - cv::Scalar s_devTh = cv::Scalar::all(devTh); - cv::Mat image = getRoiMat(pDib); - if (image.empty()) - return false; - cv::Rect rect; - cv::Rect imRect(0, 0, image.cols, image.rows); - for (int i = 0; i < image.cols; i += blockSize) - for (int j = 0; j < image.rows; j += blockSize) + cv::Mat img_resize; + cv::resize(pDib, img_resize, cv::Size(), 0.2, 0.2); + + cv::Mat threshold_img; + if (img_resize.channels() == 3) + cv::cvtColor(img_resize, threshold_img, cv::COLOR_BGR2GRAY); + cv::threshold(img_resize.channels() == 3 ? threshold_img : img_resize, threshold_img, threshold, 255, cv::THRESH_BINARY); + + std::vector> contours; + std::vector h1; + hg::findContours(threshold_img, contours, h1, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); + + std::vector contour; + for (const std::vector& sub : contours) + for (const cv::Point& p : sub) + contour.push_back(p); + + cv::RotatedRect rect = hg::getBoundingRect(contour); + rect.size = cv::Size2f(rect.size.width - edge / 2.5, rect.size.height - edge / 2.5); + cv::Point2f box[4]; + rect.points(box); + contour.clear(); + contours.clear(); + + for (size_t i = 0; i < 4; i++) + contour.push_back(box[i]); + contours.push_back(contour); + cv::Mat mask = cv::Mat::zeros(img_resize.size(), CV_8UC1); + hg::fillPolys(mask, contours, cv::Scalar::all(255)); + int kSize = (devTh / 20) / 2 * 2 + 1; + if (kSize > 1) + cv::blur(img_resize, img_resize, cv::Size(kSize, kSize)); + + bool b = true; + if (img_resize.channels() == 3) + { + cv::Mat bgr[3]; + cv::split(img_resize, bgr); + for (size_t i = 0; i < 3; i++) { - rect = cv::Rect(i, j, blockSize, blockSize) & imRect; - if (rect != cv::Rect()) - { - cv::meanStdDev(image(rect), mean, dev); - if (!scalar_LE(dev, s_devTh)) - return false; - } + b &= maxMinCompare(bgr[i], mask, devTh, meanTh); + if (!b) break; } - return true; + } + else + b &= maxMinCompare(img_resize, mask, devTh, meanTh); + /* + if (b) + { + cv::imwrite("空白页/img1/" + std::to_string(index) + ".bmp", img_resize); + cv::imwrite("空白页/mask1/" + std::to_string(index) + ".bmp", mask); + } + else + { + cv::imwrite("空白页/img2/" + std::to_string(index) + ".bmp", img_resize); + cv::imwrite("空白页/mask2/" + std::to_string(index) + ".bmp", mask); + }*/ + + return b; } diff --git a/huagao/ImageProcess/ImageApplyDiscardBlank.h b/huagao/ImageProcess/ImageApplyDiscardBlank.h index da86352e..8d6d2267 100644 --- a/huagao/ImageProcess/ImageApplyDiscardBlank.h +++ b/huagao/ImageProcess/ImageApplyDiscardBlank.h @@ -1,17 +1,23 @@ -/* +/* * ==================================================== - * ܣհҳʶ - * ߣά - * ʱ䣺2020/4/21 - * ޸ʱ䣺2020/4/21 v1.0 - 2020/8/12 v1.1 setIntensitysetMinAreaȡisNormalʶλsetIntensity÷Χ[2, 20][1, 100] - 2020/8/25 v1.1.1 ֽż100ص20 - 2020/10/16 v1.2 ½ӿڣܹЧжͼƬǷΪհҳ - 2020/10/19 v1.2.1 ޸̬հҳжʶеBUG - 2021/04/13 v1.3.0 ӱ׼/Ʊݱʶλ - 2021/08/12 v1.3.1 ӷֹͬopencv汾¼ڲĴ롣 - * 汾ţv1.3.1 + * 功能:空白页识别。 + * 作者:刘丁维 + * 生成时间:2020/4/21 + * 最近修改时间:2020/4/21 v1.0 + 2020/8/12 v1.1 开放setIntensity和setMinArea;取消isNormal标识位;扩大setIntensity的设置范围,从[2, 20]扩大到[1, 100] + 2020/8/25 v1.1.1 纸张检测缩进,从100像素调整到20像素 + 2020/10/16 v1.2 添加新接口,能够高效便捷判断图片是否为空白页 + 2020/10/19 v1.2.1 修复静态空白页判断识别误判的BUG + 2021/04/13 v1.3.0 增加标准/票据标识位 + 2021/08/12 v1.3.1 添加防止不同opencv版本导致计算结果存在差异的代码。 + 2021/12/14 v1.3.2 重构算法。 + 2021/12/15 v1.3.3 微调参数。 + 2021/12/17 v1.3.4 增加背景色接口,实现对纯色纸张的空白页判定 + 2022/09/07 v1.3.5 修复部分参数传递的BUG + 2022/09/19 v1.4 增加模糊处理,提高空白页的过滤能力 + 2022/09/19 v1.4.1 调整模糊处理步骤 + * 版本号:v1.4.1 * ==================================================== */ @@ -24,14 +30,8 @@ class CImageApplyDiscardBlank : public CImageApply { public: - CImageApplyDiscardBlank(); - CImageApplyDiscardBlank(int blockSize, int devTh); - - /* - * isnormal [in]:true׼ģʽfalseΪƱݸдֽģʽ - * */ - CImageApplyDiscardBlank(bool isnormal); + CImageApplyDiscardBlank(double threshold = 40, int edge = 150, double devTh = 50, double meanTh = 200); virtual ~CImageApplyDiscardBlank(void); @@ -39,25 +39,13 @@ public: virtual void apply(std::vector& mats, bool isTwoSide); - void setIntensity(int val); - - void setMinArea(int val) { m_dSize = val; } - - static bool apply(const cv::Mat& pDib, int blockSize = 200, int devTh = 15); + static bool apply(const cv::Mat& pDib, double threshold = 40, int edge = 150, double devTh = 50, double meanTh = 200); private: - - static int processRectR(const cv::Mat& image, cv::RotatedRect& rotatedRect, std::vector& maxContour, - double scale, double thresh, int blobAreaSize); - - static bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2); - - static cv::Mat getRoiMat(const cv::Mat& pDib); -private: - bool m_res; - bool m_isNormalDiscard; - int m_dSize; - cv::Scalar m_devTh; + double m_threshold; + int m_edge; + double m_devTh; + double m_meanTh; }; #endif // !IMAGE_APPLY_DISCARD_BLANK_H \ No newline at end of file diff --git a/huagao/ImageProcess/ImageApplyOutHole.cpp b/huagao/ImageProcess/ImageApplyOutHole.cpp index 85c7b9cc..e34a8f8d 100644 --- a/huagao/ImageProcess/ImageApplyOutHole.cpp +++ b/huagao/ImageProcess/ImageApplyOutHole.cpp @@ -1,5 +1,6 @@ #include "ImageApplyOutHole.h" #include "ImageProcess_Public.h" +//#include #ifdef LOG #include "Device/filetools.h" @@ -7,13 +8,13 @@ CImageApplyOutHole::CImageApplyOutHole(void) : CImageApply() - , m_borderSize(600) - , m_edgeScale(0.1f) - , m_threshold(100) + , m_borderSize(20) + , m_edgeScale(0.1f, 0.1f, 0.1f, 0.1f) + , m_threshold(50) { } -CImageApplyOutHole::CImageApplyOutHole(float borderSize, float edgeScale, double threshold) +CImageApplyOutHole::CImageApplyOutHole(float borderSize, cv::Vec4f edgeScale, double threshold) : CImageApply() , m_borderSize(borderSize) , m_edgeScale(edgeScale) @@ -31,6 +32,10 @@ void CImageApplyOutHole::apply(cv::Mat& pDib, int side) (void)side; } +#define MIN_CONTOUR_SIZE 10 +#define RESIZE_FIXED_WIDTH 2448.0 +#define LINE_WIDTH 18 +#define DILATE_SIZE 16 void CImageApplyOutHole::apply(std::vector& mats, bool isTwoSide) { #ifdef LOG @@ -53,14 +58,26 @@ void CImageApplyOutHole::apply(std::vector& mats, bool isTwoSide) return; } + double resize_scale = cv::min(RESIZE_FIXED_WIDTH / static_cast(mats[0].cols), 1.0); + //ֵͼ - cv::Mat front = mats[0]; - cv::Mat back = mats[1]; + cv::Mat front, back; + if (resize_scale != 1.0) + { + cv::resize(mats[0], front, cv::Size(), resize_scale, resize_scale); + cv::resize(mats[1], back, cv::Size(), resize_scale, resize_scale); + } + else + { + front = mats[0]; + back = mats[1]; + } + cv::Mat front_thre, back_thre; hg::threshold_Mat(front, front_thre, m_threshold); hg::threshold_Mat(back, back_thre, m_threshold); - cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(10, 1)); + cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5 * resize_scale, 1)); cv::morphologyEx(front_thre, front_thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0)); cv::morphologyEx(back_thre, back_thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0)); @@ -74,6 +91,22 @@ void CImageApplyOutHole::apply(std::vector& mats, bool isTwoSide) hg::findContours(back_thre.clone(), contours_back, b1_back, cv::RETR_EXTERNAL); //ȡͼ + for (size_t i = 0; i < contours_front.size(); i++) + if (contours_front[i].size() < MIN_CONTOUR_SIZE) + { + contours_front.erase(contours_front.begin() + i); + b1_front.erase(b1_front.begin() + i); + i--; + } + + for (size_t i = 0; i < contours_back.size(); i++) + if (contours_back[i].size() < MIN_CONTOUR_SIZE) + { + contours_back.erase(contours_back.begin() + i); + b1_back.erase(b1_back.begin() + i); + i--; + } + std::vector maxContour_front = hg::getMaxContour(contours_front, b1_front); std::vector maxContour_back = hg::getMaxContour(contours_back, b1_back); @@ -107,27 +140,37 @@ void CImageApplyOutHole::apply(std::vector& mats, bool isTwoSide) cv::bitwise_not(mask, mask); //cv::imwrite("mask2.jpg", mask); //ɫ - element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(10, 10)); - cv::dilate(mask, mask, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar(255)); //㷨׶ͨ + //Ϊ˱׶׹ᴩֽߣΪֽȷп׶ΪͼΣ뱳ճ + cv::polylines(mask, hg::getVertices(mask_rotatedRect), true, cv::Scalar(0), LINE_WIDTH * resize_scale); //ֽžαԵ //cv::imwrite("mask3.jpg", mask); - //Ϊ˱׶׹ᴩֽߣΪֽȷп׶ΪͼΣ뱳ճ - cv::polylines(mask, hg::getVertices(mask_rotatedRect), true, cv::Scalar(255), 15); //ֽžαԵ + //㷨׶ͨ + element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(DILATE_SIZE * resize_scale, DILATE_SIZE * resize_scale)); + cv::dilate(mask, mask, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar(255)); //cv::imwrite("mask4.jpg", mask); + //ȡصͼ std::vector> contours_mask; std::vector b1_mask; - hg::findContours(mask, contours_mask, b1_mask, cv::RETR_TREE); //ȡصͼ + hg::findContours(mask, contours_mask, b1_mask, cv::RETR_TREE); //˷ǿ׶ͨ - std::vector> hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, m_edgeScale, m_borderSize); + std::vector> hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, m_edgeScale, m_borderSize * resize_scale); + + for (size_t i = 0; i < hole_contours.size(); i++) + for (size_t j = 0; j < hole_contours[i].size(); j++) + hole_contours[i][j] /= resize_scale; cv::Scalar color = getBackGroudColor(front(roi_front), rrect_front.size.area()); + roi_front.x /= resize_scale; + roi_front.y /= resize_scale; + roi_front.width /= resize_scale; + roi_front.height /= resize_scale; for (size_t i = 0; i < hole_contours.size(); i++) { std::vector> contourss_temp; contourss_temp.push_back(hole_contours[i]); - cv::Mat front_temp = front(roi_front); + cv::Mat front_temp = mats[0](roi_front); hg::fillPolys(front_temp, contourss_temp, color); } @@ -135,16 +178,26 @@ void CImageApplyOutHole::apply(std::vector& mats, bool isTwoSide) { int width_ = roi_back.width; roi_back.x = back.cols - roi_back.width - roi_back.x; //Ϊ֮ǰͼתROIҲҪӦת - color = getBackGroudColor(back(roi_back), rrect_front.size.area()); + color = getBackGroudColor(back(roi_back), rrect_back.size.area()); + roi_back.x /= resize_scale; + roi_back.y /= resize_scale; + roi_back.width /= resize_scale; + roi_back.height /= resize_scale; + hole_contours.clear(); + hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, cv::Vec4f(m_edgeScale[0], m_edgeScale[1], m_edgeScale[2], m_edgeScale[3]), m_borderSize * resize_scale); + for (size_t i = 0; i < hole_contours.size(); i++) { std::vector hole_contour; for (size_t j = 0; j < hole_contours[i].size(); j++) + { hole_contour.push_back(cv::Point(width_ - hole_contours[i][j].x - 1, hole_contours[i][j].y)); + hole_contour[j] /= resize_scale; + } std::vector> contours_temp; contours_temp.push_back(hole_contour); - cv::Mat back_temp = back(roi_back); + cv::Mat back_temp = mats[1](roi_back); hg::fillPolys(back_temp, contours_temp, color); } } @@ -222,27 +275,44 @@ void CImageApplyOutHole::getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rre roi_front.height -= offset_bottom_b - offset_bottom_f; } -std::vector> CImageApplyOutHole::filterPoly(std::vector>& contours, const std::vector& m, - cv::RotatedRect roi, float edgeScale, float areaThreshold) +#define SIDE_LENGTH_UP_SCALE 6 +#define PI 3.14159265359f +std::vector> CImageApplyOutHole::filterPoly(std::vector>& contours, std::vector& m, + cv::RotatedRect roi, cv::Vec4f edgeScale, float sideLengthLow) { - edgeScale = std::min(0.49f, std::max(edgeScale, 0.0f)); - cv::RotatedRect roi2(roi.center, cv::Size(static_cast(roi.size.width * (1 - edgeScale * 2)), - static_cast(roi.size.height * (1 - edgeScale * 2))), roi.angle); + cv::RotatedRect roi2(roi.center, + cv::Size2f(roi.size.width * (1 - edgeScale[2] - edgeScale[3]), roi.size.height * (1 - edgeScale[0] - edgeScale[1])), + roi.angle); + + cv::Point2f offset_0(roi.size.width * (edgeScale[2] - edgeScale[3]) / 2 + roi.center.x, roi.size.height * (edgeScale[0] - edgeScale[1]) / 2 + roi.center.y); + roi2.center.x = (offset_0.x - roi.center.x) * cos(roi.angle * PI / 180.0f) - (offset_0.y - roi.center.y) * sin(roi2.angle * PI / 180.0f) + roi.center.x; + roi2.center.y = (offset_0.x - roi.center.x) * sin(roi.angle * PI / 180.0f) + (offset_0.y - roi.center.y) * cos(roi2.angle * PI / 180.0f) + roi.center.y; std::vector vertices_roi1 = hg::getVertices(roi); std::vector vertices_roi2 = hg::getVertices(roi2); std::vector> hole_contours; - for (size_t i = 0, length = contours.size(); i < length; i++) + for (size_t i = 0; i < contours.size(); i++) { - if (m[i][2] != -1) continue; + if (m[i][2] != -1) + { + contours.erase(contours.begin() + i); + m.erase(m.begin() + i); + i--; + continue; + } cv::RotatedRect rrect = hg::getBoundingRect(contours[i]); - if (rrect.size.width < areaThreshold || - rrect.size.height < areaThreshold || - rrect.size.width > areaThreshold * 6 || - rrect.size.height > areaThreshold * 6) + if (rrect.size.width < sideLengthLow || + rrect.size.height < sideLengthLow || + rrect.size.width > sideLengthLow * SIDE_LENGTH_UP_SCALE || + rrect.size.height > sideLengthLow * SIDE_LENGTH_UP_SCALE) + { + contours.erase(contours.begin() + i); + m.erase(m.begin() + i); + i--; continue; + } bool enabled = true; for (size_t j = 0, count = contours[i].size(); j < count; j++) @@ -251,9 +321,10 @@ std::vector> CImageApplyOutHole::filterPoly(std::vector 0) + if (temp1 <= 0 || temp2 >= 0) { enabled = false; + //qDebug() << rrect.center.x << ":" << rrect.center.y << "::::" << rrect.size.width << " - " << rrect.size.height; break; } } diff --git a/huagao/ImageProcess/ImageApplyOutHole.h b/huagao/ImageProcess/ImageApplyOutHole.h index a75779e7..2763c153 100644 --- a/huagao/ImageProcess/ImageApplyOutHole.h +++ b/huagao/ImageProcess/ImageApplyOutHole.h @@ -16,7 +16,15 @@ * 2022/07/18 v1.6.3 ޸maskһЩ߼ * 2022/07/18 v1.7 ޸߼BUG滻캯borderSize߼,ԭΪ߳崩׷ΧΪ[borderSize, borderSize * 6] * 2022/07/22 v1.7.1 ޸ԶʶɫBUG - * 汾ţv1.7.1 + * 2022/08/02 v1.7.2 ĬϲԼ + * 2022/09/07 v1.8 ȥұԵΧͳһȡ֮ǷֱҵıԵ + * 2022/09/09 v1.8.1 ޸ԵλľȷBUG + * 2022/09/15 v1.8.2 ޸һЩ߼BUG + * 2022/09/15 v1.8.3 ߿ + * 2022/09/15 v1.8.4 ޸±BUG + * 2022/09/16 v1.9 Żڴ + * 2022/09/16 v1.9.1 ޸ű߼ + * 汾ţv1.9.1 * ==================================================== */ @@ -33,11 +41,11 @@ public: CImageApplyOutHole(); /* - * borderSize [in]:׶ֵ - * edgeScale [in]:ֽűԵȡֵΧ(0,0.5),Ĭֵ0.1 + * borderSize [in]:׶ֵ߳ + * edgeScale [in]:ֽűԵαʾΪұ߾ȡֵΧ[0, 0.5]Ĭֵ0.1 0.1 0.1 0.1׻ڸָıԵѰҡ * threshold [in]:ֵֵ */ - CImageApplyOutHole(float borderSize, float edgeScale, double threshold); + CImageApplyOutHole(float borderSize, cv::Vec4f edgeScale, double threshold); ~CImageApplyOutHole(void); @@ -45,7 +53,7 @@ public: float getBorderSize() { return m_borderSize; } - float getEdgeScale() { return m_edgeScale; } + cv::Vec4f getEdgeScale() { return m_edgeScale; } double getThreshold() { return m_threshold; } @@ -62,8 +70,8 @@ private: void getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, const cv::Size& srcSize_front, const cv::Size& srcSize_back, cv::Rect& roi_front, cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect); - std::vector > filterPoly(std::vector>& contours, const std::vector& m, cv::RotatedRect roi, - float edgeScale, float areaThreshold); + std::vector > filterPoly(std::vector>& contours, std::vector& m, cv::RotatedRect roi, + cv::Vec4f edgeScale, float sideLengthLow); cv::Scalar getBackGroudColor(const cv::Mat& image, const std::vector pixelPoints); @@ -73,7 +81,7 @@ private: private: float m_borderSize; - float m_edgeScale; + cv::Vec4f m_edgeScale; double m_threshold; }; diff --git a/huagao/huagaods.cpp b/huagao/huagaods.cpp index 9f083e52..04a506d4 100644 --- a/huagao/huagaods.cpp +++ b/huagao/huagaods.cpp @@ -1854,6 +1854,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) { auto mech = data.currentItem(); if (mech > 0 && mech < 50) { m_scanparam->fillhole.fillholeratio = (int)mech; + m_scanparam->fillholeratio_up = m_scanparam->fillholeratio_down = m_scanparam->fillholeratio_left = m_scanparam->fillholeratio_right = int(mech); return success(); } return badValue(); @@ -2416,6 +2417,9 @@ Result HuagaoDs::pendingXfersReset(const Identity&, PendingXfers& data) { //guiIndicator.reset(); if (guiIndicator->GetSafeHwnd()) guiIndicator->DestroyWindow(); + if (guiTwain.get()) { + ((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true); + } return success(); } @@ -2652,7 +2656,6 @@ Twpp::Result HuagaoDs::pendingXfersStopFeeder(const Identity& origin, PendingXfe if (scanner->IsConnected()) { scanner->Stop_scan(); } - data.setCount(scanner->Get_IsImageQueueEmpty() ? 0 : 1); return success(); } diff --git a/huagao/huagaotwds.rc b/huagao/huagaotwds.rc index 8e69b3747c55e677f333ad1dbd21d48189939a45..e7c0a3f4f662125d0c274d06171dcf9e450730c9 100644 GIT binary patch delta 895 zcmaJYcitsD_s*AF zuD_=|O?TeNVHkq(s;v~qX1xsf9&})M`O@hAm#xPU9`RQ)<1NR?VMVT{>#-cK#GCi> z0N$xZn(8{NM?v%!6yj)DV8N&+O}izZ(&OBWhkNvsB3x^OLmB9c`pUAic?OBca6Gmar?SM%OI=bd}*xzpL=+ON6oLzg#8 z?vXqxk|nZ)8}pN`T^D{Aqd3XAPPKw8_w1WL`4R0bftjaZMndHb_vP=r(CezQcPPd8P`j&#u)Zdn5vy0!$OQWfSsNo-o!G2(U#ztl!xfm|P5$vIOxA8!PQLEHN{Ud0=jD0sNbc+6i! zKdwo`OnVA@&VIZ%qV+$w)-H>Sb9Fz`wgVlN!X;AY6*7ZoVik@B4KGC%>p_jx(l`iK z**C+m4E92rGfk#Ym#SFLo<%bdMkTCqX*?BY(FtofOjtivKa#|Q2xZ7SWe%E5v6o}( zS15WiWg0Vhugqea-Pcl9y{Q=WG^_7kj delta 374 zcmXYtF-SsD6o!4F7A0lx-Atc$I6hzM&>$i$i8vHEL|MZ_#GxS?qM@N7!XcU(qaPe3 zLdrSH2hrTn6yX?64Gj$q*4Wg2H>dyq{`12*_ja$fo0fL_;|GT(-FhIXd1kcYTlcN{ zR&Zy>k(&y;%fZeB-c5p;B(QGdbGjxufrBKYsWZxYLvdg7t8U>^uOn;~Q7{-C4#96! z)%?_AoEa7zqptWv@|Wb^kjp973iwVg;UdMT2u8mYgf1KmY{GAf&=ofJL`|_{)A#I$*ZDL1=cp4 EKf=?4`Tzg` diff --git a/huagao/stdafx.h b/huagao/stdafx.h index bdedce1b536979c5ef763500051044f83a1bd278..72789f414d4300e9c121c9f25e03b5a259a1d4e5 100644 GIT binary patch delta 31 ncmX?fobk|c#tkhTtVRq53