赞
踩
大津算法(Ostu)也称最大类间方差法。顾名思义,就使两个类别之间某个属性的方差最大的方法。在图像处理中,灰度分布均匀性作为区分图像各个区域的一种度量,背景和目标之间的灰度均值的方差越大,说明目标与背景差别越大。由于其不受图像对比度的影响,大津二值化常被用来分割目标与背景。
对于一副大小RC的图像,目标和背景的分割阈值记作T,图像中像素的灰度值小于阈值T的像素个数记作N0。
1.目标的像素点数占整幅图像的比例记为ω0,ω0=N0/ C×R,平均灰度μ0。
2.背景像素点数占整幅图像的比例为ω1, ω1=N0/ C×R,平均灰度μ1。
3.图像的总平均灰度记为μ, μ=ω0μ0+ω1*μ1 (1)
4.类间方差记为g, g = w0 * (u0 - u)^2 + w1 * (u1 - u)^2。 (2)
5. N0+N1=M×N
ω0+ω1=1
将式(1)代入式(2),得到等价公式:g=ω0ω1(μ0-μ1)^2 (3)
公式(3)便是最大类间方差法。
1.统计图像中各个灰度值的个数:
const int nGrayScale = 256;//灰度
int nPixelCount[nGrayScale] = { 0 };//灰度直方图
//统计图片中各个灰度值的个数
for (int y = 0; y < src.rows; ++y)
{
for (int x = 0; x < src.cols; ++x)
{
int val = src.at<uchar>(y, x);
nPixelCount[val]++;
}
}
2.统计图片中各个灰度值所占的比例:
//统计图片中各个灰度值所占的比例
int nPixelSum = src.rows * src.cols;//总像素值
float fPixelPct[nGrayScale] = { 0 };//各个灰度值占总体的比例
for (int i = 0; i < nGrayScale; ++i)
{
fPixelPct[i] = 1.0 *nPixelCount[i] / nPixelSum;
}
3.从灰度0迭代到灰度255,每次迭代计算能使公式(3)最大的阈值Threshed:
double w0, w1;//背景/目标像素占比 double u0, u1;//目标/背景平均灰度值 double fTempVar = 0;//类间方差 double fMaxVar = 0;//最大类间方差 double fBestValue = 0;//最优阈值 double fTemp0, fTemp1; for (int k = 0; k < nGrayScale; ++k) { w0 = w1 = u0 = u1 = fTempVar = 0; fTemp0 = fTemp1 = 0; //前景,背景区分 [0-k][k+1-255] for (int i = 0; i < nGrayScale; ++i) { //如果当前像素值小于阈值k则属于背景,反之属于目标 if (i <= k) { //计算背景像素占比 w0 += fPixelPct[i]; //计算当前灰度值发生的概率:灰度值*灰度值发生的概率 fTemp0 += (i * fPixelPct[i]); } else { //计算背景像素占比 w1 += fPixelPct[i]; fTemp1 += (i * fPixelPct[i]); } } //计算平均灰度值:p0/w0 u0 = fTemp0 / w0; u1 = fTemp1 / w1; //计算类内方差 fTempVar = (float)(w0 * w1 * pow((u0 - u1), 2)); if (fTempVar > fMaxVar) { fMaxVar = fTempVar; fBestValue = k; } }
font color=#999AAA >测试采用了三张目标与背景对比度不一样的图片。
图片1:
图片2:
图片3:
实验证明,大津二值化可以不受图像对比度的影响,自动分割目标与背景。
//原图 Mat src = imread("image4.PNG", IMREAD_GRAYSCALE); //输出图 Mat dst = Mat::zeros(src.size(), src.type()); const int nGrayScale = 256;//灰度 int nPixelCount[nGrayScale] = { 0 };//灰度直方图 //统计图片中各个灰度值的个数 for (int y = 0; y < src.rows; ++y) { for (int x = 0; x < src.cols; ++x) { int val = src.at<uchar>(y, x); nPixelCount[val]++; //int nPixelCount[nGrayScale] = { 0 };//灰度直方图 } } //统计图片中各个灰度值所占的比例 int nPixelSum = src.rows * src.cols;//总像素值 float fPixelPct[nGrayScale] = { 0 };//各个灰度值占总体的比例 for (int i = 0; i < nGrayScale; ++i) { fPixelPct[i] = 1.0 *nPixelCount[i] / nPixelSum; } double w0, w1;//背景/目标像素占比 double u0, u1;//目标/背景平均灰度值 double fTempVar = 0;//类间方差 double fMaxVar = 0;//最大类间方差 double fBestValue = 0;//最优阈值 double fTemp0, fTemp1; for (int k = 0; k < nGrayScale; ++k) { w0 = w1 = u0 = u1 = fTempVar = 0; fTemp0 = fTemp1 = 0; //前景,背景区分 [0-k][k+1-255] for (int i = 0; i < nGrayScale; ++i) { //如果当前像素值小于阈值k则属于背景,反之属于目标 if (i <= k) { //计算背景像素占比 w0 += fPixelPct[i]; //计算当前灰度值发生的概率:灰度值*灰度值发生的概率 fTemp0 += (i * fPixelPct[i]); } else { //计算背景像素占比 w1 += fPixelPct[i]; fTemp1 += (i * fPixelPct[i]); } } //计算平均灰度值:p0/w0 u0 = fTemp0 / w0; u1 = fTemp1 / w1; //计算类内方差 fTempVar = (float)(w0 * w1 * pow((u0 - u1), 2)); if (fTempVar > fMaxVar) { fMaxVar = fTempVar; fBestValue = k; } } threshold(src, dst, fBestValue, 255, THRESH_BINARY);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。