您的位置:首页 > 运维架构

OpenCV - 最大间方差分割

2016-12-06 20:10 363 查看
转载请注明出处,谢谢.

1. OpenCV - 区域生长算法

2. OpenCV - 均值迭代分割

3. OpenCV - 最大间方差(OTUS)分割

4. OpenCV - 最大熵分割

OpenCV中其实有对OTUS算法的实现,threhold()函数最后一个参数可以指定使用OTUS算法。

1、最大间方差(OTUS)算法的描述

和均值迭代算法相似,OTUS算法也是利用图像的直方图进行的。OTUS算法的思想是选取一个阈值T,T∈[0,m−1],m为图像的灰度级将直方图两部分,T值使得分成的两组间方差最大。

2、算法的步骤

待处理图像灰度值范围为[0,m−1], 记灰度值为i的像素个数为ni.

1. 统计待处理图像中像素灰度总和N:

N=∑i=0m−1ni

2. 计算每个灰度值i,i∈[0,m−1]所占的概率:pi=niN灰度均值μ:μ=∑i=0m−1i∗pi

3. 取灰度值T=0,‘1,...m−1,利用T将所有灰度分成两组C0=0...T−1和C1=T...m−1,两组的均值和概率表示为:

第一类所占的概率:w0=∑i=0T−1pi

第一类的均值:μ0=∑i=0T−1i∗piw0

第二类所占的概率:w1=∑i=Tm−1pi=1−w0

第二类的均值:μ1=∑i=Tm−1i∗piw1

4. 计算两组间的方差:δ2=w0(μ0−μ)2+w1(μ1−μ)2

5. 重复过程2 - 4,找到组间方差最大的灰度值i,使用i对图像进行阈值分割即可。

3、OpenCV下的实现

Mat OstuSeg(Mat src)
{
int tbHist[256] = {0};                      //直方图数组
double average = 0.0;                       //平均像素值
double cov = 0.0;                           //方差
double maxcov = 0.0;                        //方差最大值
int index = 0;                              //分割像素值
Mat dst;
int nCol = src.cols * src.channels();       //每行的像素个数
for (int i = 0; i < src.rows; i++)
{
uchar* pData = src.ptr<uchar>(i);
for (int j = 0; j < nCol; ++j)
{
tbHist[pData[j]] += 1;
}
}

int sum = 0;
for (int i=0; i<256; ++i)
sum += tbHist[i];

double w0=0.0, w1=0.0, u0=0.0, u1=0.0;
int count0 = 0;
for (int i = 0; i < 255; ++i)
{
u0 = 0;
count0 = 0;
for (int j=0; j<=i; ++j)
{
u0 += j * tbHist[j];
count0 += tbHist[j];
}
u0 = u0/count0;
w0 = (float)count0/sum;

u1 = 0;
for (int j=i+1; j<256; ++j)
u1 += j*tbHist[j];

u1 = u1/(sum - count0);
w1 = 1 - w0;
cov = w0*w1*(u1-u0)*(u1-u0);
if (cov > maxcov)
{
maxcov = cov;
index = i;
}
}
cv::threshold(src, dst, index, 255, 0);    //进行阈值分割
return dst.clone();
}


4、拓展

和上一篇所述一样,如果我们需要分割的物体并不是规则的矩形,那么任然可以采用在直方图中将我们已知的无效像素去掉。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: