diff --git a/hgdriver/ImageProcess/ImageApplyAutoCrop.cpp b/hgdriver/ImageProcess/ImageApplyAutoCrop.cpp index 7c2ff63..0a48e2b 100644 --- a/hgdriver/ImageProcess/ImageApplyAutoCrop.cpp +++ b/hgdriver/ImageProcess/ImageApplyAutoCrop.cpp @@ -4,7 +4,6 @@ #include #include "ImageApplyDispersion.h" -#define COLOR_BACKGROUND_THRE 20 #define FRONT_TOP 70 #define FX_FY 0.5f @@ -18,14 +17,13 @@ CImageApplyAutoCrop::CImageApplyAutoCrop() , m_noise(8) , m_indent(5) , m_normalCrop(false) - , m_isDispersion(true) , m_fx(1.0) , m_fy(1.0) { } CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor, - double threshold, int noise, int indent, bool normalCrop, bool dispersion, double fx, double fy) + double threshold, int noise, int indent, bool normalCrop, double fx, double fy) : m_isCrop(isCrop) , m_isDesaskew(isDesaskew) , m_isFillBlank(isFillBlank) @@ -36,7 +34,6 @@ CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFi , m_indent(indent) , m_fixedSize(fixedSize) , m_normalCrop(normalCrop) - , m_isDispersion(dispersion) , m_fx(fx) , m_fy(fy) { @@ -50,7 +47,7 @@ void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side) { cv::Mat dst; autoCrop_desaskew_fillBlank(pDib, dst, m_isCrop, m_isDesaskew, m_isFillBlank, m_fixedSize.width, m_fixedSize.height, - m_isConvexHull, m_isFillColor, m_threshold, m_noise, m_indent, m_normalCrop, m_isDispersion, m_fx, m_fy); + m_isConvexHull, m_isFillColor, m_threshold, m_noise, m_indent, m_normalCrop, m_fx, m_fy); pDib = dst; } @@ -99,14 +96,14 @@ void CImageApplyAutoCrop::myWarpAffine(cv::InputArray _src, cv::OutputArray _dst M, interpolation, borderType, borderValue.val); } -cv::Scalar CImageApplyAutoCrop::getBackGroudColor(const cv::Mat& image, int threshold) +cv::Scalar CImageApplyAutoCrop::getBackGroudColor(const cv::Mat& image) { if (image.channels() == 3) { uchar table[768] = { 0 }; int hist_bgr[3][256] = { 0 }; int width = image.cols, height = image.rows, bytesPerLine = image.step; - memset(table + threshold * 3, 255, 768 - threshold * 3); + memset(table, 255, 768); unsigned char* ptr_data = image.data; unsigned char b = 0; @@ -136,7 +133,7 @@ cv::Scalar CImageApplyAutoCrop::getBackGroudColor(const cv::Mat& image, int thre uchar table[256] = { 0 }; int hist_bgr[256] = { 0 }; int width = image.cols, height = image.rows, bytesPerLine = image.step; - memset(table + threshold, 255, 256 - threshold); + memset(table, 255, 256); unsigned char* ptr_data = image.data; unsigned char b = 0; for (uint i = 0; i < height; i++, ptr_data += bytesPerLine) @@ -153,7 +150,7 @@ cv::Scalar CImageApplyAutoCrop::getBackGroudColor(const cv::Mat& image, int thre } void CImageApplyAutoCrop::autoCrop_desaskew_fillBlank(cv::Mat& src, cv::Mat& dst, bool isAutoCrop, bool isDesaskew, bool isFillBlank, int dWidth, int dHeight, - bool isConvex, bool isColorBlank, double threshold, int noise, int indent, bool isNormalCrop, bool dispersion, double fx, double fy) + bool isConvex, bool isColorBlank, double threshold, int noise, int indent, bool isNormalCrop, double fx, double fy) { if (src.empty()) return; @@ -186,7 +183,7 @@ void CImageApplyAutoCrop::autoCrop_desaskew_fillBlank(cv::Mat& src, cv::Mat& dst hg::threshold_Mat(resizeMat, thre, threshold); if (noise > 0) - cv::morphologyEx(thre, thre, cv::MORPH_OPEN, getStructuringElement(cv::MORPH_RECT, cv::Size(noise * FX_FY, 1)), + cv::morphologyEx(thre, thre, cv::MORPH_OPEN, getStructuringElement(cv::MORPH_RECT, cv::Size(cv::max(static_cast(noise * FX_FY), 1), 1)), cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0)); std::vector hierarchy; @@ -213,18 +210,24 @@ void CImageApplyAutoCrop::autoCrop_desaskew_fillBlank(cv::Mat& src, cv::Mat& dst } cv::RotatedRect rect = hg::getBoundingRect(maxContour); - - if (dispersion) + if (rect.size.width < 1 || rect.size.height < 1) { - CImageApplyDispersion m_dispersion_apply; - cv::Mat mat_dispersion = src(cv::boundingRect(maxContour)); - m_dispersion_apply.apply(mat_dispersion, 0); + dst = src; + return; } cv::Scalar blankColor; if (isFillBlank) if (isColorBlank) - blankColor = getBackGroudColor(resizeMat, COLOR_BACKGROUND_THRE); + { + cv::Rect boudingRect = cv::boundingRect(maxContour); + boudingRect.x *= FX_FY; + boudingRect.y *= FX_FY; + boudingRect.width *= FX_FY; + boudingRect.height *= FX_FY; + + blankColor = getBackGroudColor(resizeMat(boudingRect)); + } else blankColor = cv::Scalar::all(255); else diff --git a/hgdriver/ImageProcess/ImageApplyAutoCrop.h b/hgdriver/ImageProcess/ImageApplyAutoCrop.h index 1f4c9d7..8c749cd 100644 --- a/hgdriver/ImageProcess/ImageApplyAutoCrop.h +++ b/hgdriver/ImageProcess/ImageApplyAutoCrop.h @@ -2,8 +2,8 @@ * ==================================================== * 功能:自动裁剪、纠偏、除黑底 - * 作者:刘丁绿 - * 生成时间_020/4/21 + * 作者:刘丁维 + * 生成时间:2020/4/21 * 最近修改时间:2020/4/21 v1.0 2020/7/22 v1.1 增加获取图像有效区域轮廓的接口maxContour(用于配合一体机的“跳过空白页”算法,PC端暂时无需使用_ 2020/10/16 v1.2 修复自动裁剪尺寸精度丢失的BUG;提高除黑底缩进精度 @@ -29,7 +29,12 @@ 2022/10/31 v1.5 增加横纵DPI缩放参数fx,fy。 2022/11/19 v1.5.1 修复文稿背景色识别算法的BUG。 2022/11/19 v1.5.2 修复灰度文稿背景色识别算法的BUG。 - * 版本号:v1.5.2 + 2023/03/17 v1.5.3 修复背景除噪时,形态学处理kSize可能为0的BUG。 + 2023/04/19 v1.5.4 取消集成色散功能。 + 2023/05/15 v1.5.5 优化文稿背景色识别算法。 + 2023/05/23 v1.5.6 修复纯黑图找不到外界轮廓会导致崩溃的BUG。 + 2023/11/02 v1.6 优化抗噪能力。采用自适应背景色二值化。 + * 版本号:v1.5.6 * ==================================================== */ @@ -39,29 +44,28 @@ #include "ImageApply.h" -class CImageApplyDispersion; class GIMGPROC_LIBRARY_API CImageApplyAutoCrop : public CImageApply { public: CImageApplyAutoCrop(); - /* - * isCrop [in]:自动幅面裁剪使能,true自动裁剪,false为固定裁剿 - * isDesaskew [in]:自动纠偏使能,true自动纠偏,false为不纠偏 - * isFillBlank [in]:黑底填充使能,true为填充,false为不填充 - * fixedSize [in]:固定幅面尺寸,当isCrop为false时生效,结果尺寸按fixedSize大小输出,单位像紿 - * isConvex [in]:黑底填充时的填充方式,true为凸多边形填充,false为凹多边形填充,默认true - * isFillColor [in]:黑底填充时采用自适应色彩填充,false为白色填充,true为自适应文稿底色填充,默认false - * threshold [in]:二值化阈值,取值范囿0, 255),默访0 - * noise [in]:除噪像素,能够消除noise宽度的背景竖条纹干扰,默访 - * indent [in]:轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默访 - * normalCrop [in]:为true时,m_isCrop m_isDesaskew m_isFillBlank失效,固定裁切采用最传统的裁切方式,默认false - * dispersion [in]:为true时,除色散;false时不除色散。默认为true - * fx [in]:横向缩放比例。默认1.0 - * fy [in]:纵向缩放比例。默认1.0 - */ + /// + /// 构造函数 + /// + /// 自动幅面裁剪使能,true自动裁剪,false为固定裁切 + /// 自动纠偏使能,true自动纠偏,false为不纠偏 + /// 黑底填充使能,true为填充,false为不填充 + /// 固定幅面尺寸,当isCrop为false时生效,结果尺寸按fixedSize大小输出,单位像素 + /// 黑底填充时的填充方式,true为凸多边形填充,false为凹多边形填充,默认true + /// 黑底填充时采用自适应色彩填充,false为白色填充,true为自适应文稿底色填充,默认false + /// 二值化阈值,取值范囿[-1, 255],默认40。当threshold<0时,采用根据背景自适应二值化。 + /// 除噪像素,能够消除noise宽度的背景竖条纹干扰,默认8。 + /// 轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默认8 + /// 为true时,m_isCrop m_isDesaskew m_isFillBlank失效,固定裁切采用最传统的裁切方式,默认false + /// 横向缩放比例。默认1.0 + /// 纵向缩放比例。默认1.0 CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true, - bool isFillColor = false, double threshold = 40, int noise = 8, int indent = 5, bool normalCrop = false, bool dispersion = true, double fx = 1.0, double fy = 1.0); + bool isFillColor = false, double threshold = 40, int noise = 8, int indent = 5, bool normalCrop = false, double fx = 1.0, double fy = 1.0); virtual ~CImageApplyAutoCrop(); @@ -105,23 +109,20 @@ public: void setFixedSize(cv::Size size) { m_fixedSize = size; } - void setDispersion(bool enable) { m_isDispersion = enable; } - static void autoCrop_desaskew_fillBlank(cv::Mat& src, cv::Mat& dst, bool isAutoCrop, bool isDesaskew, bool isFillBlank, int dWidth, int dHeight, - bool isConvex = true, bool isColorBlank = false, double threshold = 40, int noise = 8, int indent = 5, bool isNormalCrop = false, bool dispersion = true, + bool isConvex = true, bool isColorBlank = false, double threshold = 40, int noise = 8, int indent = 5, bool isNormalCrop = false, double fx = 1.0, double fy = 1.0); private: static void myWarpAffine(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _M0, cv::Size dsize, int flags, int borderType, const cv::Scalar& borderValue); - static cv::Scalar getBackGroudColor(const cv::Mat& image, int threshold); + static cv::Scalar getBackGroudColor(const cv::Mat& image); private: bool m_isCrop; bool m_isDesaskew; bool m_isFillBlank; bool m_isConvexHull; bool m_isFillColor; - bool m_isDispersion; double m_threshold; int m_noise;