Derek Bradley & Gerhard Roth自适应二值化算法, Opencv实现
2015-10-17 20:41
459 查看
算法介绍请参考: http://blog.csdn.net/qiaxi/article/details/49205135
二值化函数:
void BradleyThreshold(const cv::Mat& srcImage, cv::Mat& dstImage, int iRows, int iCols, double dPercentThres)
{
// Safety check
if (srcImage.empty())
{
std::cout << "Empty matrix. Please check your input into QxBinarior::BradleyThreshold()" << std::endl << std::endl;
return;
}
if (dPercentThres < -1)
{
std::cout << "Percentage value can not be lhigher than 100% percent. Please check your input into QxBinarior::BradleyThreshold()" << std::endl << std::endl;
return;
}
// Deal with even blocksize
if (iRows % 2 == 0)
++iRows;
if (iCols % 2 == 0)
++iCols;
// Deal with color image
cv::Mat grayImg;
if (srcImage.type() == CV_8UC3)
cv::cvtColor(srcImage, grayImg, CV_BGR2GRAY);
else
grayImg = srcImage;
//-- Generate integral image.
int iRowAmount = grayImg.rows + 1; //Padding
int iColAmount = grayImg.cols + 1; //Padding
double* pIntegralImage = new double[iRowAmount * iColAmount];
// Zero padding
for (int iCol = 0; iCol < iColAmount; ++iCol)
pIntegralImage[iCol] = 0.0;
for (int iRow = 0; iRow < iRowAmount; ++iRow)
pIntegralImage[iRow*iColAmount] = 0.0;
bool bIsFirstRow = true;
double dSum = 0.0;
uchar* pCurrentRow = grayImg.ptr<uchar>(0);
for (int iRow = 1; iRow < iRowAmount; ++iRow)
{
bIsFirstRow = iRow == 1;
pCurrentRow = grayImg.ptr<uchar>(iRow - 1);
dSum = 0.0;
for (int iCol = 1; iCol < iColAmount; ++iCol)
{
dSum += pCurrentRow[iCol - 1];
if (!bIsFirstRow)
pIntegralImage[iRow*iColAmount + iCol] = dSum + pIntegralImage[(iRow - 1)*iColAmount + iCol];
else
pIntegralImage[iRow*iColAmount + iCol] = dSum;
}
}
//-- Integral image generated.
// Binarization
const int iRowHalfRange = iRows / 2;
const int iColHalfRange = iCols / 2;
int iRowBegin = 0;
int iRowEnd = 0;
int iColBegin = 0;
int iColEnd = 0;
int iArea = 0;
double dAverageVal = 0.0;
dstImage.create(grayImg.size(), CV_8UC1);
for (int iRow = 1; iRow < iRowAmount; ++iRow)
{
uchar* pDstCurrentRow = dstImage.ptr<uchar>(iRow - 1);
uchar* pSrcCurrentRow = grayImg.ptr<uchar>(iRow - 1);
iRowBegin = iRow - iRowHalfRange - 1;
iRowEnd = iRow + iRowHalfRange;
if (iRowBegin < 0)
iRowBegin = 0;
if (iRowEnd >= iRowAmount)
iRowEnd = iRowAmount - 1;
for (int iCol = 1; iCol < iColAmount; ++iCol)
{
iColBegin = iCol - iColHalfRange - 1;
iColEnd = iCol + iColHalfRange;
if (iColBegin < 0)
iColBegin = 0;
if (iColEnd >= iColAmount)
iColEnd = iColAmount - 1;
iArea = (iColEnd - iColBegin)*(iRowEnd - iRowBegin);
dSum = pIntegralImage[iRowBegin*iColAmount + iColBegin] + pIntegralImage[iRowEnd*iColAmount + iColEnd]
- pIntegralImage[iRowBegin*iColAmount + iColEnd] - pIntegralImage[iRowEnd*iColAmount + iColBegin];
dAverageVal = dSum / iArea;
pDstCurrentRow[iCol - 1] = pSrcCurrentRow[iCol - 1] > dAverageVal*(1 + dPercentThres) ? 255: 0;
}
}
delete[] pIntegralImage;
}
主函数:
#include <opencv2\core\core.hpp> #include <opencv2\imgproc\imgproc.hpp> #include <opencv2\highgui\highgui.hpp> #include "BradleyThreshold.h" using namespace cv; using namespace std; int main() { Mat matSrcImage = imread("E:\\Picture\\IMG\\191.jpg", CV_LOAD_IMAGE_COLOR); Mat matBinaryImage; BradleyThreshold(matSrcImage, matBinaryImage, 5, 5, 0.1); //参数需根据不同图片设定 imshow("Original Image", matSrcImage); imshow("Bianry Image", matBinaryImage); waitKey(0); return EXIT_SUCCESS; }
程序运行结果如下:
--------------------------------------------------------------------------------------------------------
测试发现,这段代码的时间效率比Opencv自带函数adpativeThreshold()低30%-50%, 二值化表现各有千秋。
对于整体较明亮的图像,adaptiveThreshold()的表现优于以上代码。但是对于整体灰度值偏低的图片,上面那段代码的表现要优于
adaptiveThreshold(). 平均灰度越低,这种差异越明显。因此推荐大家对昏暗的图片采用Bradley与Roth提出的该算法,明亮图片采用adaptiveThreshold()函数。
adaptiveThreshold()与上述算法最大的区别在于: adaptiveThreshold()以灰度值的差值的绝对数值为参数区分前景与背景,该算法则使用差值与本身灰度值的百分比作为区分依据,因此后者在灰度值整体偏低的情况下更有区分性。大家也可以对这个算法做一些改进,比如在二值化操作之前先对更大邻域内的图像均值做一次评估,若均值偏高则使用绝对数值差异作为二值化依据;如果均值偏低则使用差值百分比参数作为区分依据。
相关文章推荐
- c#实现图片二值化例子(黑白效果)
- C#数字图像处理之图像二值化(彩色变黑白)的方法
- python中使用OpenCV进行人脸检测的例子
- opencv 做人脸识别 opencv 人脸匹配分析
- 使用opencv拉伸图像扩大分辨率示例
- OpenCV 2.4.3 C++ 平滑处理分析
- 利用Python和OpenCV库将URL转换为OpenCV格式的方法
- python结合opencv实现人脸检测与跟踪
- 在树莓派2或树莓派B+上安装Python和OpenCV的教程
- OpenCV配置,从来没有这么简单!
- ubuntu下opencv和qt的安装配置
- OpenCV学习笔记(二十五)——OpenCV图形界面设计Qt+VS2008
- 分享一些OpenCV实现立体视觉的经验
- 关于OpenCv图像变换与基本图形检测
- "应用程序正常初始化失败"-0xc0150002 解决办法
- OpenCV->HSV色彩空间
- opencv 内存泄露
- OpenCV函数cvFindContours
- OpenCV 2.3.1图像文件的读入和显示
- opencv2 矩阵方式 resize图像缩放代码