164 lines
4.5 KiB
C++
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 <20>IJ<DEB8><C4B2><EFBFBD>Ϊ51 10 30 235
|
|||
|
//20.12.30 <20>IJ<DEB8><C4B2><EFBFBD>Ϊ51 20 30 235
|
|||
|
// <20>IJ<DEB8><C4B2><EFBFBD>Ϊ17 20 110 235
|
|||
|
cv::Mat integ;
|
|||
|
int blockSize = 17;//<2F><><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD>
|
|||
|
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;
|
|||
|
}
|