更新防渗透算法,优化效果,支持灰度图防渗透,BUG-769
This commit is contained in:
parent
b1b5ed44e0
commit
b7b85e44a8
|
@ -1,9 +1,9 @@
|
|||
#include "ImageApplyRefuseInflow.h"
|
||||
#include "ImageProcess_Public.h"
|
||||
|
||||
CImageApplyRefuseInflow::CImageApplyRefuseInflow(int d, int sigmaColor, int sigmaSpace)
|
||||
: m_d(d)
|
||||
, m_sigmaColor(sigmaColor)
|
||||
, m_sigmaSpace(sigmaSpace)
|
||||
CImageApplyRefuseInflow::CImageApplyRefuseInflow(int threshold, int range)
|
||||
: m_threshold(threshold)
|
||||
, m_range(range)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,53 @@ CImageApplyRefuseInflow::~CImageApplyRefuseInflow()
|
|||
|
||||
void CImageApplyRefuseInflow::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
cv::Mat dst;
|
||||
cv::bilateralFilter(pDib, dst, m_d, m_sigmaColor, m_sigmaSpace);
|
||||
pDib = dst;
|
||||
if (pDib.channels() == 3)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
* v1.1 2022/05/04 重构算法,采用提高对比度实现防渗透。
|
||||
* v2.0 2023/08/12 筹够算法,采用双边滤波实现防渗透。
|
||||
* 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:
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="d">邻域的直径。取值范围[0, +∞)</param>
|
||||
/// <param name="sigmaColor">颜色空间滤波器的标准差。取值范围[0, +∞)</param>
|
||||
/// <param name="sigmaSpace">空域滤波器的标准差。取值范围[0, +∞)。注意当d为0时,该参数才生效</param>
|
||||
CImageApplyRefuseInflow(int d, int sigmaColor, int sigmaSpace);
|
||||
/// <param name="threshod">背景阈值.取值范围[0, 255]</param>
|
||||
/// <param name="range">文稿底色相近范围。取值范围[0, 255]</param>
|
||||
CImageApplyRefuseInflow(int threshod = 20, int range = 40);
|
||||
|
||||
virtual ~CImageApplyRefuseInflow();
|
||||
|
||||
|
@ -37,8 +38,7 @@ public:
|
|||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
private:
|
||||
int m_d;
|
||||
int m_sigmaColor;
|
||||
int m_sigmaSpace;
|
||||
int m_threshold;
|
||||
int m_range;
|
||||
};
|
||||
#endif // !IMAGE_APPLY_REFUSE_INFLOW_H
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#include "ImageProcess_Public.h"
|
||||
#include <opencv2/core/core_c.h>
|
||||
#include <opencv2/core/types_c.h>
|
||||
#include <opencv2/imgproc/imgproc_c.h>
|
||||
|
||||
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)
|
||||
{
|
||||
#if CV_VERSION_REVISION <= 6
|
||||
CvMat c_image = src;
|
||||
#else
|
||||
CvMat c_image;
|
||||
c_image = cvMat(src.rows, src.cols, src.type(), src.data);
|
||||
c_image.step = src.step[0];
|
||||
c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG);
|
||||
#endif
|
||||
|
||||
cv::MemStorage storage(cvCreateMemStorage());
|
||||
CvSeq* _ccontours = nullptr;
|
||||
|
||||
|
@ -205,6 +205,38 @@ namespace hg
|
|||
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)
|
||||
{
|
||||
if (contour.empty()) return {};
|
||||
|
@ -302,8 +334,11 @@ namespace hg
|
|||
return dst;
|
||||
}
|
||||
|
||||
#define DEFAULT_THRESHOLD 30
|
||||
#define THRESHOLD_OFFSET 10
|
||||
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre)
|
||||
{
|
||||
cv::Mat temp;
|
||||
if (src.channels() == 3)
|
||||
{
|
||||
#ifdef USE_ONENCL
|
||||
|
@ -312,13 +347,39 @@ namespace hg
|
|||
else
|
||||
#endif
|
||||
{
|
||||
cv::Mat gray = transforColor(src);
|
||||
cv::threshold(gray, dst, thre, 255, cv::THRESH_BINARY);
|
||||
gray.release();
|
||||
//temp = transforColor(src);
|
||||
cv::cvtColor(src, temp, cv::COLOR_BGR2GRAY);
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
* 最近修改时间:2020/4/21
|
||||
* 2021/07/12 v1.1 getBoundingRect中,增加考虑纠正初始 angle > 90 的情况。
|
||||
* 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,
|
||||
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: 点集
|
||||
|
@ -90,7 +103,7 @@ namespace hg
|
|||
* 功能: 二值化,能够处理彩色和灰度图像。src为彩色图像时,灰度图取三个通道的最大值
|
||||
* src: 源图
|
||||
* dst: 目标图
|
||||
* thre: 阈值
|
||||
* thre: 阈值。当thre < 0时,采用背景色作为每列自适应阈值。
|
||||
*/
|
||||
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
if (0 == lv)
|
||||
lv = 3;
|
||||
lv = 20;
|
||||
else if (1 == lv)
|
||||
lv = 5;
|
||||
lv = 30;
|
||||
else if (2 == lv)
|
||||
lv = 7;
|
||||
lv = 40;
|
||||
else if (3 == lv)
|
||||
lv = 9;
|
||||
lv = 50;
|
||||
else if (4 == lv)
|
||||
lv = 11;
|
||||
lv = 60;
|
||||
|
||||
hg_imgproc::antiInflow(ImagePrc_pHandle_, lv);
|
||||
(this->*dump_img_)(ImagePrc_pHandle_, "antiInflow");
|
||||
|
|
|
@ -989,7 +989,7 @@ namespace hg_imgproc
|
|||
std::vector<cv::Mat> mats(mats_);
|
||||
mats_.clear();
|
||||
|
||||
CImageApplyRefuseInflow Inflow(permeate_lv, 200, 200);
|
||||
CImageApplyRefuseInflow Inflow(20, permeate_lv);
|
||||
for (size_t i = 0; i < mats.size(); ++i)
|
||||
{
|
||||
Inflow.apply(mats[i],img_conf_.is_duplex);
|
||||
|
|
Loading…
Reference in New Issue