This commit is contained in:
13038267101 2023-10-24 14:39:11 +08:00
commit e6080d803f
9 changed files with 150 additions and 59 deletions

View File

@ -1,11 +1,17 @@
#include "ImageApplyDiscardBlank.h"
#include "ImageProcess_Public.h"
#include <stdio.h>
#include <iostream>
CImageApplyDiscardBlank::CImageApplyDiscardBlank(double threshold, int edge, double devTh, double meanTh)
#define FX 0.5
#define FY 0.5
CImageApplyDiscardBlank::CImageApplyDiscardBlank(double threshold, int edge, double devTh, double meanTh, int dilate)
: m_threshold(threshold)
, m_edge(edge)
, m_devTh(devTh)
, m_meanTh(meanTh)
, m_dilate(dilate)
{
}
@ -15,7 +21,7 @@ CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void)
void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side)
{
if (apply(pDib, m_threshold, m_edge, m_devTh, m_meanTh))
if (apply(pDib, m_threshold, m_edge, m_devTh, m_meanTh, m_dilate))
pDib.release();
}
@ -32,14 +38,6 @@ void CImageApplyDiscardBlank::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
}
}
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;
@ -49,18 +47,32 @@ bool maxMinCompare(const cv::Mat& img, const cv::Mat& mask, double devTh, double
return (max - min) < devTh;
}
bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int edge, double devTh, double meanTh)
bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int edge, double devTh, double meanTh, int dilate)
{
if (pDib.empty())
return true;
cv::Mat img_resize;
cv::resize(pDib, img_resize, cv::Size(), 0.2, 0.2);
cv::resize(pDib, img_resize, cv::Size(), FX, FY);
if (img_resize.channels() == 3)
cv::cvtColor(img_resize, img_resize, cv::COLOR_BGR2GRAY);
if (dilate > 2)
{
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1, dilate));
cv::Mat img_temp1;
cv::morphologyEx(img_resize, img_temp1, cv::MORPH_DILATE, element);
element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(dilate, 1));
cv::Mat img_temp2;
cv::morphologyEx(img_resize, img_temp2, cv::MORPH_DILATE, element);
img_resize = img_temp1 & img_temp2;
}
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);
cv::threshold(img_resize, threshold_img, threshold, 255, cv::THRESH_BINARY);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> h1;
@ -72,7 +84,7 @@ bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int e
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);
rect.size = cv::Size2f(rect.size.width - edge * FX, rect.size.height - edge * FX);
cv::Point2f box[4];
rect.points(box);
contour.clear();
@ -83,9 +95,6 @@ bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int e
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)
@ -100,17 +109,29 @@ bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int e
}
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;
}
bool CImageApplyDiscardBlank::apply(int fileSize, const cv::Size& imageSize, FileType flag)
{
switch (flag)
{
case JPEG_COLOR:
if (static_cast<double>(fileSize) / static_cast<double>(imageSize.width * imageSize.height) > 0.039)
return true;
break;
case JPEG_GRAY:
if (static_cast<double>(fileSize) / static_cast<double>(imageSize.width * imageSize.height) > 0.018)
return true;
break;
case PNG_COLOR:
break;
case PNG_GRAY:
break;
case PNG_BINARAY:
break;
}
return false;
}

View File

