#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] = (uchar)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 (int i = 0; i < height; i++) { int x = 0; unsigned char b = 0; for (int 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] = { 0 }; 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 (int i = 0; i < height; i++) { int x = 0; for (int 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 (int i = 0; i < height; i++) { int x = 0; for (int 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++; } }