#include "ImageApplyBWBinaray.h" CImageApplyBWBinaray::CImageApplyBWBinaray(ThresholdType type, int threshold, int blockSize, int constant) : m_threshold(threshold) , m_type(type) , m_blockSize(blockSize) , m_constant(constant) , m_table(new uchar[256]) { memset(m_table, 255, 256); memset(m_table, 0, static_cast(m_threshold)); } CImageApplyBWBinaray::CImageApplyBWBinaray() : m_threshold(120) , m_type(ThresholdType::THRESH_BINARY) , m_blockSize(51) , m_constant(41) , m_table(new uchar[256]) { memset(m_table, 255, 256); memset(m_table, 0, static_cast(m_threshold)); } CImageApplyBWBinaray::~CImageApplyBWBinaray(void) { delete[] m_table; } #define THRESHOLD_LOW 30 #define THRESHOLD_UP 245 void CImageApplyBWBinaray::apply(cv::Mat& pDib, int side) { (void)side; if (pDib.empty()) return; if (pDib.channels() == 3) cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY); cv::Mat integ; int blockSize = m_blockSize;//邻域尺寸 int threshold = m_constant; int low = THRESHOLD_LOW; int up = THRESHOLD_UP; int halfSize = blockSize / 2; int square_blockSize = blockSize * blockSize; switch (m_type) { case ThresholdType::THRESH_BINARY: cv::integral(pDib, integ, CV_32S); for (int j = halfSize; j < integ.rows - halfSize - 1; j++) { uchar* data = pDib.ptr(j); int* idata1 = integ.ptr(j - halfSize); int* idata2 = integ.ptr(j + halfSize + 1); for (int i = halfSize; i < integ.cols - halfSize - 1; i++) { if (data[i] < low) data[i] = 0; else if (data[i] > up) data[i] = 255; else data[i] = data[i] < ((idata2[i + halfSize + 1] - idata2[i - halfSize] - idata1[i + halfSize + 1] + idata1[i - halfSize]) / square_blockSize - threshold) ? 0 : 255; } } cv::threshold(pDib(cv::Rect(0, 0, halfSize, pDib.rows)), pDib(cv::Rect(0, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY); cv::threshold(pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY); cv::threshold(pDib(cv::Rect(0, 0, pDib.cols, halfSize)), pDib(cv::Rect(0, 0, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY); cv::threshold(pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY); break; case ThresholdType::THRESH_OTSU: cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_OTSU); break; case ThresholdType::ADAPTIVE_GAUSSIAN: cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, m_blockSize, m_constant); break; case ThresholdType::ADAPTIVE_MEAN: cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, m_blockSize, m_constant); break; case ThresholdType::ERROR_DIFFUSION: errorDiffuse(pDib); break; default: break; } #ifdef LOG FileTools::write_log("imgprc.txt", "exit CImageApplyBWBinaray apply"); #endif // LOG } void CImageApplyBWBinaray::apply(std::vector& mats, bool isTwoSide) { (void)isTwoSide; int i = 0; for (cv::Mat& var : mats) { if (i != 0 && isTwoSide == false) break; if (!var.empty()) apply(var, 0); i++; } } void CImageApplyBWBinaray::errorDiffuse(cv::Mat& image) { if (image.rows < 3 || image.cols < 3) { cv::threshold(image, image, m_threshold, 255, CV_THRESH_BINARY); return; } cv::Mat dst; image.convertTo(dst, CV_16S); size_t rows = static_cast(image.rows) - 1; size_t cols = static_cast(image.cols) - 1; short** pixels_dst = new short* [static_cast(image.rows)]; for (int i = 0; i < image.rows; i++) pixels_dst[i] = reinterpret_cast(dst.data + i * static_cast(dst.step)); short error; for (size_t y = 0; y < rows; y++) for (size_t x = 1; x < cols; x++) { short dstPix = pixels_dst[y][x]; if (dstPix >= m_threshold) { pixels_dst[y][x] = 255; error = dstPix - 255; } else { pixels_dst[y][x] = 0; error = dstPix; } pixels_dst[y][x + 1] += error * 1 / 16; pixels_dst[y + 1][x - 1] += error * 1 / 16; pixels_dst[y + 1][x] += error * 1 / 16; pixels_dst[y + 1][x + 1] += error * 1 / 16; } image.release(); dst.convertTo(image, CV_8U); rows++; uchar* ptr = image.data; size_t step = image.step; size_t offset; for (size_t y = 0; y < rows; y++) { offset = y * step; ptr[offset] = m_table[ptr[offset]]; offset += cols; ptr[offset] = m_table[ptr[offset]]; } cols++; ptr = image.data + step * (rows - 1); for (size_t x = 0; x < cols; x++) ptr[x] = m_table[ptr[x]]; delete[] pixels_dst; }