更新裁切纠偏算法到最新版本

This commit is contained in:
yangjiaxuan 2023-11-28 15:47:34 +08:00
parent 7de96f6dff
commit 9e30fa0db0
2 changed files with 45 additions and 41 deletions

View File

@ -4,7 +4,6 @@
#include <opencv2/imgproc/hal/hal.hpp> #include <opencv2/imgproc/hal/hal.hpp>
#include "ImageApplyDispersion.h" #include "ImageApplyDispersion.h"
#define COLOR_BACKGROUND_THRE 20
#define FRONT_TOP 70 #define FRONT_TOP 70
#define FX_FY 0.5f #define FX_FY 0.5f
@ -18,14 +17,13 @@ CImageApplyAutoCrop::CImageApplyAutoCrop()
, m_noise(8) , m_noise(8)
, m_indent(5) , m_indent(5)
, m_normalCrop(false) , m_normalCrop(false)
, m_isDispersion(true)
, m_fx(1.0) , m_fx(1.0)
, m_fy(1.0) , m_fy(1.0)
{ {
} }
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor, 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_isCrop(isCrop)
, m_isDesaskew(isDesaskew) , m_isDesaskew(isDesaskew)
, m_isFillBlank(isFillBlank) , m_isFillBlank(isFillBlank)
@ -36,7 +34,6 @@ CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFi
, m_indent(indent) , m_indent(indent)
, m_fixedSize(fixedSize) , m_fixedSize(fixedSize)
, m_normalCrop(normalCrop) , m_normalCrop(normalCrop)
, m_isDispersion(dispersion)
, m_fx(fx) , m_fx(fx)
, m_fy(fy) , m_fy(fy)
{ {
@ -50,7 +47,7 @@ void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
{ {
cv::Mat dst; cv::Mat dst;
autoCrop_desaskew_fillBlank(pDib, dst, m_isCrop, m_isDesaskew, m_isFillBlank, m_fixedSize.width, m_fixedSize.height, 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; pDib = dst;
} }
@ -99,14 +96,14 @@ void CImageApplyAutoCrop::myWarpAffine(cv::InputArray _src, cv::OutputArray _dst
M, interpolation, borderType, borderValue.val); 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) if (image.channels() == 3)
{ {
uchar table[768] = { 0 }; uchar table[768] = { 0 };
int hist_bgr[3][256] = { 0 }; int hist_bgr[3][256] = { 0 };
int width = image.cols, height = image.rows, bytesPerLine = image.step; 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* ptr_data = image.data;
unsigned char b = 0; unsigned char b = 0;
@ -136,7 +133,7 @@ cv::Scalar CImageApplyAutoCrop::getBackGroudColor(const cv::Mat& image, int thre
uchar table[256] = { 0 }; uchar table[256] = { 0 };
int hist_bgr[256] = { 0 }; int hist_bgr[256] = { 0 };
int width = image.cols, height = image.rows, bytesPerLine = image.step; 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* ptr_data = image.data;
unsigned char b = 0; unsigned char b = 0;
for (uint i = 0; i < height; i++, ptr_data += bytesPerLine) 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, 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; 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); hg::threshold_Mat(resizeMat, thre, threshold);
if (noise > 0) 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<int>(noise * FX_FY), 1), 1)),
cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0)); cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
std::vector<cv::Vec4i> hierarchy; std::vector<cv::Vec4i> hierarchy;
@ -213,18 +210,24 @@ void CImageApplyAutoCrop::autoCrop_desaskew_fillBlank(cv::Mat& src, cv::Mat& dst
} }
cv::RotatedRect rect = hg::getBoundingRect(maxContour); cv::RotatedRect rect = hg::getBoundingRect(maxContour);
if (rect.size.width < 1 || rect.size.height < 1)
if (dispersion)
{ {
CImageApplyDispersion m_dispersion_apply; dst = src;
cv::Mat mat_dispersion = src(cv::boundingRect(maxContour)); return;
m_dispersion_apply.apply(mat_dispersion, 0);
} }
cv::Scalar blankColor; cv::Scalar blankColor;
if (isFillBlank) if (isFillBlank)
if (isColorBlank) 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 else
blankColor = cv::Scalar::all(255); blankColor = cv::Scalar::all(255);
else else

