更新防渗透算法,优化效果,支持灰度图防渗透,BUG-769

This commit is contained in:
yangjiaxuan 2023-12-04 18:03:23 +08:00
parent b1b5ed44e0
commit b7b85e44a8
6 changed files with 152 additions and 34 deletions

View File

@ -1,9 +1,9 @@
#include "ImageApplyRefuseInflow.h" #include "ImageApplyRefuseInflow.h"
#include "ImageProcess_Public.h"
CImageApplyRefuseInflow::CImageApplyRefuseInflow(int d, int sigmaColor, int sigmaSpace) CImageApplyRefuseInflow::CImageApplyRefuseInflow(int threshold, int range)
: m_d(d) : m_threshold(threshold)
, m_sigmaColor(sigmaColor) , m_range(range)
, m_sigmaSpace(sigmaSpace)
{ {
} }
@ -13,9 +13,53 @@ CImageApplyRefuseInflow::~CImageApplyRefuseInflow()
void CImageApplyRefuseInflow::apply(cv::Mat& pDib, int side) void CImageApplyRefuseInflow::apply(cv::Mat& pDib, int side)
{ {
cv::Mat dst; if (pDib.channels() == 3)
cv::bilateralFilter(pDib, dst, m_d, m_sigmaColor, m_sigmaSpace); {
pDib = dst; cv::Mat resizeMat;
cv::resize(pDib, resizeMat, cv::Size(200, 200));
cv::Mat mask;
cv::cvtColor(resizeMat, mask, cv::COLOR_BGR2GRAY);
cv::threshold(mask, mask, m_threshold, 255, cv::THRESH_BINARY);
cv::Scalar bgc = hg::getBackGroundColor(resizeMat, mask, m_threshold);
std::vector<int> low, up;
for (size_t i = 0; i < 3; i++)
{
low.push_back(cv::max((int)bgc[i] - m_range, 0));
up.push_back(cv::min((int)bgc[i] + m_range, 255));
}
cv::inRange(pDib, low, up, mask);
pDib = pDib.setTo(bgc, mask);
}
else
{
cv::Mat resizeMat;
cv::resize(pDib, resizeMat, cv::Size(200, 200));
cv::Mat mask;
cv::threshold(resizeMat, mask, m_threshold, 255, cv::THRESH_BINARY);
cv::Mat hist;
double min, max;
cv::Point maxLoc;
float range[] = { 0, 256 };
const float* ranges = { range };
int histSize = 256;
cv::calcHist(&resizeMat, 1, 0, mask, hist, 1, &histSize, &ranges);
int index_max = 0;
int max_value = 0;
for (size_t j = m_threshold; j < 256; j++)
if (hist.at<float>(j) > max_value)
{
index_max = j;
max_value = hist.at<float>(j);
}
cv::inRange(pDib, cv::max(index_max - m_range, 0), cv::min(index_max + m_range, 255), mask);
pDib = pDib.setTo(cv::Scalar::all(index_max), mask);
}
} }
void CImageApplyRefuseInflow::apply(std::vector<cv::Mat>& mats, bool isTwoSide) void CImageApplyRefuseInflow::apply(std::vector<cv::Mat>& mats, bool isTwoSide)

View File

