mirror of http://192.168.1.51:8099/lmh188/twain3.0
调整穿孔UI,更新算法
This commit is contained in:
parent
e964c60148
commit
6d233d10be
|
@ -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 自适应幅面功能
|
||||
3.修复显示UI时通过协议reset停止扫描时按钮未正常复位问题
|
||||
4.更新除穿孔以及跳过空白页算法
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
};
|
|
@ -6,7 +6,7 @@
|
|||
#include "afxdialogex.h"
|
||||
#include "resource.h"
|
||||
#include <vector>
|
||||
|
||||
#include "CFillHoleDlg.h"
|
||||
|
||||
|
||||
static std::vector<CString> 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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<CImageApply>(new CImageApplyOutHole(25, ratio, 40)));
|
||||
if (scanParam.fillhole.is_fillhole) {
|
||||
m_iaList.push_back(shared_ptr<CImageApply>(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<CImageApply>(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<CImageApply>(disBlank));
|
||||
//m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank(param.areanum,param.devnmax)));
|
||||
if (param.is_autodiscradblank_normal)
|
||||
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank(40, 30, param.discardblank_percent, 200)));
|
||||
else
|
||||
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank(40, 30, param.discardblank_percent * 15 / 10, 150)));
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -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字节做协议扩展*/
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<GScanCap> 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<GScanCap> 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<GScanCap> 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<GScanCap> 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<GScanCap> 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 ,
|
||||
|
|
|
@ -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<cv::Point>& 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<std::vector<cv::Point>> contours;
|
||||
std::vector<cv::Vec4i> h1;
|
||||
hg::findContours(threshold_img, contours, h1, CV_CHAIN_APPROX_SIMPLE);
|
||||
threshold_img.release();
|
||||
|
||||
if (contours.size() == 0)
|
||||
return blockCount;
|
||||
|
||||
std::vector<cv::Point2f> 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<int> 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<cv::Point> 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<cv::Mat>& mats, bool isTwoSide)
|
||||
|
@ -197,30 +32,86 @@ void CImageApplyDiscardBlank::apply(std::vector<cv::Mat>& 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<std::vector<cv::Point>> contours;
|
||||
std::vector<cv::Vec4i> h1;
|
||||
hg::findContours(threshold_img, contours, h1, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
|
||||
|
||||
std::vector<cv::Point> contour;
|
||||
for (const std::vector<cv::Point>& 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
/*
|
||||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:空白页识别。
|
||||
* 作者:刘丁维
|
||||
* 生成时间: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版本导致计算结果存在差异的代码。
|
||||
* 版本号: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<cv::Mat>& 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<cv::Point>& 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
|
|
@ -1,5 +1,6 @@
|
|||
#include "ImageApplyOutHole.h"
|
||||
#include "ImageProcess_Public.h"
|
||||
//#include <QDebug>
|
||||
|
||||
#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<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
#ifdef LOG
|
||||
|
@ -53,14 +58,26 @@ void CImageApplyOutHole::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
|||
return;
|
||||
}
|
||||
|
||||
double resize_scale = cv::min(RESIZE_FIXED_WIDTH / static_cast<double>(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<cv::Mat>& 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<cv::Point> maxContour_front = hg::getMaxContour(contours_front, b1_front);
|
||||
std::vector<cv::Point> maxContour_back = hg::getMaxContour(contours_back, b1_back);
|
||||
|
||||
|
@ -107,27 +140,37 @@ void CImageApplyOutHole::apply(std::vector<cv::Mat>& 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<std::vector<cv::Point>> contours_mask;
|
||||
std::vector<cv::Vec4i> b1_mask;
|
||||
hg::findContours(mask, contours_mask, b1_mask, cv::RETR_TREE); //提取重叠图像轮廓
|
||||
hg::findContours(mask, contours_mask, b1_mask, cv::RETR_TREE);
|
||||
|
||||
//过滤非孔洞的联通区域
|
||||
std::vector<std::vector<cv::Point>> hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, m_edgeScale, m_borderSize);
|
||||
std::vector<std::vector<cv::Point>> 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<std::vector<cv::Point>> 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<cv::Mat>& 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<cv::Point> 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<std::vector<cv::Point>> 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<std::vector<cv::Point>> CImageApplyOutHole::filterPoly(std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& m,
|
||||
cv::RotatedRect roi, float edgeScale, float areaThreshold)
|
||||
#define SIDE_LENGTH_UP_SCALE 6
|
||||
#define PI 3.14159265359f
|
||||
std::vector<std::vector<cv::Point>> CImageApplyOutHole::filterPoly(std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& 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<int>(roi.size.width * (1 - edgeScale * 2)),
|
||||
static_cast<int>(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<cv::Point> vertices_roi1 = hg::getVertices(roi);
|
||||
std::vector<cv::Point> vertices_roi2 = hg::getVertices(roi2);
|
||||
|
||||
std::vector<std::vector<cv::Point>> 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<std::vector<cv::Point>> CImageApplyOutHole::filterPoly(std::vector<s
|
|||
double temp1 = pointPolygonTest(vertices_roi1, p, false); //判断是否在纸张内 1:内;0:上;-1:外
|
||||
double temp2 = pointPolygonTest(vertices_roi2, p, false); //判断是否在边缘区域内 1:内;0:上;-1:外
|
||||
//如果在纸张外,或者边缘内,视为非孔洞
|
||||
if (temp1 < 0 || temp2 > 0)
|
||||
if (temp1 <= 0 || temp2 >= 0)
|
||||
{
|
||||
enabled = false;
|
||||
//qDebug() << rrect.center.x << ":" << rrect.center.y << "::::" << rrect.size.width << " - " << rrect.size.height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<std::vector<cv::Point> > filterPoly(std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& m, cv::RotatedRect roi,
|
||||
float edgeScale, float areaThreshold);
|
||||
std::vector<std::vector<cv::Point> > filterPoly(std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& m, cv::RotatedRect roi,
|
||||
cv::Vec4f edgeScale, float sideLengthLow);
|
||||
|
||||
cv::Scalar getBackGroudColor(const cv::Mat& image, const std::vector<cv::Point> pixelPoints);
|
||||
|
||||
|
@ -73,7 +81,7 @@ private:
|
|||
|
||||
private:
|
||||
float m_borderSize;
|
||||
float m_edgeScale;
|
||||
cv::Vec4f m_edgeScale;
|
||||
double m_threshold;
|
||||
};
|
||||
|
||||
|
|
|
@ -1854,6 +1854,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
|
|||
auto mech = data.currentItem<Int32>();
|
||||
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();
|
||||
}
|
||||
|
|
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