View File

@ -2,8 +2,8 @@
* ==================================================== * ====================================================
* *
* 绿 *
* _020/4/21 * 2020/4/21
* 2020/4/21 v1.0 * 2020/4/21 v1.0
2020/7/22 v1.1 maxContourPC端暂时无需使用_ 2020/7/22 v1.1 maxContourPC端暂时无需使用_
2020/10/16 v1.2 BUG 2020/10/16 v1.2 BUG
@ -29,7 +29,12 @@
2022/10/31 v1.5 DPI缩放参数fx,fy 2022/10/31 v1.5 DPI缩放参数fx,fy
2022/11/19 v1.5.1 稿BUG 2022/11/19 v1.5.1 稿BUG
2022/11/19 v1.5.2 稿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" #include "ImageApply.h"
class CImageApplyDispersion;
class GIMGPROC_LIBRARY_API CImageApplyAutoCrop : public CImageApply class GIMGPROC_LIBRARY_API CImageApplyAutoCrop : public CImageApply
{ {
public: public:
CImageApplyAutoCrop(); CImageApplyAutoCrop();
/* /// <summary>
* isCrop [in]:使true自动裁剪false为固定裁剿 /// 构造函数
* isDesaskew [in]:使true自动纠偏false为不纠偏 /// </summary>
* isFillBlank [in]:使true为填充false为不填充 /// <param name="isCrop">自动幅面裁剪使能true自动裁剪false为固定裁切</param>
* fixedSize [in]:isCrop为false时生效fixedSize大小输出紿 /// <param name="isDesaskew">自动纠偏使能true自动纠偏false为不纠偏</param>
* isConvex [in]:,true为凸多边形填充false为凹多边形填充true /// <param name="isFillBlank">黑底填充使能true为填充false为不填充</param>
* isFillColor [in]:false为白色填充true为自适应文稿底色填充false /// <param name="fixedSize">固定幅面尺寸当isCrop为false时生效结果尺寸按fixedSize大小输出单位像素</param>
* threshold [in]:0, 255)访0 /// <param name="isConvex">黑底填充时的填充方式,true为凸多边形填充false为凹多边形填充默认true</param>
* noise [in]:noise宽度的背景竖条纹干扰访 /// <param name="isFillColor">黑底填充时采用自适应色彩填充false为白色填充true为自适应文稿底色填充默认false</param>
* indent [in]:indent像素访 /// <param name="threshold">二值化阈值,取值范囿[-1, 255]默认40。当threshold<0时采用根据背景自适应二值化。</param>
* normalCrop [in]:true时m_isCrop m_isDesaskew m_isFillBlank失效false /// <param name="noise">除噪像素能够消除noise宽度的背景竖条纹干扰默认8。</param>
* dispersion [in]:true时false时不除色散true /// <param name="indent">轮廓缩进裁剪、纠偏或者黑底填充时对探索到的纸张轮廓进行缩进indent像素默认8</param>
* fx [in]:1.0 /// <param name="normalCrop">为true时m_isCrop m_isDesaskew m_isFillBlank失效固定裁切采用最传统的裁切方式默认false</param>
* fy [in]:1.0 /// <param name="fx">横向缩放比例。默认1.0</param>
*/ /// <param name="fy">纵向缩放比例。默认1.0</param>
CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true, 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(); virtual ~CImageApplyAutoCrop();
@ -105,23 +109,20 @@ public:
void setFixedSize(cv::Size size) { m_fixedSize = size; } 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, 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); double fx = 1.0, double fy = 1.0);
private: 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 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: private:
bool m_isCrop; bool m_isCrop;
bool m_isDesaskew; bool m_isDesaskew;
bool m_isFillBlank; bool m_isFillBlank;
bool m_isConvexHull; bool m_isConvexHull;
bool m_isFillColor; bool m_isFillColor;
bool m_isDispersion;
double m_threshold; double m_threshold;
int m_noise; int m_noise;