消除背景算法更新

This commit is contained in:
13038267101 2023-02-22 11:47:55 +08:00
parent 62d8334646
commit 8664ff90c2
2 changed files with 58 additions and 51 deletions

View File

@ -48,91 +48,97 @@ void CImageApplyFadeBackGroudColor::apply(cv::Mat& pDib, int side)
cv::add(pDib, cv::Scalar::all(255 + m_offset) - mean_bgr, pDib, mask); cv::add(pDib, cv::Scalar::all(255 + m_offset) - mean_bgr, pDib, mask);
#else #else
fadeBackground(pDib.data, pDib.step, pDib.rows, m_threshold, m_offset, m_range); fadeBackground(pDib.data, pDib.cols, pDib.rows, pDib.step, m_threshold, m_offset, m_range);
#endif #endif
} }
void CImageApplyFadeBackGroudColor::fadeBackground(unsigned char* data, int bytesPerLine, int height, int threshold, int offset, int range) /// <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>
void CImageApplyFadeBackGroudColor::fadeBackground(unsigned char* data, int width, int height, int bytesPerLine, int threshold, int offset, int range)
{ {
memset(m_table1, 255, 768);
memset(m_table1, 0, threshold * 3);
memset(m_table2, 255, 256 * 3);
for (uint i = 0; i < 256; i++)
m_table2[i] = i;
int hist_bgr[3][256] = { 0 }; int hist_bgr[3][256] = { 0 };
int width = bytesPerLine / 3;
unsigned char* mask = new unsigned char[width * height]; unsigned char* mask = new unsigned char[width * height];
unsigned char* ptr_data = data; unsigned char* ptr_data = data;
unsigned char* ptr_mask = mask; unsigned char* ptr_mask = mask;
unsigned char b = 0;
//创建掩模mask并且统计三通道的直方图 for (uint i = 0; i < height; i++, ptr_data += bytesPerLine, ptr_mask += width)
for (size_t i = 0; i < height; i++) for (uint j = 0, x = 0; j < width; j++, x += 3)
{
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]]; b = m_table1[ptr_data[x] + ptr_data[x + 1] + ptr_data[x + 2]];
ptr_mask[j] = b; ptr_mask[j] = b;
for (size_t k = 0; k < 3; k++) for (uint k = 0; k < 3; k++)
hist_bgr[k][ptr_data[x + k] & b]++; hist_bgr[k][ptr_data[x + k] & b]++;
x += 3;
} }
ptr_data += bytesPerLine;
ptr_mask += width;
}
//统计背景色
int max_vals[3] = { 0 }; int max_vals[3] = { 0 };
int max_indexes[3] = { 0 }; int max_indexes[3] = { 0 };
for (size_t i = 1; i < 256; i++) for (uint i = 1; i < 256; i++)
for (size_t j = 0; j < 3; j++) for (uint j = 0; j < 3; j++)
if (hist_bgr[j][i] > max_vals[j]) if (hist_bgr[j][i] > max_vals[j])
{ {
max_vals[j] = hist_bgr[j][i]; max_vals[j] = hist_bgr[j][i];
max_indexes[j] = i; max_indexes[j] = i;
} }
//创建背景色误查值表在误差±range范围内的颜色被同样视为背景色 uchar table_rgb[3][256] = { 0 };
for (size_t i = 0; i < 3; i++) for (uint i = 0; i < 3; i++)
{ {
memset(m_table_rgb[i], 0, 256);
int start = cv::max(max_indexes[i] - range, 0); int start = cv::max(max_indexes[i] - range, 0);
int end = cv::min(max_indexes[i] + range, 255); int end = cv::min(max_indexes[i] + range, 255);
memset(m_table_rgb[i] + start, 255, end - start + 1); memset(table_rgb[i] + start, 255, cv::min(end - start + 1, 256 - start));
} }
//根据背景色误差查值表,更新掩模,排除背景色以外的内容
ptr_data = data; ptr_data = data;
ptr_mask = mask; ptr_mask = mask;
for (size_t i = 0; i < height; i++) for (uint i = 0; i < height; i++, ptr_data += bytesPerLine, ptr_mask += width)
{ for (uint j = 0, x = 0; j < width; j++, x += 3)
int x = 0; ptr_mask[j] &= table_rgb[0][ptr_data[x]] & table_rgb[1][ptr_data[x + 1]] & table_rgb[2][ptr_data[x + 2]];
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]; unsigned char offset_rgb[3];
for (size_t i = 0; i < 3; i++) for (uint i = 0; i < 3; i++)
offset_rgb[i] = 255 + offset - max_indexes[i]; offset_rgb[i] = 255 + offset - max_indexes[i];
#if 1
ptr_data = data; ptr_data = data;
ptr_mask = mask; ptr_mask = mask;
for (size_t i = 0; i < height; i++) for (uint i = 0; i < height; i++, ptr_data += bytesPerLine, ptr_mask += width)
{ for (uint j = 0, x = 0; j < width; j++, x += 3)
int x = 0; for (uint k = 0; k < 3; k++)
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])]; ptr_data[x + k] = m_table2[(int)ptr_data[x + k] + (offset_rgb[k] & ptr_mask[j])];
x += 3; #else
for (uint c = 0; c < 3; c++)
{
ptr_data = data + c;
ptr_mask = mask;
for (uint y = 0; y < height; y++)
{
int ptr_x = 0;
for (uint x = 0; x < width; x++)
{
ptr_data[ptr_x] = m_table2[(int)ptr_data[ptr_x] + (offset_rgb[c] & ptr_mask[x])];
ptr_x += 3;
}
ptr_data += bytesPerLine;
ptr_mask += width;
} }
ptr_data += bytesPerLine;
ptr_mask += width;
} }
#endif
delete[] mask; delete[] mask;
} }

