twain3/ImageProcess/ImageApplyBWBinaray.cpp

164 lines
4.5 KiB
C++

#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<size_t>(m_threshold));
}
CImageApplyBWBinaray::CImageApplyBWBinaray()
: m_threshold(120)
, m_type(ThresholdType::THRESH_BINARY)
, m_blockSize(25)
, m_constant(5)
, m_table(new uchar[256])
{
memset(m_table, 255, 256);
memset(m_table, 0, static_cast<size_t>(m_threshold));
}
CImageApplyBWBinaray::~CImageApplyBWBinaray(void)
{
delete[] m_table;
}
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);
//20.12.29 修改参数为51 10 30 235
//20.12.30 修改参数为51 20 30 235
// 修改参数为17 20 110 235
cv::Mat integ;
int blockSize = 17;//邻域尺寸
int threshold = 20;
int low = 110;
int up = 235;
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<uchar>(j);
int* idata1 = integ.ptr<int>(j - halfSize);
int* idata2 = integ.ptr<int>(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;
}
}
void CImageApplyBWBinaray::apply(std::vector<cv::Mat>& 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<size_t>(image.rows) - 1;
size_t cols = static_cast<size_t>(image.cols) - 1;
short** pixels_dst = new short* [static_cast<size_t>(image.rows)];
for (int i = 0; i < image.rows; i++)
pixels_dst[i] = reinterpret_cast<short*>(dst.data + i * static_cast<int>(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;
}