From b3afcc43820a49029490ad3b6a1855a248d59f17 Mon Sep 17 00:00:00 2001 From: masayume <1936714878@qq.com> Date: Mon, 14 Feb 2022 10:49:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E8=83=8C=E6=99=AF=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ImageApplyFadeBackGroundColor.cpp | 150 ++++++++++++++++++ .../ImageApplyFadeBackGroundColor.h | 64 ++++++++ 2 files changed, 214 insertions(+) create mode 100644 huagao/ImageProcess/ImageApplyFadeBackGroundColor.cpp create mode 100644 huagao/ImageProcess/ImageApplyFadeBackGroundColor.h diff --git a/huagao/ImageProcess/ImageApplyFadeBackGroundColor.cpp b/huagao/ImageProcess/ImageApplyFadeBackGroundColor.cpp new file mode 100644 index 00000000..d66e9869 --- /dev/null +++ b/huagao/ImageProcess/ImageApplyFadeBackGroundColor.cpp @@ -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& mats, bool isTwoSide) +{ + (void)isTwoSide; + int i = 0; + for (cv::Mat& var : mats) + if (!var.empty()) + { + apply(var, i); + i++; + } +} + diff --git a/huagao/ImageProcess/ImageApplyFadeBackGroundColor.h b/huagao/ImageProcess/ImageApplyFadeBackGroundColor.h new file mode 100644 index 00000000..792a72b7 --- /dev/null +++ b/huagao/ImageProcess/ImageApplyFadeBackGroundColor.h @@ -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: + /// + /// 构造函数 + /// + /// 在自动识别增白参数的基础上,增加的偏移量。取值范围[-255, 255] + 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& mats, bool isTwoSide); + +private: + + /// + /// 除文稿底色算法,仅支持24位图像 + /// + /// 图像数据头指针 + /// 每行数据大小 + /// 图像高度 + /// 阈值,参考值为100 + /// 文稿底色增亮偏移量,默认为0。值越大,背景越白,反之越暗 + /// 底色误差范围,色彩与识别到的底色误差在[-range, range]范围内,视为底色,否则不会被消除 + 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