View File

@ -13,7 +13,8 @@
* 2021/10/28 v3.2 C++ * 2021/10/28 v3.2 C++
* 2021/10/29 v3.3 range参数 * 2021/10/29 v3.3 range参数
* 2022/03/08 v3.4 BUG * 2022/03/08 v3.4 BUG
* v3.4 * 2022/10/22 v3.5 使opencv ROI的内存机制
* v3.5
* ==================================================== * ====================================================
*/ */
@ -41,24 +42,24 @@ public:
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private: private:
/// <summary> /// <summary>
/// 除文稿底色算法仅支持24位图像 /// 除文稿底色算法仅支持24位图像
/// </summary> /// </summary>
/// <param name="data">图像数据头指针</param> /// <param name="data">图像数据头指针</param>
/// <param name="bytesPerLine">每行数据大小</param> /// <param name="width">图像宽度</param>
/// <param name="height">图像高度</param> /// <param name="height">图像高度</param>
/// <param name="threshold">阈值参考值为100</param> /// <param name="bytesPerLine">每行数据大小</param>
/// <param name="threshold">阈值。区分文稿和黑色背景。取值范围[0, 255],参考值为100</param>
/// <param name="offset">文稿底色增亮偏移量默认为0。值越大背景越白反之越暗</param> /// <param name="offset">文稿底色增亮偏移量默认为0。值越大背景越白反之越暗</param>
/// <param name="range">底色误差范围,色彩与识别到的底色误差在[-range, range]范围内,视为底色,否则不会被消除</param> /// <param name="range">背景色彩的浮动范围。要求大于等于1。值越大范围越大更多的色彩被判定为底色并除色。参考值40</param>
void fadeBackground(unsigned char* data, int bytesPerLine, int height, int threshold, int offset, int range); void fadeBackground(unsigned char* data, int width, int height, int bytesPerLine, int threshold, int offset, int range);
private: private:
int m_threshold; int m_threshold;
int m_offset; int m_offset;
int m_range; int m_range;
uchar m_table1[768]; uchar m_table1[768];
uchar m_table2[512]; uchar m_table2[768];
uchar m_table_rgb[3][256]; uchar m_table_rgb[3][256];
}; };