更新跳过空白页算法,优化通过jpeg大小判断空白页
This commit is contained in:
parent
5f1c2f45fd
commit
bb6c1cdf6e
|
@ -1,11 +1,17 @@
|
||||||
#include "ImageApplyDiscardBlank.h"
|
#include "ImageApplyDiscardBlank.h"
|
||||||
#include "ImageProcess_Public.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_threshold(threshold)
|
||||||
, m_edge(edge)
|
, m_edge(edge)
|
||||||
, m_devTh(devTh)
|
, m_devTh(devTh)
|
||||||
, m_meanTh(meanTh)
|
, m_meanTh(meanTh)
|
||||||
|
, m_dilate(dilate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +21,7 @@ CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void)
|
||||||
|
|
||||||
void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side)
|
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();
|
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)
|
bool maxMinCompare(const cv::Mat& img, const cv::Mat& mask, double devTh, double meanTh)
|
||||||
{
|
{
|
||||||
double min, max;
|
double min, max;
|
||||||
|
@ -49,18 +47,32 @@ bool maxMinCompare(const cv::Mat& img, const cv::Mat& mask, double devTh, double
|
||||||
return (max - min) < devTh;
|
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())
|
if (pDib.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
cv::Mat img_resize;
|
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;
|
cv::Mat threshold_img;
|
||||||
if (img_resize.channels() == 3)
|
cv::threshold(img_resize, threshold_img, threshold, 255, cv::THRESH_BINARY);
|
||||||
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<std::vector<cv::Point>> contours;
|
||||||
std::vector<cv::Vec4i> h1;
|
std::vector<cv::Vec4i> h1;
|
||||||
|
@ -72,7 +84,7 @@ bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int e
|
||||||
contour.push_back(p);
|
contour.push_back(p);
|
||||||
|
|
||||||
cv::RotatedRect rect = hg::getBoundingRect(contour);
|
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];
|
cv::Point2f box[4];
|
||||||
rect.points(box);
|
rect.points(box);
|
||||||
contour.clear();
|
contour.clear();
|
||||||
|
@ -83,9 +95,6 @@ bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int e
|
||||||
contours.push_back(contour);
|
contours.push_back(contour);
|
||||||
cv::Mat mask = cv::Mat::zeros(img_resize.size(), CV_8UC1);
|
cv::Mat mask = cv::Mat::zeros(img_resize.size(), CV_8UC1);
|
||||||
hg::fillPolys(mask, contours, cv::Scalar::all(255));
|
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;
|
bool b = true;
|
||||||
if (img_resize.channels() == 3)
|
if (img_resize.channels() == 3)
|
||||||
|
@ -100,17 +109,29 @@ bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int e
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
b &= maxMinCompare(img_resize, mask, devTh, meanTh);
|
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;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,11 @@
|
||||||
2022/09/19 v1.4 增加模糊处理,提高空白页的过滤能力
|
2022/09/19 v1.4 增加模糊处理,提高空白页的过滤能力
|
||||||
2022/09/19 v1.4.1 调整模糊处理步骤
|
2022/09/19 v1.4.1 调整模糊处理步骤
|
||||||
2022/11/18 v1.4.2 调整默认参数
|
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
|
class GIMGPROC_LIBRARY_API CImageApplyDiscardBlank : public CImageApply
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum FileType
|
||||||
|
{
|
||||||
|
JPEG_COLOR,
|
||||||
|
JPEG_GRAY,
|
||||||
|
PNG_COLOR,
|
||||||
|
PNG_GRAY,
|
||||||
|
PNG_BINARAY
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 空白页识别
|
/// 空白页识别
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pDib">原图</param>
|
/// <param name="pDib">原图</param>
|
||||||
/// <param name="threshold">轮廓阈值</param>
|
/// <param name="threshold">轮廓阈值。取值范围[0, 255]</param>
|
||||||
/// <param name="edge">边缘缩进</param>
|
/// <param name="edge">边缘缩进。取值范围[0, +∞]</param>
|
||||||
/// <param name="devTh">笔迹判定阈值。该阈值越低,越容易判定存在笔迹。</param>
|
/// <param name="devTh">笔迹判定阈值。该阈值越低,越容易判定存在笔迹。取值范围[0, +∞]</param>
|
||||||
/// <param name="meanTh">文稿底色阈值。低于该阈值的文稿底色,直接视为非空白页。</param>
|
/// <param name="meanTh">文稿底色阈值。低于该阈值的文稿底色,直接视为非空白页。取值范围[0, 255]</param>
|
||||||
/// <returns></returns>
|
/// <param name="dilate">忽略纸张杂点。≤1时不生效,值越大越容易忽略杂点。取值范围[1, +∞]</param>
|
||||||
CImageApplyDiscardBlank(double threshold = 40, int edge = 50, double devTh = 30, double meanTh = 200);
|
CImageApplyDiscardBlank(double threshold = 40, int edge = 50, double devTh = 30, double meanTh = 200, int dilate = 11);
|
||||||
|
|
||||||
virtual ~CImageApplyDiscardBlank(void);
|
virtual ~CImageApplyDiscardBlank(void);
|
||||||
|
|
||||||
|
@ -50,21 +62,32 @@ public:
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 空白页识别
|
/// 空白页识别。根据图像内容进行识别。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pDib">原图</param>
|
/// <param name="pDib">原图</param>
|
||||||
/// <param name="threshold">轮廓阈值</param>
|
/// <param name="threshold">轮廓阈值</param>
|
||||||
/// <param name="edge">边缘缩进</param>
|
/// <param name="edge">边缘缩进</param>
|
||||||
/// <param name="devTh">笔迹判定阈值。该阈值越低,越容易判定存在笔迹。</param>
|
/// <param name="devTh">笔迹判定阈值。该阈值越低,越容易判定存在笔迹。</param>
|
||||||
/// <param name="meanTh">文稿底色阈值。低于该阈值的文稿底色,直接视为非空白页。</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>
|
/// <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:
|
private:
|
||||||
double m_threshold;
|
double m_threshold;
|
||||||
int m_edge;
|
int m_edge;
|
||||||
double m_devTh;
|
double m_devTh;
|
||||||
double m_meanTh;
|
double m_meanTh;
|
||||||
|
int m_dilate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !IMAGE_APPLY_DISCARD_BLANK_H
|
#endif // !IMAGE_APPLY_DISCARD_BLANK_H
|
Loading…
Reference in New Issue