From bb6c1cdf6e76e5cee01d037847ca86a79c0f2816 Mon Sep 17 00:00:00 2001 From: yangjiaxuan <171295266@qq.com> Date: Mon, 23 Oct 2023 09:28:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=B7=B3=E8=BF=87=E7=A9=BA?= =?UTF-8?q?=E7=99=BD=E9=A1=B5=E7=AE=97=E6=B3=95=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=80=9A=E8=BF=87jpeg=E5=A4=A7=E5=B0=8F=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E7=A9=BA=E7=99=BD=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ImageProcess/ImageApplyDiscardBlank.cpp | 81 ++++++++++++------- .../ImageProcess/ImageApplyDiscardBlank.h | 41 +++++++--- 2 files changed, 83 insertions(+), 39 deletions(-) diff --git a/hgdriver/ImageProcess/ImageApplyDiscardBlank.cpp b/hgdriver/ImageProcess/ImageApplyDiscardBlank.cpp index 0526ed5..b63bdea 100644 --- a/hgdriver/ImageProcess/ImageApplyDiscardBlank.cpp +++ b/hgdriver/ImageProcess/ImageApplyDiscardBlank.cpp @@ -1,11 +1,17 @@ #include "ImageApplyDiscardBlank.h" #include "ImageProcess_Public.h" +#include +#include -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& 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> contours; std::vector 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(fileSize) / static_cast(imageSize.width * imageSize.height) > 0.039) + return true; + break; + case JPEG_GRAY: + if (static_cast(fileSize) / static_cast(imageSize.width * imageSize.height) > 0.018) + return true; + break; + case PNG_COLOR: + break; + case PNG_GRAY: + break; + case PNG_BINARAY: + break; + } + + return false; +} diff --git a/hgdriver/ImageProcess/ImageApplyDiscardBlank.h b/hgdriver/ImageProcess/ImageApplyDiscardBlank.h index df9cb72..47b991b 100644 --- a/hgdriver/ImageProcess/ImageApplyDiscardBlank.h +++ b/hgdriver/ImageProcess/ImageApplyDiscardBlank.h @@ -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 + }; /// /// 空白页识别 /// /// 原图 - /// 轮廓阈值 - /// 边缘缩进 - /// 笔迹判定阈值。该阈值越低,越容易判定存在笔迹。 - /// 文稿底色阈值。低于该阈值的文稿底色,直接视为非空白页。 - /// - CImageApplyDiscardBlank(double threshold = 40, int edge = 50, double devTh = 30, double meanTh = 200); + /// 轮廓阈值。取值范围[0, 255] + /// 边缘缩进。取值范围[0, +∞] + /// 笔迹判定阈值。该阈值越低,越容易判定存在笔迹。取值范围[0, +∞] + /// 文稿底色阈值。低于该阈值的文稿底色,直接视为非空白页。取值范围[0, 255] + /// 忽略纸张杂点。≤1时不生效,值越大越容易忽略杂点。取值范围[1, +∞] + 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& mats, bool isTwoSide); /// - /// 空白页识别 + /// 空白页识别。根据图像内容进行识别。 /// /// 原图 /// 轮廓阈值 /// 边缘缩进 /// 笔迹判定阈值。该阈值越低,越容易判定存在笔迹。 /// 文稿底色阈值。低于该阈值的文稿底色,直接视为非空白页。 + /// 忽略纸张杂点。≤1时不生效,值越大越容易忽略杂点 + /// true为空白页,false为非空白页 + static bool apply(const cv::Mat& pDib, double threshold = 40, int edge = 50, double devTh = 30, double meanTh = 200, int dilate = 3); + + /// + /// 空白页识别。根据jpeg文件大小进行判断。 + /// + /// J文件大小 + /// 图像大小 + /// 0为JPG + 彩色,1为JPG + 灰度,2为PNG + 彩色, 3为PNG + 灰度, 4为PNG + /// - 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 \ No newline at end of file