@ -18,7 +18,11 @@
2022/09/19 v1.4
2022/09/19 v1.4.1
2022/11/18 v1.4.2
* v1.4.2
2022/11/29 v1.5
2022/12/03 v1.5.1
2023/10/12 v1.6 JEPG文件大小判断是否为空白页
2023/10/20 v1.6.1 JEPG文件大小判断空白页
* v1.6.1
* ====================================================
*/
@ -31,17 +35,25 @@
class GIMGPROC_LIBRARY_API CImageApplyDiscardBlank : public CImageApply
{
public:
enum FileType
{
JPEG_COLOR,
JPEG_GRAY,
PNG_COLOR,
PNG_GRAY,
PNG_BINARAY
};
/// <summary>
/// 空白页识别
/// </summary>
/// <param name="pDib">原图</param>
/// <param name="threshold">轮廓阈值</param>
/// <param name="edge">边缘缩进</param>
/// <param name="devTh">笔迹判定阈值。该阈值越低,越容易判定存在笔迹。</param>
/// <param name="meanTh">文稿底色阈值。低于该阈值的文稿底色,直接视为非空白页。</param>
/// <returns></returns>
CImageApplyDiscardBlank(double threshold = 40, int edge = 50, double devTh = 30, double meanTh = 200);
/// <param name="threshold">轮廓阈值。取值范围[0, 255]</param>
/// <param name="edge">边缘缩进。取值范围[0, +∞]</param>
/// <param name="devTh">笔迹判定阈值。该阈值越低,越容易判定存在笔迹。取值范围[0, +∞]</param>
/// <param name="meanTh">文稿底色阈值。低于该阈值的文稿底色,直接视为非空白页。取值范围[0, 255]</param>
/// <param name="dilate">忽略纸张杂点。≤1时不生效值越大越容易忽略杂点。取值范围[1, +∞]</param>
CImageApplyDiscardBlank(double threshold = 40, int edge = 50, double devTh = 30, double meanTh = 200, int dilate = 11);
virtual ~CImageApplyDiscardBlank(void);
@ -50,21 +62,32 @@ public:
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
/// <summary>
/// 空白页识别
/// 空白页识别。根据图像内容进行识别。
/// </summary>
/// <param name="pDib">原图</param>
/// <param name="threshold">轮廓阈值</param>
/// <param name="edge">边缘缩进</param>
/// <param name="devTh">笔迹判定阈值。该阈值越低,越容易判定存在笔迹。</param>
/// <param name="meanTh">文稿底色阈值。低于该阈值的文稿底色,直接视为非空白页。</param>
/// <param name="dilate">忽略纸张杂点。≤1时不生效值越大越容易忽略杂点</param>
/// <returns>true为空白页false为非空白页</returns>
static bool apply(const cv::Mat& pDib, double threshold = 40, int edge = 50, double devTh = 30, double meanTh = 200, int dilate = 3);
/// <summary>
/// 空白页识别。根据jpeg文件大小进行判断。
/// </summary>
/// <param name="fileSize">J文件大小</param>
/// <param name="imageSize">图像大小</param>
/// <param name="flag">0为JPG + 彩色1为JPG + 灰度2为PNG + 彩色, 3为PNG + 灰度, 4为PNG + </param>
/// <returns></returns>
static bool apply(const cv::Mat& pDib, double threshold = 40, int edge = 50, double devTh = 30, double meanTh = 200);
static bool apply(int fileSize, const cv::Size& imageSize, FileType type);
private:
double m_threshold;
int m_edge;
double m_devTh;
double m_meanTh;
int m_dilate;
};
#endif // !IMAGE_APPLY_DISCARD_BLANK_H

View File

@ -2920,7 +2920,54 @@ int hg_scanner::setting_get_initial_boot_time(void* data, long* len)
int hg_scanner::setting_set_discardblank(void* data, long* len)
{
is_discardblank = *(bool*)data;
return SCANNER_ERR_OK;
//discard_blank and fold_in_half are mutually exclusive.
if (is_discardblank)
{
std::string str(page_string(PAGE_FOLIO));
int id = lang_get_string_id(str.c_str(), false);
if (id == -1)
{
setting_jsn_.at(SANE_STD_OPT_NAME_PAGE).at("range").erase(str.c_str());
}
else
{
for (int i = 0; i < setting_jsn_.at(SANE_STD_OPT_NAME_PAGE).at("range").size(); ++i)
{
int val = 0;
setting_jsn_.at(SANE_STD_OPT_NAME_PAGE).at("range").at(i).get_to(val);
if (val == id)
{
setting_jsn_.at(SANE_STD_OPT_NAME_PAGE).at("range").erase(i);
break;
}
}
}
}
else
{
std::string str(page_string(PAGE_FOLIO));
int id = lang_get_string_id(str.c_str(), false), val = 0;
bool add = true;
for (int i = 0; i < setting_jsn_.at(SANE_STD_OPT_NAME_PAGE).at("range").size(); ++i)
{
setting_jsn_.at(SANE_STD_OPT_NAME_PAGE).at("range").at(i).get_to(val);
if (val == id)
{
add = false;
break;
}
}
if (add)
{
if (id == -1)
setting_jsn_.at(SANE_STD_OPT_NAME_PAGE).at("range").push_back(str);
else
setting_jsn_.at(SANE_STD_OPT_NAME_PAGE).at("range").push_back(id);
}
}
return SCANNER_ERR_RELOAD_OPT_PARAM;
}
int hg_scanner::on_color_mode_changed(int& color_mode)
{

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
// hg_scanner is the base class of kinds of scanners
//
@ -31,6 +31,7 @@
#include <unistd.h>
#include <dlfcn.h>
#endif
#include "../../../sdk/include/huagao/brand.h"
#ifndef WIN32

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1708,6 +1708,7 @@ SANE_Status hg_sane_middleware::read(SANE_Handle h, void* buf, int* bytes)
}
SANE_Status hg_sane_middleware::stop(SANE_Handle h)
{
LOG_INFO(LOG_LEVEL_ALL, "sane_cancel\n");
scanner_handle hs = find_openning_device(h);
if(hs)
@ -2602,8 +2603,6 @@ extern "C" { // avoid compiler exporting name in C++ style !!!
}
void inner_sane_cancel(SANE_Handle handle)
{
LOG_INFO(LOG_LEVEL_ALL, "sane_cancel\n");
hg_sane_middleware::instance()->stop(handle);
}
SANE_Status inner_sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)