@ -8,7 +8,9 @@
* v1.1 2022/05/04 * v1.1 2022/05/04
* v2.0 2023/08/12 * v2.0 2023/08/12
* v2.1 2023/10/20 BUG * v2.1 2023/10/20 BUG
* v2.1 * v3.0 2023/12/02 稿
* v3.1 2023/12/04
* v3.1
* ==================================================== * ====================================================
*/ */
@ -23,12 +25,11 @@ class GIMGPROC_LIBRARY_API CImageApplyRefuseInflow : public CImageApply
public: public:
/// <summary> /// <summary>
/// 构造函数 ///
/// </summary> /// </summary>
/// <param name="d">邻域的直径。取值范围[0, +∞)</param> /// <param name="threshod">背景阈值.取值范围[0, 255]</param>
/// <param name="sigmaColor">颜色空间滤波器的标准差。取值范围[0, +∞)</param> /// <param name="range">文稿底色相近范围。取值范围[0, 255]</param>
/// <param name="sigmaSpace">空域滤波器的标准差。取值范围[0, +∞。注意当d为0时该参数才生效</param> CImageApplyRefuseInflow(int threshod = 20, int range = 40);
CImageApplyRefuseInflow(int d, int sigmaColor, int sigmaSpace);
virtual ~CImageApplyRefuseInflow(); virtual ~CImageApplyRefuseInflow();
@ -37,8 +38,7 @@ public:
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private: private:
int m_d; int m_threshold;
int m_sigmaColor; int m_range;
int m_sigmaSpace;
}; };
#endif // !IMAGE_APPLY_REFUSE_INFLOW_H #endif // !IMAGE_APPLY_REFUSE_INFLOW_H

View File

@ -1,4 +1,7 @@
#include "ImageProcess_Public.h" #include "ImageProcess_Public.h"
#include <opencv2/core/core_c.h>
#include <opencv2/core/types_c.h>
#include <opencv2/imgproc/imgproc_c.h>
namespace hg namespace hg
{ {
@ -150,14 +153,11 @@ namespace hg
void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset) void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset)
{ {
#if CV_VERSION_REVISION <= 6
CvMat c_image = src;
#else
CvMat c_image; CvMat c_image;
c_image = cvMat(src.rows, src.cols, src.type(), src.data); c_image = cvMat(src.rows, src.cols, src.type(), src.data);
c_image.step = src.step[0]; c_image.step = src.step[0];
c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG); c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG);
#endif
cv::MemStorage storage(cvCreateMemStorage()); cv::MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr; CvSeq* _ccontours = nullptr;
@ -205,6 +205,38 @@ namespace hg
storage.release(); storage.release();
} }
cv::Scalar getBackGroundColor(const cv::Mat& image, const cv::Mat& mask, int threshold)
{
cv::Scalar bgc;
cv::Mat mv[3];
cv::split(image, mv);
float range[] = { 0, 256 };
const float* ranges = { range };
int histSize = 256;
cv::Mat hist[3];
double min, max;
cv::Point maxLoc;
for (int i = 0; i < 3; i++)
{
cv::calcHist(&mv[i], 1, 0, mask, hist[i], 1, &histSize, &ranges);
int index_max = 0;
int max_value = 0;
for (size_t j = threshold; j < 256; j++)
if (hist[i].at<float>(j) > max_value)
{
index_max = j;
max_value = hist[i].at<float>(j);
}
bgc[i] = index_max;
}
return bgc;
}
cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour) cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour)
{ {
if (contour.empty()) return {}; if (contour.empty()) return {};
@ -302,8 +334,11 @@ namespace hg
return dst; return dst;
} }
#define DEFAULT_THRESHOLD 30
#define THRESHOLD_OFFSET 10
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre) void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre)
{ {
cv::Mat temp;
if (src.channels() == 3) if (src.channels() == 3)
{ {
#ifdef USE_ONENCL #ifdef USE_ONENCL
@ -312,13 +347,39 @@ namespace hg
else else
#endif #endif
{ {
cv::Mat gray = transforColor(src); //temp = transforColor(src);
cv::threshold(gray, dst, thre, 255, cv::THRESH_BINARY); cv::cvtColor(src, temp, cv::COLOR_BGR2GRAY);
gray.release();
} }
} }
else else
cv::threshold(src, dst, thre, 255, cv::THRESH_BINARY); temp = src;
if (thre > 0)
cv::threshold(temp, dst, thre, 255, cv::THRESH_BINARY);
else
{
std::vector<int> unusual_cols;
std::vector<uchar> unusual_gray;
uchar* firstLine = temp.ptr<uchar>(0);
uchar* lastLine = temp.ptr<uchar>(temp.rows - 1);
uchar temp_gray;
for (size_t i = 0, length = temp.step; i < length; i++)
{
temp_gray = cv::min(firstLine[i], lastLine[i]);
if (temp_gray > DEFAULT_THRESHOLD)
{
unusual_cols.push_back(i);
unusual_gray.push_back(temp_gray);
}
}
cv::threshold(temp, dst, DEFAULT_THRESHOLD + THRESHOLD_OFFSET, 255, cv::THRESH_BINARY);
for (size_t i = 0; i < unusual_cols.size(); i++)
dst(cv::Rect(unusual_cols[i], 0, 1, temp.rows)) = 0;
}
} }
cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat) cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat)

