uv-twain/huagao/ImageProcess/ImageApplyBWBinaray.cpp

534 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//#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(180)
// , 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)
//{
//#ifdef LOG
// FileTools::write_log("imgprc.txt", "enter CImageApplyBWBinaray apply");
//#endif // LOG
// if (pDib.empty())
// {
//#ifdef LOG
// FileTools::write_log("imgprc.txt", "exit CImageApplyBWBinaray apply");
//#endif // LOG
// return;
// }
//
// if (pDib.channels() == 3)
// cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
//
// switch (m_type)
// {
// case ThresholdType::THRESH_BINARY:
// //cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_BINARY);
// cv::adaptiveThreshold(pDib, pDib, 255.0, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 91, 41);
// 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<cv::Mat>& mats, bool isTwoSide)
//{
// if (mats.empty()) return;
//
// if (!mats[0].empty()) {
// apply(mats[0], 0);
// }
//
//
// if (isTwoSide && mats.size() > 1) {
// if (!mats[1].empty())
// apply(mats[1], 1);
// }
//}
//
//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 * 7 / 16;
// pixels_dst[y + 1][x - 1] += error * 3 / 16;
// pixels_dst[y + 1][x] += error * 5 / 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;
//}
#include "ImageApplyBWBinaray.h"
typedef struct image_info
{
int32_t width;
int32_t height;
uint8_t* data;
}ImageInfo;
void updataIntergralImg(const uint8_t* const imgData, uint32_t* integralImg, const int32_t& width, const int32_t& height)
{
// create the integral image
//<2F><><EFBFBD><EFBFBD>ͼ<EFBFBD>񽫴<EFBFBD><F1BDABB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD>תΪ<D7AA><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD>
uint32_t sum = 0;
int32_t i, j;
const uint32_t* img = (uint32_t*)imgData;
uint32_t* interImgTmp = integralImg;
uint32_t tmp = 0;
for (i = 0; i < width; i += 4)
{
tmp = *img;
sum += tmp & 0x000000ff;//unportble
interImgTmp[0] = sum;
interImgTmp++;
sum += (tmp >> 8) & 0x000000ff;
interImgTmp[0] = sum;
interImgTmp++;
sum += (tmp >> 16) & 0x000000ff;
interImgTmp[0] = sum;
interImgTmp++;
sum += (tmp >> 24) & 0x000000ff;
interImgTmp[0] = sum;
interImgTmp++;
img++;
}
for (i = 1; i < height; ++i)
{
sum = 0;
for (j = 0; j < width; j += 4)
{
tmp = *img;
sum += tmp & 0x000000ff;
interImgTmp[0] = sum + interImgTmp[-width];
interImgTmp++;
sum += (tmp >> 8) & 0x000000ff;
interImgTmp[0] = sum + interImgTmp[-width];
interImgTmp++;
sum += (tmp >> 16) & 0x000000ff;
interImgTmp[0] = sum + interImgTmp[-width];
interImgTmp++;
sum += (tmp >> 24) & 0x000000ff;
interImgTmp[0] = sum + interImgTmp[-width];
interImgTmp++;
img++;
}
}
}
void threshold(ImageInfo& image_src, uint8_t thre)
{
uint8_t table[256];
memset(table, 0, thre);
memset(table + thre, 255, 256 - thre);
int32_t size = image_src.width * image_src.height;
uint8_t* ptr = image_src.data;
for (int32_t i = 0; i < size; i++)
{
ptr[i] = table[ptr[i]];
}
}
void adaptivethresh(ImageInfo& image_src, const uint8_t& lowThr, const uint8_t& upThr, const uint8_t& init_threshold)
{
//<2F><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>μ<EFBFBD>welner<65><72><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ֵ<EFBFBD><EFBFBD><E3B7A8><EFBFBD>޸IJ<DEB8><C4B2><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ĸ<EFBFBD><C4B8>߽<EFBFBD><DFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><E3A3AC><EFBFBD>IJ<EFBFBD><C4B2>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3A3AC><EFBFBD><EFBFBD>ħ<EFBFBD><C4A7>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ֵ
const uint8_t thresh = __min(init_threshold, 100);
uint8_t S = 17;
unsigned short T = 100 - thresh;
T = (unsigned short)((float)T * 10.24);
unsigned short i, j;
uint32_t sum = 0;
unsigned short count = 0;
int16_t x1, y1, x2, y2;
const uint8_t s2 = S >> 1;
uint8_t* pointer = image_src.data;
//pointer = image_src;
const int32_t width = image_src.width;
const int32_t height = image_src.height;
uint32_t* integralImg = new uint32_t[width * height];//<2F><><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ֵ<EFBFBD>
updataIntergralImg(image_src.data, integralImg, width, height);
uint8_t t = 0;
ImageInfo img_up_dwon;
img_up_dwon.data = pointer;
img_up_dwon.width = width;
img_up_dwon.height = s2 + 1;
threshold(img_up_dwon, init_threshold);
pointer = image_src.data;
pointer += (height - s2) * width;
img_up_dwon.data = pointer;
img_up_dwon.width = width;
img_up_dwon.height = s2;
threshold(img_up_dwon, init_threshold);
pointer = image_src.data + (s2 + 1) * width;
for (i = 0; i <= s2; ++i)
{
for (j = s2 + 1; j < height - s2; ++j)
{
if (pointer[0] < init_threshold)
{
pointer[0] = 0;
}
else
{
pointer[0] = 255;
}
pointer += width;
}
pointer = image_src.data + (s2 + 1) * width + i + 1;
}
pointer = image_src.data + (s2 + 1) * width + (width - s2);
unsigned short ii = 1;
for (i = width - s2; i < width; ++i)
{
for (j = s2 + 1; j < height - s2; ++j)
{
if (pointer[0] < init_threshold)
{
pointer[0] = 0;
}
else
{
pointer[0] = 255;
}
pointer += width;
}
pointer = image_src.data + (s2 + 1) * width + (width - s2) + ii;
ii++;
}
///center part
unsigned short ww = width - s2 - s2 - 1;
unsigned short hh = height - s2 - s2 - 1;
uint8_t gap = width - ww;
count = (s2 << 1) + 1;
count *= count;
const uint32_t factor = count * 100 / (100 - 50);
uint32_t* plt;
uint32_t* prt;
uint32_t* plb;
uint32_t* prb;
plt = integralImg;
prt = plt + (s2 << 1) + 1;
plb = plt + ((s2 << 1) + 1) * width;
prb = prt + ((s2 << 1) + 1) * width;
pointer = image_src.data + (s2 + 1) * width + s2 + 1;
for (i = 0; i < hh; ++i)
{
for (j = 0; j < ww; j++)
{
if (/*expected_true(*/*pointer >= upThr/*)*/)
{
*pointer = 255;
}
else if (*pointer < lowThr)
{
*pointer = 0;
}
else
{
sum = *prb - *prt - *plb + *plt;
t = *pointer;
if (/*expected_false(*/t * factor <= sum/*)*/)
*pointer = 0;
else
*pointer = 255;
}
plt++;
prt++;
plb++;
prb++;
pointer++;
}
plt += gap;
prt += gap;
plb += gap;
prb += gap;
pointer += width - ww;
}
delete[]integralImg;
}
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(160)
, 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);
switch (m_type)
{
case ThresholdType::THRESH_BINARY:
{
//ImageInfo info;
//info.data = pDib.data;
//info.width = pDib.step;
//info.height = pDib.rows;
//adaptivethresh(info, 80, 255, 127);
cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_BINARY);
//cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 91, 21);
//cv::Mat integ;
//cv::integral(pDib, integ, CV_32S);
//int blockSize = 30;//<2F><><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD>
//int threshold = 4;
//int low = 115;
//int up = 200;
//int halfSize = blockSize / 2;
//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++)
// {
// int sum = (idata2[i + halfSize + 1] - idata2[i - halfSize] - idata1[i + halfSize + 1] + idata1[i - halfSize]) / (blockSize * blockSize);
// if (data[i] < low) data[i] = 0;
// else if (data[i] > up) data[i] = 255;
// else
// {
// if (data[i] < (sum - threshold))
// data[i] = 0;
// else
// data[i] = 255;
// }
// }
//}
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<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 * 7 / 16;
pixels_dst[y + 1][x - 1] += error * 3 / 16;
pixels_dst[y + 1][x] += error * 5 / 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;
}