diff --git a/huagao/ImageProcess/ImageApplyBWBinaray.cpp b/huagao/ImageProcess/ImageApplyBWBinaray.cpp index 39cdfdbc..7dfee1da 100644 --- a/huagao/ImageProcess/ImageApplyBWBinaray.cpp +++ b/huagao/ImageProcess/ImageApplyBWBinaray.cpp @@ -1,366 +1,5 @@ -//#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(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(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& 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(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 * 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" -#include "ImageProcess_Public.h" -#include "StopWatch.h" -#include "filetools.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 - //积分图像将窗口内像素值和计算时间由二阶转为常量,窗口越大,效果越明显 - - 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) -{ - - //基本原理参见welner自适应阈值算法,修改部分为将四个边界事先计算,中心部分单独计算,所有魔数为经验值 - 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];//积分图,用于自适应二值算法 - - 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; -} - +#include "ImageApplyDetachNoise.h" CImageApplyBWBinaray::CImageApplyBWBinaray(ThresholdType type, int threshold, int blockSize, int constant) : m_threshold(threshold) @@ -374,7 +13,7 @@ CImageApplyBWBinaray::CImageApplyBWBinaray(ThresholdType type, int threshold, in } CImageApplyBWBinaray::CImageApplyBWBinaray() - : m_threshold(160) + : m_threshold(120) , m_type(ThresholdType::THRESH_BINARY) , m_blockSize(25) , m_constant(5) @@ -384,7 +23,6 @@ CImageApplyBWBinaray::CImageApplyBWBinaray() memset(m_table, 0, static_cast(m_threshold)); } - CImageApplyBWBinaray::~CImageApplyBWBinaray(void) { delete[] m_table; @@ -398,42 +36,19 @@ void CImageApplyBWBinaray::apply(cv::Mat& pDib, int side) if (pDib.channels() == 3) cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY); + cv::Mat integ; + int blockSize = 31;//邻域尺寸 + int threshold = 21; + int low = 110; + int up = 220; + int halfSize = blockSize / 2; + int square_blockSize = blockSize * blockSize; + CImageApplyDetachNoise noise(6); switch (m_type) { case ThresholdType::THRESH_BINARY: - { -#if 0 - StopWatch sw; - float ksize = 9.0f; - float other = (1.0f - ksize) / 4.0f; - float kernel_data[] = { 0, other, 0, other, ksize, other, 0, other, 0 }; - cv::Mat kernel(3, 3, CV_32FC1, kernel_data); - - cv::filter2D(pDib, pDib, pDib.depth(), kernel); - FileTools::write_log("E:\\Users\\huago\\Desktop\\2.txt", "filter2D: " + std::to_string(sw.elapsed_ms())); - sw.reset(); - cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 91, 21); - FileTools::write_log("E:\\Users\\huago\\Desktop\\2.txt", "adaptiveThreshold: " + std::to_string(sw.elapsed_ms())); - //cv::Mat mask = pDib.clone(); - //std::vector> contours; - //std::vector h; - //hg::findContours(mask, contours, h); - //mask.release(); - - //for (const std::vector& contour : contours) - // if (contourArea(contour) < 6) - // fillConvexPoly(pDib, contour, cv::Scalar(255)); -#endif - //StopWatch sw; - cv::Mat integ; cv::integral(pDib, integ, CV_32S); - int blockSize = 31;//邻域尺寸 - int threshold = 21; - int low = 110; - int up = 220; - int halfSize = blockSize / 2; - int square_block = blockSize * blockSize; for (int j = halfSize; j < integ.rows - halfSize - 1; j++) { uchar* data = pDib.ptr(j); @@ -441,35 +56,19 @@ void CImageApplyBWBinaray::apply(cv::Mat& pDib, int side) int* idata2 = integ.ptr(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]) / square_block; 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; - } + 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); - cv::Mat mask = pDib.clone(); - std::vector> contours; - std::vector h; - hg::findContours(mask, contours, h); - mask.release(); - - for (const std::vector& contour : contours) - if (contourArea(contour) < 6) - fillConvexPoly(pDib, contour, cv::Scalar(255)); - //FileTools::write_log("E:\\Users\\huago\\Desktop\\2.txt", "THRESH_BINARY eplsed: " + std::to_string(sw.elapsed_ms())); - //cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_OTSU); + noise.apply(pDib, side); break; - } case ThresholdType::THRESH_OTSU: cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_OTSU); break; @@ -538,9 +137,9 @@ void CImageApplyBWBinaray::errorDiffuse(cv::Mat& image) 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][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(); diff --git a/huagao/ImageProcess/ImageApplyBWBinaray.h b/huagao/ImageProcess/ImageApplyBWBinaray.h index 9be206b7..1f0442d7 100644 --- a/huagao/ImageProcess/ImageApplyBWBinaray.h +++ b/huagao/ImageProcess/ImageApplyBWBinaray.h @@ -1,75 +1,13 @@ -//#ifndef IMAGE_APPLY_BW_BINARAY_H -//#define IMAGE_APPLY_BW_BINARAY_H -// -//#include "ImageApply.h" -// -//class CImageApplyBWBinaray:public CImageApply -//{ -//public: -// -// enum class ThresholdType -// { -// THRESH_BINARY = 0, -// THRESH_OTSU, -// -// ADAPTIVE_GAUSSIAN, -// ADAPTIVE_MEAN, -// -// ERROR_DIFFUSION -// }; -// -// CImageApplyBWBinaray(ThresholdType type, int threshold = 180, int blockSize = 25, int constant = 5); -// -// CImageApplyBWBinaray(); -// -// virtual ~CImageApplyBWBinaray(void); -// -// virtual void apply(cv::Mat& pDib,int side); -// -// virtual void apply(std::vector& mats, bool isTwoSide); -// -// double getThreshold() { return m_threshold; } -// -// ThresholdType getThresholdType() { return m_type; } -// -// int getBlockSize() { return m_blockSize; } -// -// double getConstant() { return m_constant; } -// -// void setThreshold(double value) { m_threshold = value; } -// -// void setThresholdType(ThresholdType type) { m_type = type; } -// -// void setBlockSize(int value) { m_blockSize = value; } -// -// void setConstant(double value) { m_constant = value; } -// -//private: -// -// void errorDiffuse(cv::Mat& image); -// -//private: -// double m_threshold; -// -// ThresholdType m_type; -// -// int m_blockSize; -// -// double m_constant; -// -// uchar* m_table; -//}; -// -//#endif //!IMAGE_APPLY_BW_BINARAY_H -// /* * ==================================================== - * 功能:二值化处理 - * 作者:刘丁维 - * 生成时间:2020/4/21 - * 最近修改时间:2020/4/21 - * 版本号:v1.0 + * 鍔熻兘锛氫簩鍊煎寲澶勭悊 + * 浣滆咃細鍒樹竵缁 + * 鐢熸垚鏃堕棿锛2020/4/21 + * 鏈杩戜慨鏀规椂闂达細2020/5/28 v1.1 淇敼浼犵粺浜屽煎寲绠楁硶锛屾敼鐢ㄨ嚜瀹氫箟灞閮ㄨ嚜閫傚簲闃堝肩畻娉 + 2020/5/29 v1.2 鍦ㄤ紶缁熶簩鍊煎寲涔嬪墠娣诲姞澧炲己閿愬寲鏁堟灉锛屼簩鍊煎寲涔嬪悗澧炲姞闄ゅ櫔鏁堟灉 + 2020/6/19 v1.3 缂栧啓鑷畾涔夎嚜閫傚簲闃堝间簩鍊煎寲锛涘彇娑堥攼鍖栧鐞嗭紱淇濈暀闄ゅ櫔鏁堟灉 + * 鐗堟湰鍙凤細v1.3 * ==================================================== */ @@ -79,34 +17,34 @@ #include "ImageApply.h" -class CImageApplyBWBinaray :public CImageApply +class CImageApplyBWBinaray:public CImageApply { public: enum class ThresholdType { - THRESH_BINARY = 0, //传统二值化 - THRESH_OTSU, //大津阈值 + THRESH_BINARY = 0, //浼犵粺浜屽煎寲 + THRESH_OTSU, //澶ф触闃堝 - ADAPTIVE_GAUSSIAN, //高斯局部自适应阈值 - ADAPTIVE_MEAN, //均值局部自适应阈值 + ADAPTIVE_GAUSSIAN, //楂樻柉灞閮ㄨ嚜閫傚簲闃堝 + ADAPTIVE_MEAN, //鍧囧煎眬閮ㄨ嚜閫傚簲闃堝 - ERROR_DIFFUSION //错误扩散 + ERROR_DIFFUSION //閿欒鎵╂暎 }; - /* - * type [in]:二值化模式 - * threshold [in]:阈值,当选择THRESH_OTSU时无效 - * blockSize [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效,表示局部观察块的宽度 - * constant [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效,与blockSize形成比例关系,作为局部筛选阈值 - */ + /* + * type [in]:浜屽煎寲妯″紡 + * threshold [in]:闃堝硷紝褰撻夋嫨THRESH_OTSU鏃舵棤鏁 + * blockSize [in]:ADAPTIVE_GAUSSIAN鍜孉DAPTIVE_MEAN妯″紡鏈夋晥锛岃〃绀哄眬閮ㄨ瀵熷潡鐨勫搴 + * constant [in]:ADAPTIVE_GAUSSIAN鍜孉DAPTIVE_MEAN妯″紡鏈夋晥锛屼笌blockSize褰㈡垚姣斾緥鍏崇郴锛屼綔涓哄眬閮ㄧ瓫閫夐槇鍊 + */ CImageApplyBWBinaray(ThresholdType type, int threshold = 120, int blockSize = 25, int constant = 5); CImageApplyBWBinaray(); virtual ~CImageApplyBWBinaray(void); - virtual void apply(cv::Mat& pDib, int side); + virtual void apply(cv::Mat& pDib,int side); virtual void apply(std::vector& mats, bool isTwoSide); diff --git a/huagao/ImageProcess/ImageApplyDetachNoise.cpp b/huagao/ImageProcess/ImageApplyDetachNoise.cpp new file mode 100644 index 00000000..d32951bc --- /dev/null +++ b/huagao/ImageProcess/ImageApplyDetachNoise.cpp @@ -0,0 +1,42 @@ +#include "ImageApplyDetachNoise.h" +#include "ImageProcess_Public.h" + +CImageApplyDetachNoise::CImageApplyDetachNoise(int noise) + : m_noise(noise) +{ +} + +CImageApplyDetachNoise::~CImageApplyDetachNoise(void) +{ +} + +void CImageApplyDetachNoise::apply(cv::Mat& pDib, int side) +{ + (void)side; + if (pDib.empty()||pDib.channels() != 1) + return; + + cv::Mat mask; + cv::threshold(pDib, mask, 127, 255, cv::THRESH_BINARY_INV); + + std::vector> contours; + std::vector h; + hg::findContours(mask, contours, h); + + for (const std::vector& contour : contours) + if (contourArea(contour) < m_noise) + fillConvexPoly(pDib, contour, cv::Scalar(255)); +} + +void CImageApplyDetachNoise::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++; + } +} diff --git a/huagao/ImageProcess/ImageApplyDetachNoise.h b/huagao/ImageProcess/ImageApplyDetachNoise.h new file mode 100644 index 00000000..1238afbe --- /dev/null +++ b/huagao/ImageProcess/ImageApplyDetachNoise.h @@ -0,0 +1,38 @@ +/* + * ==================================================== + + * 功能:除噪,消除3*3以内的像素点,主要针对黑白图 + * 作者:刘丁维 + * 生成时间:2020/4/21 + * 最近修改时间:2020/4/21 v1.0 + 2020/5/29 v1.1 增加接口,使噪点大小阈值可调 + * 版本号:v1.1 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_DETACH_NOISE_H +#define IMAGE_APPLY_DETACH_NOISE_H + +#include "ImageApply.h" + +class CImageApplyDetachNoise : public CImageApply +{ +public: + CImageApplyDetachNoise(int noise = 4); + + inline int getNoise() { return m_noise; } + + inline void setNoise(int noise) { m_noise = noise; } + + virtual ~CImageApplyDetachNoise(void); + + virtual void apply(cv::Mat& pDib, int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + +private: + int m_noise; +}; +#endif // !IMAGE_APPLY_DETACH_NOISE_H + diff --git a/huagao/ImageProcess/ImageApplyHSVCorrect.cpp b/huagao/ImageProcess/ImageApplyHSVCorrect.cpp new file mode 100644 index 00000000..4b558a8f --- /dev/null +++ b/huagao/ImageProcess/ImageApplyHSVCorrect.cpp @@ -0,0 +1,144 @@ +#include "ImageApplyHSVCorrect.h" +#include + +CImageApplyHSVCorrect::CImageApplyHSVCorrect() + : m_table(new uint[256 * 256 * 256]) +{ + initLUT(); +} + +CImageApplyHSVCorrect::CImageApplyHSVCorrect(CorrectOption mode) + : m_table(new uint[256 * 256 * 256]) +{ + initLUT(); + switch (mode) + { + case CImageApplyHSVCorrect::Red_Removal: + set_HSV_value(std::pair(0, 63), std::pair(20, 255), std::pair(160, 255), 0x00FFFFFF); + set_HSV_value(std::pair(191, 255), std::pair(20, 255), std::pair(160, 255), 0x00FFFFFF); + break; + default: + break; + } +} + +CImageApplyHSVCorrect::~CImageApplyHSVCorrect() +{ + delete [] m_table; +} + +void CImageApplyHSVCorrect::apply(cv::Mat &pDib, int side) +{ + (void)side; + if (pDib.empty() || pDib.channels() != 3) return; + + uchar* src = pDib.data; + cv::Mat z = cv::Mat::zeros(pDib.size(), CV_8UC3); + uchar* dst = z.data; + + int total = pDib.total(); +#pragma omp parallel for + for (int i = 0; i < total; i++) + { + int offset = i * 3; + int index = *reinterpret_cast(src + offset) & 0x00ffffff; + uint color = m_table[index]; + *reinterpret_cast(dst + offset) |= color; + } + pDib = z; +} + +void CImageApplyHSVCorrect::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 CImageApplyHSVCorrect::initLUT() +{ +#if 0 + uchar h, s, v; +#endif + for (uint b = 0; b < 256; b++) + for (uint g = 0; g < 256; g++) + for (uint r = 0; r < 256; r++) + { +#if 0 + RGB_2_HSV_full(r, g, b, h, s, v); + + uint index = b | (g << 8) | (r << 16); + if (h < 12 || h > 245) + m_table[index] = index & 0x00ffffff; + else + m_table[index] = (v | (v << 8) | (v << 16)) & 0x00ffffff; +#else + m_table[b | (g << 8) | (r << 16)] = b | (g << 8) | (r << 16); +#endif + } +} + +void CImageApplyHSVCorrect::set_single(const uint src_b, const uint src_g, const uint src_r, + const uint dst_b, const uint dst_g, const uint dst_r) +{ + m_table[src_b | (src_g << 8) | (src_r << 16)] = dst_b | (dst_g << 8) | (dst_r << 16); +} + +void CImageApplyHSVCorrect::set_HSV_value(const std::pair& range_h, + const std::pair& range_s, + const std::pair& range_v, + uint bgr) +{ + uchar h, s, v; + for (int b = 0; b < 256; b++) + for (int g = 0; g < 256; g++) + for (int r = 0; r < 256; r++) + { + RGB_2_HSV_full(r, g, b, h, s, v); + if (contained(h, range_h) && contained(s, range_s) && contained(v, range_v)) + m_table[(b | (g << 8) | (r << 16)) & 0x00ffffff] = bgr & 0x00ffffff; + } +} + +void CImageApplyHSVCorrect::set_table(const uint* table) +{ + memcpy(m_table, table, 256 * 256 * 256); +} + +bool CImageApplyHSVCorrect::contained(uchar value, const std::pair &range) +{ + return value >= range.first && value <= range.second; +} + +void CImageApplyHSVCorrect::RGB_2_HSV_full(int r, int g, int b, uchar& h, uchar& s, uchar& v) +{ + int minn = cv::min(r, cv::min(g, b)); + int maxx = cv::max(r, cv::max(g, b)); + v = static_cast(maxx); //V + + int delta = maxx - minn; + float _h; + if (maxx == 0) + { + h = s = v = 0; + return; + } + else + s = static_cast(delta * 255 / maxx); + + if (r == maxx) + _h = static_cast(g - b) / static_cast(delta); + else if (g == maxx) + _h = 2 + static_cast(b - r) / static_cast(delta); + else + _h = 4 + static_cast(r - g) / static_cast(delta); + + float __h = _h * 42.6666666667f; + h = (__h >= 0) ? static_cast(__h) : static_cast(__h + 256); +} diff --git a/huagao/ImageProcess/ImageApplyHSVCorrect.h b/huagao/ImageProcess/ImageApplyHSVCorrect.h new file mode 100644 index 00000000..8816d13f --- /dev/null +++ b/huagao/ImageProcess/ImageApplyHSVCorrect.h @@ -0,0 +1,87 @@ +/* + * ==================================================== + + * 功能:彩色图像,色彩校正。基于LUT实现,预设BGR查值表(表达所有HVS),对BGR原图进行查值校正。 + * 作者:刘丁维 + * 生成时间:2020/3/21 + * 最近修改时间:v1.0 2020/3/21 + v1.1 2020/6/15 调整除红效果的HSV取值范围 + * 版本号:v1.1 + + * ==================================================== + */ + +#ifndef IMAGE_APPLY_COLOR_CORRECT_H +#define IMAGE_APPLY_COLOR_CORRECT_H + +#include "ImageApply.h" + +class CImageApplyHSVCorrect : public CImageApply +{ +public: + enum CorrectOption + { + Red_Removal //除掉红色。红色定义H:[0, 85]∪[170, 255],S:[10, 255],V:[120,255] + }; +public: + + CImageApplyHSVCorrect(); + + /* + * mode [in]:预设初色模式 + */ + CImageApplyHSVCorrect(CorrectOption mode); + + virtual ~CImageApplyHSVCorrect(); + + virtual void apply(cv::Mat& pDib,int side); + + virtual void apply(std::vector& mats, bool isTwoSide); + + /* + * 函数功能:初始化查值表,按照RGB(R在高位,B在低位)的32位数据进行索引,值与索引一致。 + 表中索引范围[0,0x00FFFFFF]。在构造函数中会默认调用该函数。 + */ + void initLUT(); + + /* + * 函数功能:将查值表指定RGB索引值设置为目标值。 + 索引 = src_b | (src_g << 8) | (src_r << 16) + 值 = dst_b | (dst_g << 8) | (dst_r << 16) + * src_b:[in] 原查值表B通道索引 + * src_g:[in] 原查值表G通道索引 + * src_r:[in] 原查值表R通道索引 + * dst_b:[in] 目标查值表B通道值 + * dst_g:[in] 目标查值表G通道值 + * dst_r:[in] 目标查值表R通道值 + */ + void set_single(const uint src_b, const uint src_g, const uint src_r, + const uint dst_b, const uint dst_g, const uint dst_r); + /* + * 函数功能:按照HSV色彩空间描述色彩范围,将该范围对应的BGR索引设置为0x00FFFFFF(默认白色) + * range_h:[in] H分量范围,取值范围[0, 255] + * range_s:[in] S分量范围,取值范围[0, 255] + * range_v:[in] V分量范围,取值范围[0, 255] + * bgr:[in] 用uint表示BGR值,B在低位,R在高位 + */ + void set_HSV_value(const std::pair& range_h, + const std::pair& range_s, + const std::pair& range_v, + uint bgr = 0x00FFFFFF); + + /* + * 函数功能:设置外部查值表,表默认长度为 256 * 256 * 256 * sizeof(uint) + * table:[in] 数组指针 + */ + void set_table(const uint* table); + +private: + static bool contained(uchar value, const std::pair& range); + + static void RGB_2_HSV_full(int r, int g, int b, uchar& h, uchar& s, uchar& v); + +private: + uint* m_table; +}; + +#endif diff --git a/huagao/ImageProcess/ImageApplyHeaders.h b/huagao/ImageProcess/ImageApplyHeaders.h index e463176d..baf1de6a 100644 --- a/huagao/ImageProcess/ImageApplyHeaders.h +++ b/huagao/ImageProcess/ImageApplyHeaders.h @@ -13,5 +13,6 @@ #include "ImageApplyRotation.h" #include "ImageApplySharpen.h" #include "ImageApplyConcatenation.h" +#include "ImageApplyHSVCorrect.h" #endif