View File

@ -7,7 +7,11 @@
* 2020/4/21 * 2020/4/21
* 2021/07/12 v1.1 getBoundingRect中 angle > 90 * 2021/07/12 v1.1 getBoundingRect中 angle > 90
* 2021/07/22 v1.2 convexHull中BUG * 2021/07/22 v1.2 convexHull中BUG
* v1.2 * 2023/11/02 v1.3 threshold_Mat,thre<0
* 2023/12/01 v1.4 getBackGroundColor算法
* 2023/12/02 v1.4.1 getBackGroundColor增加threshold阈值
* 2023/12/04 v1.4.2 opencv版本接口
* v1.4.2
* ==================================================== * ====================================================
*/ */
@ -55,6 +59,15 @@ namespace hg
void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy,
int retr = cv::RETR_LIST, int method = cv::CHAIN_APPROX_SIMPLE, cv::Point offset = cv::Point(0, 0)); int retr = cv::RETR_LIST, int method = cv::CHAIN_APPROX_SIMPLE, cv::Point offset = cv::Point(0, 0));
/// <summary>
/// 获取图片文稿底色
/// </summary>
/// <param name="image">图像,三通道</param>
/// <param name="mask">掩膜</param>
/// <param name="threshold">阈值,用于排除黑色背景</param>
/// <returns>文稿底色</returns>
cv::Scalar getBackGroundColor(const cv::Mat& image, const cv::Mat& mask = cv::Mat(), int threshold = 20);
/* /*
* *
* contour: * contour:
@ -90,7 +103,7 @@ namespace hg
* : src为彩色图像时 * : src为彩色图像时
* src: * src:
* dst: * dst:
* thre: * thre: thre < 0
*/ */
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre); void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre);

View File

@ -5294,15 +5294,15 @@ void hg_scanner::image_process(std::shared_ptr<tiny_buffer>& buffer, uint32_t id
int lv = image_prc_param_.bits.is_permeate_lv_; //image_prc_param_.bits.is_permeate_lv_ = 0 1 2 3 4 int lv = image_prc_param_.bits.is_permeate_lv_; //image_prc_param_.bits.is_permeate_lv_ = 0 1 2 3 4
if (0 == lv) if (0 == lv)
lv = 3; lv = 20;
else if (1 == lv) else if (1 == lv)
lv = 5; lv = 30;
else if (2 == lv) else if (2 == lv)
lv = 7; lv = 40;
else if (3 == lv) else if (3 == lv)
lv = 9; lv = 50;
else if (4 == lv) else if (4 == lv)
lv = 11; lv = 60;
hg_imgproc::antiInflow(ImagePrc_pHandle_, lv); hg_imgproc::antiInflow(ImagePrc_pHandle_, lv);
(this->*dump_img_)(ImagePrc_pHandle_, "antiInflow"); (this->*dump_img_)(ImagePrc_pHandle_, "antiInflow");

View File

@ -989,7 +989,7 @@ namespace hg_imgproc
std::vector<cv::Mat> mats(mats_); std::vector<cv::Mat> mats(mats_);
mats_.clear(); mats_.clear();
CImageApplyRefuseInflow Inflow(permeate_lv, 200, 200); CImageApplyRefuseInflow Inflow(20, permeate_lv);
for (size_t i = 0; i < mats.size(); ++i) for (size_t i = 0; i < mats.size(); ++i)
{ {
Inflow.apply(mats[i],img_conf_.is_duplex); Inflow.apply(mats[i],img_conf_.is_duplex);