matlab中threshold,OpenCV中threshold自动阈值,类似matlab中的graythresh

本文详细解析了OpenCV中如何使用Otsu方法对灰度图像进行自动阈值分割,并展示了如何自定义函数getThreshVal_Otsu_8u进行8位图像处理。通过实例说明了调用该函数后如何进行二值化操作,适用于图像处理初学者和开发者。
摘要由CSDN通过智能技术生成

在opencv工程里面使用otsu分割灰度图像类似于matlab里的graythresh,

opencv里面提供了otsu threshold的源代码“icvGetThreshVal_Otsu”,我们可以根据源代码进行自动阈值处理

icvGetThreshVal_Otsu的源代码如下:

//opencv Source code:

static double icvGetThreshVal_Otsu( const CvHistogram* hist )

{

double max_val = 0;

CV_FUNCNAME( "icvGetThreshVal_Otsu" );

__BEGIN__;

int i, count;

const float* h;

double sum = 0, mu = 0;

bool uniform = false;

double low = 0, high = 0, delta = 0;

float* nu_thresh = 0;

double mu1 = 0, q1 = 0;

double max_sigma = 0;

if( !CV_IS_HIST(hist) || CV_IS_SPARSE_HIST(hist) || hist->mat.dims != 1 )

CV_ERROR( CV_StsBadArg,

"The histogram in Otsu method must be a valid dense 1D histogram" );

count = hist->mat.dim[0].size;

h = (float*)cvPtr1D( hist->bins, 0 );

if( !CV_HIST_HAS_RANGES(hist) || CV_IS_UNIFORM_HIST(hist) )

{

if( CV_HIST_HAS_RANGES(hist) )

{

low = hist->thresh[0][0];

high = hist->thresh[0][1];

}

else

{

low = 0;

high = count;

}

delta = (high-low)/count;

low += delta*0.5;

uniform = true;

}

else

nu_thresh = hist->thresh2[0];

for( i = 0; i < count; i++ )

{

sum += h;

if( uniform )

mu += (i*delta + low)*h;

else

mu += (nu_thresh[i*2] + nu_thresh[i*2+1])*0.5*h;

}

sum = fabs(sum) > FLT_EPSILON ? 1./sum : 0;

mu *= sum;

mu1 = 0;

q1 = 0;

for( i = 0; i < count; i++ )

{

double p_i, q2, mu2, val_i, sigma;

p_i = h*sum;

mu1 *= q1;

q1 += p_i;

q2 = 1. - q1;

if( MIN(q1,q2) < FLT_EPSILON || MAX(q1,q2) > 1. - FLT_EPSILON )

continue;

if( uniform )

val_i = i*delta + low;

else

val_i = (nu_thresh[i*2] + nu_thresh[i*2+1])*0.5;

mu1 = (mu1 + val_i*p_i)/q1;

mu2 = (mu - q1*mu1)/q2;

sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);

if( sigma > max_sigma )

{

max_sigma = sigma;

max_val = val_i;

}

}

__END__;

return max_val;

}对源代码进行改写,得到我们想要的代码:

double getThreshVal_Otsu_8u( const cv::Mat& _src )

{

cv::Size size = _src.size();

if ( _src.isContinuous() )

{

size.width *= size.height;

size.height = 1;

}

const int N = 256;

int i, j, h[N] = {0};

for ( i = 0; i < size.height; i++ )

{

const uchar* src = _src.data + _src.step*i;

for ( j = 0; j <= size.width - 4; j += 4 )

{

int v0 = src[j], v1 = src[j+1];

h[v0]++; h[v1]++;

v0 = src[j+2]; v1 = src[j+3];

h[v0]++; h[v1]++;

}

for ( ; j < size.width; j++ )

h[src[j]]++;

}

double mu = 0, scale = 1./(size.width*size.height);

for ( i = 0; i < N; i++ )

mu += i*h[i];

mu *= scale;

double mu1 = 0, q1 = 0;

double max_sigma = 0, max_val = 0;

for ( i = 0; i < N; i++ )

{

double p_i, q2, mu2, sigma;

p_i = h[i]*scale;

mu1 *= q1;

q1 += p_i;

q2 = 1. - q1;

if ( std::min(q1,q2) < FLT_EPSILON || std::max(q1,q2) > 1. - FLT_EPSILON )

continue;

mu1 = (mu1 + i*p_i)/q1;

mu2 = (mu - q1*mu1)/q2;

sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);

if ( sigma > max_sigma )

{

max_sigma = sigma;

max_val = i;

}

}

return max_val;

}直接进行调用上述函数,即可:

m_threshold = getThreshVal_Otsu_8u(matMedian);在进行二值化:

threshold(matMedian,matBinary,m_threshold,255,0); // 二值化

详细请参考OpenCV

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值