diff --git a/build/windows/HGImgProc/HGImgProc.def b/build/windows/HGImgProc/HGImgProc.def index b06c3968..1f980a0f 100644 --- a/build/windows/HGImgProc/HGImgProc.def +++ b/build/windows/HGImgProc/HGImgProc.def @@ -8,6 +8,7 @@ HGImgProc_ImageAutoCrop HGImgProc_ImageBlankCheck HGImgProc_ImageDrawLine HGImgProc_AddImageWatermark +HGImgProc_ImageBinarization HGImgProc_CreateOCRMgr HGImgProc_DestroyOCRMgr diff --git a/build/windows/HGTest/HGTestDlg.cpp b/build/windows/HGTest/HGTestDlg.cpp index d35c44a6..13ea8599 100644 --- a/build/windows/HGTest/HGTestDlg.cpp +++ b/build/windows/HGTest/HGTestDlg.cpp @@ -104,6 +104,16 @@ BOOL CHGTestDlg::OnInitDialog() SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 + HGImage img = NULL; + HGImgFmt_LoadImage("D:\\1.jpg", 0, NULL, HGBASE_IMGTYPE_BGRA, HGBASE_IMGORIGIN_BOTTOM, &img); + if (NULL != img) + { + HGImgProc_ImageBinarization(img, img, HGIMGPROC_THRESHTYPE_OTSU, 120, 51, 41); + + HGImgFmt_SaveImage(img, 0, NULL, "D:\\2222.bmp"); + HGBase_DestroyImage(img); + } + return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } diff --git a/modules/imgproc/HGImgProc.cpp b/modules/imgproc/HGImgProc.cpp index b054250e..57f81987 100644 --- a/modules/imgproc/HGImgProc.cpp +++ b/modules/imgproc/HGImgProc.cpp @@ -2,6 +2,7 @@ #include "./ImageProcess/ImageApplyAdjustColors.h" #include "./ImageProcess/ImageApplyAutoCrop.h" #include "./ImageProcess/ImageApplyDiscardBlank.h" +#include "./ImageProcess/ImageApplyBWBinaray.h" #include "CvxText.hpp" #include "../base/HGInc.h" #include "../base/HGUtility.h" @@ -159,6 +160,7 @@ HGResult HGAPI HGImgProc_ImageAdjustColors(HGImage image, HGImage destImage, cv::Mat img(roiHeight, roiWidth, CV_8UC(channels), p, imgInfo.widthStep); CImageApplyAdjustColors imgApply(brightness, contrast, gamma); imgApply.apply(img, 0); + assert(img.data == p); } else { @@ -210,6 +212,7 @@ HGResult HGAPI HGImgProc_ImageAdjustColors(HGImage image, HGImage destImage, cv::Mat destImg(destRoiHeight, destRoiWidth, CV_8UC(channels), pDest, destImgInfo.widthStep); CImageApplyAdjustColors imgApply(brightness, contrast, gamma); imgApply.apply(destImg, 0); + assert(destImg.data == pDest); } return HGBASE_ERR_OK; @@ -225,11 +228,11 @@ HGResult HGAPI HGImgProc_ImageAutoCrop(HGImage image, HGBool autoCrop, HGBool de HGImageInfo imgInfo; HGBase_GetImageInfo(image, &imgInfo); - if (HGBASE_IMGTYPE_BINARY == imgInfo.type || HGBASE_IMGTYPE_RGBA == imgInfo.type - || HGBASE_IMGTYPE_BGRA == imgInfo.type) + if (HGBASE_IMGTYPE_BINARY == imgInfo.type || HGBASE_IMGTYPE_RGB == imgInfo.type + || HGBASE_IMGTYPE_RGBA == imgInfo.type || HGBASE_IMGTYPE_BGRA == imgInfo.type) { HGImage imageTmp = NULL; - HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, 0, &imageTmp); + HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_BGR, 0, &imageTmp); if (HGBASE_ERR_OK == ret) { if (0 == destType) @@ -273,7 +276,7 @@ HGResult HGAPI HGImgProc_ImageAutoCrop(HGImage image, HGBool autoCrop, HGBool de HGUInt roiHeight = roi.bottom - roi.top; uint32_t channels = 1; - if (HGBASE_IMGTYPE_RGB == imgInfo.type || HGBASE_IMGTYPE_BGR == imgInfo.type) + if (HGBASE_IMGTYPE_BGR == imgInfo.type) channels = 3; uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left * channels; @@ -314,11 +317,11 @@ HGResult HGAPI HGImgProc_ImageBlankCheck(HGImage image, const HGImgBlankCheckPar HGImageInfo imgInfo; HGBase_GetImageInfo(image, &imgInfo); - if (HGBASE_IMGTYPE_BINARY == imgInfo.type || HGBASE_IMGTYPE_RGBA == imgInfo.type - || HGBASE_IMGTYPE_BGRA == imgInfo.type) + if (HGBASE_IMGTYPE_BINARY == imgInfo.type || HGBASE_IMGTYPE_RGB == imgInfo.type + || HGBASE_IMGTYPE_RGBA == imgInfo.type || HGBASE_IMGTYPE_BGRA == imgInfo.type) { HGImage imageTmp = NULL; - HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, 0, &imageTmp); + HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_BGR, 0, &imageTmp); if (HGBASE_ERR_OK == ret) { ret = HGImgProc_ImageBlankCheck(imageTmp, param, blank); @@ -352,7 +355,7 @@ HGResult HGAPI HGImgProc_ImageBlankCheck(HGImage image, const HGImgBlankCheckPar HGUInt roiHeight = roi.bottom - roi.top; uint32_t channels = 1; - if (HGBASE_IMGTYPE_BGR == imgInfo.type || HGBASE_IMGTYPE_RGB == imgInfo.type) + if (HGBASE_IMGTYPE_BGR == imgInfo.type) channels = 3; uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left * channels; @@ -379,7 +382,7 @@ HGResult HGAPI HGImgProc_ImageDrawLine(HGImage image, HGInt x1, HGInt y1, HGInt if (HGBASE_IMGTYPE_BINARY == imgInfo.type || HGBASE_IMGTYPE_GRAY == imgInfo.type) { HGImage imageTmp = NULL; - HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, 0, &imageTmp); + HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_BGR, 0, &imageTmp); if (HGBASE_ERR_OK == ret) { ret = HGImgProc_ImageDrawLine(imageTmp, x1, y1, x2, y2, color, width, type); @@ -422,14 +425,14 @@ HGResult HGAPI HGImgProc_ImageDrawLine(HGImage image, HGInt x1, HGInt y1, HGInt HGUInt r = HG_GETCOLOR_R(color); HGUInt g = HG_GETCOLOR_G(color); HGUInt b = HG_GETCOLOR_B(color); - if (HGBASE_IMGTYPE_BGR == imgInfo.type || HGBASE_IMGTYPE_BGRA == imgInfo.type) + if (HGBASE_IMGTYPE_RGB == imgInfo.type || HGBASE_IMGTYPE_RGBA == imgInfo.type) { r = HG_GETCOLOR_B(color); g = HG_GETCOLOR_G(color); b = HG_GETCOLOR_R(color); } - cvLine(pImg, cvPoint(x1, y1), cvPoint(x2, y2), cvScalar(r, g, b), width); + cvLine(pImg, cvPoint(x1, y1), cvPoint(x2, y2), cvScalar(b, g, r), width); cvReleaseImageHeader(&pImg); return HGBASE_ERR_OK; } @@ -482,3 +485,128 @@ HGResult HGAPI HGImgProc_AddImageWatermark(HGImage image, const HGChar* text, HG ret = cvxText.DrawString(image, text, color, posType, locationX, locationY, fontSize, bold, underline, italic, strikeout); return ret; } + +HGResult HGAPI HGImgProc_ImageBinarization(HGImage image, HGImage destImage, HGUInt thresholdType, + HGInt threshold, HGInt blockSize, HGInt constant) +{ + if (NULL == image || thresholdType < HGIMGPROC_THRESHTYPE_BINARY || thresholdType > HGIMGPROC_THRESHTYPE_ERROR_DIFFUSION) + { + return HGBASE_ERR_INVALIDARG; + } + + CImageApplyBWBinaray::ThresholdType thresholdType2 = CImageApplyBWBinaray::ThresholdType::THRESH_BINARY; + if (HGIMGPROC_THRESHTYPE_OTSU == thresholdType) + thresholdType2 = CImageApplyBWBinaray::ThresholdType::THRESH_OTSU; + else if (HGIMGPROC_THRESHTYPE_ADAPTIVE_GAUSSIAN == thresholdType) + thresholdType2 = CImageApplyBWBinaray::ThresholdType::ADAPTIVE_GAUSSIAN; + else if (HGIMGPROC_THRESHTYPE_ADAPTIVE_MEAN == thresholdType) + thresholdType2 = CImageApplyBWBinaray::ThresholdType::ADAPTIVE_MEAN; + else if (HGIMGPROC_THRESHTYPE_ERROR_DIFFUSION == thresholdType) + thresholdType2 = CImageApplyBWBinaray::ThresholdType::ERROR_DIFFUSION; + + HGImageInfo imgInfo; + HGBase_GetImageInfo(image, &imgInfo); + + HGByte* data = NULL; + HGBase_GetImageData(image, &data); + + HGImageRoi roi; + HGBase_GetImageROI(image, &roi); + HGUInt roiWidth = roi.right - roi.left; + HGUInt roiHeight = roi.bottom - roi.top; + + if (NULL == destImage || image == destImage) + { + if (HGBASE_IMGTYPE_GRAY != imgInfo.type) + { + HGImage imageTmp = NULL; + HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp); + if (HGBASE_ERR_OK == ret) + { + ret = HGImgProc_ImageBinarization(imageTmp, imageTmp, thresholdType, threshold, blockSize, constant); + if (HGBASE_ERR_OK == ret) + { + ret = HGBase_CopyImage(imageTmp, image); + } + + HGBase_DestroyImage(imageTmp); + } + + return ret; + } + + uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left; + if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin) + p = data + (imgInfo.height - roi.bottom) * imgInfo.widthStep + roi.left; + + cv::Mat img(roiHeight, roiWidth, CV_8UC(1), p, imgInfo.widthStep); + CImageApplyBWBinaray imgApply(thresholdType2, threshold, blockSize, constant); + imgApply.apply(img, 0); + if (img.data != p) + { + for (HGUInt i = 0; i < roiHeight; ++i) + { + memcpy(p + i * imgInfo.widthStep, img.data + i * img.step, roiWidth); + } + } + } + else + { + HGImageInfo destImgInfo; + HGBase_GetImageInfo(destImage, &destImgInfo); + if (imgInfo.type != destImgInfo.type) + { + return HGBASE_ERR_INVALIDDATA; + } + + HGByte* destData = NULL; + HGBase_GetImageData(destImage, &destData); + + HGImageRoi destRoi; + HGBase_GetImageROI(destImage, &destRoi); + HGUInt destRoiWidth = destRoi.right - destRoi.left; + HGUInt destRoiHeight = destRoi.bottom - destRoi.top; + + if (roiWidth != destRoiWidth || roiHeight != destRoiHeight) + { + return HGBASE_ERR_INVALIDDATA; + } + + if (HGBASE_IMGTYPE_GRAY != imgInfo.type) + { + HGImage imageTmp = NULL; + HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp); + if (HGBASE_ERR_OK == ret) + { + ret = HGImgProc_ImageBinarization(imageTmp, imageTmp, thresholdType, threshold, blockSize, constant); + if (HGBASE_ERR_OK == ret) + { + ret = HGBase_CopyImage(imageTmp, destImage); + } + + HGBase_DestroyImage(imageTmp); + } + + return ret; + } + + HGBase_CopyImage(image, destImage); + + uint8_t* pDest = destData + destRoi.top * destImgInfo.widthStep + destRoi.left; + if (HGBASE_IMGORIGIN_BOTTOM == destImgInfo.origin) + pDest = destData + (destImgInfo.height - destRoi.bottom) * destImgInfo.widthStep + destRoi.left; + + cv::Mat destImg(destRoiHeight, destRoiWidth, CV_8UC(1), pDest, destImgInfo.widthStep); + CImageApplyBWBinaray imgApply(thresholdType2, threshold, blockSize, constant); + imgApply.apply(destImg, 0); + if (destImg.data != pDest) + { + for (HGUInt i = 0; i < destRoiHeight; ++i) + { + memcpy(pDest + i * destImgInfo.widthStep, destImg.data + i * destImg.step, destRoiWidth); + } + } + } + + return HGBASE_ERR_OK; +} diff --git a/modules/imgproc/HGImgProc.h b/modules/imgproc/HGImgProc.h index e4949567..cb77fa23 100644 --- a/modules/imgproc/HGImgProc.h +++ b/modules/imgproc/HGImgProc.h @@ -37,6 +37,17 @@ /* 水印位置-自定义 */ #define HGIMGPROC_WMPOSTYPE_LOCATION 10L +/* 传统二值化 */ +#define HGIMGPROC_THRESHTYPE_BINARY 1L +/* 大津法 */ +#define HGIMGPROC_THRESHTYPE_OTSU 2L +/* 高斯局部自适应阈值 */ +#define HGIMGPROC_THRESHTYPE_ADAPTIVE_GAUSSIAN 3L +/* 均值局部自适应阈值 */ +#define HGIMGPROC_THRESHTYPE_ADAPTIVE_MEAN 4L +/* 错误扩散 */ +#define HGIMGPROC_THRESHTYPE_ERROR_DIFFUSION 5L + /* 自动裁剪参数 */ typedef struct { @@ -155,4 +166,15 @@ HGEXPORT HGResult HGAPI HGImgProc_ImageDrawLine(HGImage image, HGInt x1, HGInt y HGEXPORT HGResult HGAPI HGImgProc_AddImageWatermark(HGImage image, const HGChar *text, HGColor color, HGUInt posType, HGInt locationX, HGInt locationY, const HGImgWatermarkFontParam *fontParam); +/* 图像二值化 +* 1) image: in, 源图像句柄 +* 2) destImage: in, 目标图像句柄 +* 3) thresholdType: in, 二值化类型,参见HGIMGPROC_THRESHTYPE_* +* 4) threshold: in, 阈值, 当选择HGIMGPROC_THRESHTYPE_OTSU时无效 +* 5) blockSize: in, HGIMGPROC_THRESHTYPE_ADAPTIVE_GAUSSIAN和HGIMGPROC_THRESHTYPE_ADAPTIVE_MEAN模式有效,表示局部观察块的宽度 +* 6) constant: in, HGIMGPROC_THRESHTYPE_ADAPTIVE_GAUSSIAN和HGIMGPROC_THRESHTYPE_ADAPTIVE_MEAN模式有效,与blockSize形成比例关系,作为局部筛选阈值 +*/ +HGEXPORT HGResult HGAPI HGImgProc_ImageBinarization(HGImage image, HGImage destImage, HGUInt thresholdType, + HGInt threshold, HGInt blockSize, HGInt constant); + #endif /* __HGIMGPROC_H__ */ \ No newline at end of file