mirror of http://192.168.1.51:8099/lmh188/twain3.0
上传背景移除算法
This commit is contained in:
parent
1e8d06e002
commit
b3afcc4382
|
@ -0,0 +1,150 @@
|
||||||
|
#include "ImageApplyFadeBackGroundColor.h"
|
||||||
|
|
||||||
|
|
||||||
|
CImageApplyFadeBackGroudColor::CImageApplyFadeBackGroudColor(int threshold, int offset, int range)
|
||||||
|
: m_threshold(threshold)
|
||||||
|
, m_offset(offset)
|
||||||
|
, m_range(range)
|
||||||
|
{
|
||||||
|
memset(m_table1, 255, 768);
|
||||||
|
memset(m_table1, 0, m_threshold * 3);
|
||||||
|
|
||||||
|
memset(m_table2, 255, 256 * 3);
|
||||||
|
for (size_t i = 0; i < 256; i++)
|
||||||
|
m_table2[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
CImageApplyFadeBackGroudColor::~CImageApplyFadeBackGroudColor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CImageApplyFadeBackGroudColor::apply(cv::Mat& pDib, int side)
|
||||||
|
{
|
||||||
|
if (pDib.channels() != 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
cv::Mat mask;
|
||||||
|
cv::cvtColor(pDib, mask, cv::COLOR_BGR2GRAY);
|
||||||
|
cv::threshold(mask, mask, m_threshold, 255, cv::THRESH_BINARY);
|
||||||
|
//cv::imwrite("mask.jpg", mask);
|
||||||
|
cv::Mat bgr[3];
|
||||||
|
cv::split(pDib, bgr);
|
||||||
|
|
||||||
|
int histSize = 255;
|
||||||
|
float range[] = { 0, 255 };
|
||||||
|
const float* histRange = { range };
|
||||||
|
|
||||||
|
cv::Mat hist_bgr[3];
|
||||||
|
cv::Scalar mean_bgr;
|
||||||
|
for (size_t i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
cv::calcHist(&bgr[i], 1, 0, mask, hist_bgr[i], 1, &histSize, &histRange);
|
||||||
|
double maxVal = 0;
|
||||||
|
cv::Point maxLoc;
|
||||||
|
cv::minMaxLoc(hist_bgr[i], NULL, &maxVal, NULL, &maxLoc);
|
||||||
|
mean_bgr[i] = maxLoc.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::add(pDib, cv::Scalar::all(255 + m_offset) - mean_bgr, pDib, mask);
|
||||||
|
#else
|
||||||
|
fadeBackground(pDib.data, pDib.step, pDib.rows, m_threshold, m_offset, m_range);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CImageApplyFadeBackGroudColor::fadeBackground(unsigned char* data, int bytesPerLine, int height, int threshold, int offset, int range)
|
||||||
|
{
|
||||||
|
int hist_bgr[3][256] = { 0 };
|
||||||
|
|
||||||
|
int width = bytesPerLine / 3;
|
||||||
|
unsigned char* mask = new unsigned char[width * height];
|
||||||
|
unsigned char* ptr_data = data;
|
||||||
|
unsigned char* ptr_mask = mask;
|
||||||
|
|
||||||
|
//创建掩模mask,并且统计三通道的直方图
|
||||||
|
for (size_t i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
unsigned char b = 0;
|
||||||
|
for (size_t j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
b = m_table1[ptr_data[x] + ptr_data[x + 1] + ptr_data[x + 2]];
|
||||||
|
ptr_mask[j] = b;
|
||||||
|
for (size_t k = 0; k < 3; k++)
|
||||||
|
hist_bgr[k][ptr_data[x + k] & b]++;
|
||||||
|
x += 3;
|
||||||
|
}
|
||||||
|
ptr_data += bytesPerLine;
|
||||||
|
ptr_mask += width;
|
||||||
|
}
|
||||||
|
|
||||||
|
//统计背景色
|
||||||
|
int max_vals[3] = { 0 };
|
||||||
|
int max_indexes[3];
|
||||||
|
|
||||||
|
for (size_t i = 1; i < 256; i++)
|
||||||
|
for (size_t j = 0; j < 3; j++)
|
||||||
|
if (hist_bgr[j][i] > max_vals[j])
|
||||||
|
{
|
||||||
|
max_vals[j] = hist_bgr[j][i];
|
||||||
|
max_indexes[j] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建背景色误查值表,在误差±range范围内的颜色被同样视为背景色
|
||||||
|
for (size_t i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
memset(m_table_rgb[i], 0, 256);
|
||||||
|
int start = cv::max(max_indexes[i] - range, 0);
|
||||||
|
int end = cv::min(max_indexes[i] + range, 255);
|
||||||
|
memset(m_table_rgb[i] + start, 255, end - start + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据背景色误差查值表,更新掩模,排除背景色以外的内容
|
||||||
|
ptr_data = data;
|
||||||
|
ptr_mask = mask;
|
||||||
|
for (size_t i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
for (size_t j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
ptr_mask[j] &= m_table_rgb[0][ptr_data[x]] & m_table_rgb[1][ptr_data[x + 1]] & m_table_rgb[2][ptr_data[x + 2]];
|
||||||
|
x += 3;
|
||||||
|
}
|
||||||
|
ptr_data += bytesPerLine;
|
||||||
|
ptr_mask += width;
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据掩模,除背景色
|
||||||
|
unsigned char offset_rgb[3];
|
||||||
|
for (size_t i = 0; i < 3; i++)
|
||||||
|
offset_rgb[i] = 255 + offset - max_indexes[i];
|
||||||
|
|
||||||
|
ptr_data = data;
|
||||||
|
ptr_mask = mask;
|
||||||
|
for (size_t i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
for (size_t j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
for (size_t k = 0; k < 3; k++)
|
||||||
|
ptr_data[x + k] = m_table2[(int)ptr_data[x + k] + (offset_rgb[k] & ptr_mask[j])];
|
||||||
|
x += 3;
|
||||||
|
}
|
||||||
|
ptr_data += bytesPerLine;
|
||||||
|
ptr_mask += width;
|
||||||
|
}
|
||||||
|
delete[] mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CImageApplyFadeBackGroudColor::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||||
|
{
|
||||||
|
(void)isTwoSide;
|
||||||
|
int i = 0;
|
||||||
|
for (cv::Mat& var : mats)
|
||||||
|
if (!var.empty())
|
||||||
|
{
|
||||||
|
apply(var, i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
|
||||||
|
* 功能:消除文稿纸张底色
|
||||||
|
* 作者:刘丁维
|
||||||
|
* 生成时间:2020/11/30
|
||||||
|
* 最近修改时间:2021/04/14 v2.0 改为档位设置
|
||||||
|
* 2021/04/14 v2.1 调整方案,与LINUX方案保持一致。
|
||||||
|
* 2021/08/03 v2.2 自定义获取饱和度算法,避免不同opencv版本结果存在偏差。
|
||||||
|
* 2021/10/12 v2.3 重构算法,去除原来分档设定改为自动识别颜色,并去除底色。
|
||||||
|
* 2021/10/23 v3.0 重构算法。避开黑色背景(制作掩模),计算文稿平均底色,并进行增白。
|
||||||
|
* 2021/10/26 v3.1 构造函数增加参数,可设置生成掩模时的阈值。
|
||||||
|
* 2021/10/28 v3.2 重构算法,改用纯C++代码实现功能,提高处理速度。
|
||||||
|
* 2021/10/29 v3.3 优化算法,增加range参数。针对复杂内容的图像,能够有效甄别背景和非背景内容。
|
||||||
|
* 版本号:v3.2
|
||||||
|
|
||||||
|
* ====================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IMAGE_APPLY_FADE_BACKGROUND_COLOR_H
|
||||||
|
#define IMAGE_APPLY_FADE_BACKGROUND_COLOR_H
|
||||||
|
|
||||||
|
#include "ImageApply.h"
|
||||||
|
|
||||||
|
class CImageApplyAdjustColors;
|
||||||
|
class CImageApplyFadeBackGroudColor : public CImageApply
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">在自动识别增白参数的基础上,增加的偏移量。取值范围[-255, 255]</param>
|
||||||
|
CImageApplyFadeBackGroudColor(int threshold = 100, int offset = 0, int range = 40);
|
||||||
|
|
||||||
|
virtual ~CImageApplyFadeBackGroudColor();
|
||||||
|
|
||||||
|
virtual void apply(cv::Mat& pDib, int side);
|
||||||
|
|
||||||
|
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 除文稿底色算法,仅支持24位图像
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">图像数据头指针</param>
|
||||||
|
/// <param name="bytesPerLine">每行数据大小</param>
|
||||||
|
/// <param name="height">图像高度</param>
|
||||||
|
/// <param name="threshold">阈值,参考值为100</param>
|
||||||
|
/// <param name="offset">文稿底色增亮偏移量,默认为0。值越大,背景越白,反之越暗</param>
|
||||||
|
/// <param name="range">底色误差范围,色彩与识别到的底色误差在[-range, range]范围内,视为底色,否则不会被消除</param>
|
||||||
|
void fadeBackground(unsigned char* data, int bytesPerLine, int height, int threshold, int offset, int range);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_threshold;
|
||||||
|
int m_offset;
|
||||||
|
int m_range;
|
||||||
|
uchar m_table1[768];
|
||||||
|
uchar m_table2[512];
|
||||||
|
uchar m_table_rgb[3][256];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !IMAGE_APPLY_FADE_BACKGROUND_COLOR_H
|
Loading…
Reference in New Issue