This commit is contained in:
13038267101 2023-11-30 10:53:24 +08:00
commit ef3792b131
7 changed files with 108 additions and 95 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;

View File

@ -1,28 +1,5 @@
#include "ImageApplyColorRecognition.h" #include "ImageApplyColorRecognition.h"
/// <summary>
/// 检测图像是否是彩色。当前逻辑仅针对红色像素进行判断,即存在红色像素则为彩色,否则为非彩色
/// </summary>
/// <param name="image">待测图像</param>
/// <returns>true为彩色false为非彩色</returns>
bool isColor(const cv::Mat& image, double threshold = 60)
{
if (image.channels() != 3) return false;
cv::Mat pDib_resize;
cv::resize(image, pDib_resize, cv::Size(200, 200), 0, 0, cv::INTER_AREA);
cv::Mat hsv;
cv::cvtColor(pDib_resize, hsv, cv::COLOR_BGR2HSV_FULL);
std::vector<cv::Mat> hsv_channels;
cv::split(hsv, hsv_channels);
double minVal, maxVal;
cv::minMaxLoc(hsv_channels[1], &minVal, &maxVal);
return maxVal > threshold;
}
bool isGray(const cv::Mat& image) bool isGray(const cv::Mat& image)
{ {
//if (image.channels() == 3) return true; //if (image.channels() == 3) return true;
@ -62,6 +39,7 @@ CImageApplyColorRecognition::~CImageApplyColorRecognition(void)
{ {
} }
#define HSV_S_THRE 30
void CImageApplyColorRecognition::apply(cv::Mat& pDib, int side) void CImageApplyColorRecognition::apply(cv::Mat& pDib, int side)
{ {
if (pDib.channels() != 3) if (pDib.channels() != 3)
@ -69,7 +47,7 @@ void CImageApplyColorRecognition::apply(cv::Mat& pDib, int side)
m_result = Gray; m_result = Gray;
return; return;
} }
m_result = isColor(pDib) ? Color : Gray; m_result = isColor(pDib, HSV_S_THRE) ? Color : Gray;
if (m_result == Gray && pDib.channels() == 3) if (m_result == Gray && pDib.channels() == 3)
cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY); cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
@ -135,3 +113,26 @@ std::vector<CImageApplyColorRecognition::ColorType> CImageApplyColorRecognition:
{ {
return m_results; return m_results;
} }
/// <summary>
/// 检测图像是否是彩色。当前逻辑仅针对红色像素进行判断,即存在红色像素则为彩色,否则为非彩色
/// </summary>
/// <param name="image">待测图像</param>
/// <returns>true为彩色false为非彩色</returns>
bool CImageApplyColorRecognition::isColor(const cv::Mat& image, double threshold)
{
if (image.channels() != 3) return false;
cv::Mat pDib_resize;
cv::resize(image, pDib_resize, cv::Size(200, 200), 0, 0, cv::INTER_AREA);
//cv::imwrite("pDib_resize.bmp", pDib_resize);
cv::Mat hsv;
cv::cvtColor(pDib_resize, hsv, cv::COLOR_BGR2HSV_FULL);
std::vector<cv::Mat> hsv_channels;
cv::split(hsv, hsv_channels);
double minVal, maxVal;
cv::minMaxLoc(hsv_channels[1], &minVal, &maxVal);
return maxVal > threshold;
}

View File

@ -10,7 +10,8 @@
* v1.3 2021/04/19 1 * v1.3 2021/04/19 1
* v1.4 2021/06/18 [90, 200][50, 200] * v1.4 2021/06/18 [90, 200][50, 200]
* v1.5 2023/11/22 * v1.5 2023/11/22
* v1.5 * v1.5.1 2023//11/28 调整饱和度判定阈值
* v1.5.1
* ==================================================== * ====================================================
*/ */
@ -60,6 +61,9 @@ public:
/// <returns>色彩类型数组</returns> /// <returns>色彩类型数组</returns>
std::vector<ColorType> getResults(); std::vector<ColorType> getResults();
private:
bool isColor(const cv::Mat& image, double threshold = 30);
private: private:
ColorType m_result; ColorType m_result;
std::vector<ColorType> m_results; std::vector<ColorType> m_results;

View File

@ -212,7 +212,7 @@ void CImageApplyOutHole::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
for (size_t i = 0; i < hole_contours.size(); i++) for (size_t i = 0; i < hole_contours.size(); i++)
{ {
std::vector<std::vector<cv::Point>> contourss_temp; std::vector<std::vector<cv::Point>> contourss_temp;
dilateContour(hole_contours[i], 5); dilateContour(hole_contours[i], m_borderSize / 4);
contourss_temp.push_back(hole_contours[i]); contourss_temp.push_back(hole_contours[i]);
cv::Mat front_temp = mats[0](roi_front); cv::Mat front_temp = mats[0](roi_front);
hg::fillPolys(front_temp, contourss_temp, color); hg::fillPolys(front_temp, contourss_temp, color);

View File

@ -27,7 +27,8 @@
* 2022/11/17 v1.9.2 BUG * 2022/11/17 v1.9.2 BUG
* 2023/05/16 v1.9.3 BUG * 2023/05/16 v1.9.3 BUG
* 2023/11/18 v1.10 * 2023/11/18 v1.10
* v1.10 * 2023/11/28 v1.10.1 kSize根据borderSize调整
* v1.10.1
* ==================================================== * ====================================================
*/ */

View File

@ -737,7 +737,10 @@ int hg_scanner_300::set_kernelsnap_ver()
if (atoi(fw.substr(4, 6).c_str()) >= 221106 && atoi(fw.substr(4, 6).c_str()) < 230210) if (atoi(fw.substr(4, 6).c_str()) >= 221106 && atoi(fw.substr(4, 6).c_str()) < 230210)
firmware_sup_dpi_300 = true; firmware_sup_dpi_300 = true;
else if (atoi(fw.substr(4, 6).c_str()) >= 230210) else if (atoi(fw.substr(4, 6).c_str()) >= 230210)
{
firmware_sup_dpi_300 = true;
firmware_sup_dpi_600 = true; firmware_sup_dpi_600 = true;
}
else else
{ {
firmware_sup_dpi_300 = false; firmware_sup_dpi_300 = false;