code_device/hgdriver/ImageProcess/ImageApplyFadeBackGroundCol...

157 lines
4.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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.cols, pDib.rows, pDib.step, m_threshold, m_offset, m_range);
#endif
}
/// <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 };
unsigned char* mask = new unsigned char[width * height];
unsigned char* ptr_data = data;
unsigned char* ptr_mask = mask;
unsigned char b = 0;
for (uint i = 0; i < height; i++, ptr_data += bytesPerLine, ptr_mask += width)
for (uint j = 0, x = 0; j < width; j++, x += 3)
{
b = m_table1[ptr_data[x] + ptr_data[x + 1] + ptr_data[x + 2]];
ptr_mask[j] = b;
for (uint k = 0; k < 3; k++)
hist_bgr[k][ptr_data[x + k] & b]++;
}
int max_vals[3] = { 0 };
int max_indexes[3] = { 0 };
for (uint i = 1; i < 256; i++)
for (uint j = 0; j < 3; j++)
if (hist_bgr[j][i] > max_vals[j])
{
max_vals[j] = hist_bgr[j][i];
max_indexes[j] = i;
}
uchar table_rgb[3][256] = { 0 };
for (uint i = 0; i < 3; i++)
{
int start = cv::max(max_indexes[i] - range, 0);
int end = cv::min(max_indexes[i] + range, 255);
memset(table_rgb[i] + start, 255, cv::min(end - start + 1, 256 - start));
}
ptr_data = data;
ptr_mask = mask;
for (uint i = 0; i < height; i++, ptr_data += bytesPerLine, ptr_mask += width)
for (uint j = 0, x = 0; j < width; j++, x += 3)
ptr_mask[j] &= table_rgb[0][ptr_data[x]] & table_rgb[1][ptr_data[x + 1]] & table_rgb[2][ptr_data[x + 2]];
unsigned char offset_rgb[3];
for (uint i = 0; i < 3; i++)
offset_rgb[i] = 255 + offset - max_indexes[i];
#if 1
ptr_data = data;
ptr_mask = mask;
for (uint i = 0; i < height; i++, ptr_data += bytesPerLine, ptr_mask += width)
for (uint j = 0, x = 0; j < width; j++, x += 3)
for (uint k = 0; k < 3; k++)
ptr_data[x + k] = m_table2[(int)ptr_data[x + k] + (offset_rgb[k] & ptr_mask[j])];
#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;
}
}
#endif
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++;
}
}