转载请注明出处,谢谢.
1. OpenCV - 区域生长算法
2. OpenCV - 均值迭代分割
3. OpenCV - 最大间方差(OTUS)分割
4. OpenCV - 最大熵分割
OpenCV中其实有对OTUS算法的实现,threhold()函数最后一个参数可以指定使用OTUS算法。
1、最大间方差(OTUS)算法的描述
和均值迭代算法相似,OTUS算法也是利用图像的直方图进行的。OTUS算法的思想是选取一个阈值
T,T∈[0,m−1]
,
m
为图像的灰度级将直方图两部分,
2、算法的步骤
待处理图像灰度值范围为
[0,m−1]
, 记灰度值为
i
的像素个数为
1. 统计待处理图像中像素灰度总和
N
:
2. 计算每个灰度值 i,i∈[0,m−1] 所占的概率:
pi=niN
灰度均值
μ
:
μ=∑i=0m−1i∗pi
3. 取灰度值 T=0,‘1,...m−1 ,利用 T 将所有灰度分成两组
第一类所占的概率:
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 ,使用
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、拓展
和上一篇所述一样,如果我们需要分割的物体并不是规则的矩形,那么任然可以采用在直方图中将我们已知的无效像素去掉。