OpenCV 像 Matlab 函数 graythresh 一样只得到 Otsu 阈值
OpenCV get only Otsu Threshold value like Matlab function graythresh
如何像Matlab函数graythresh一样使用OpenCV只获取Otsu Threshold值。
例如,如果我编写这段代码,我会像使用 Matlab 函数 im2bw 一样得到二进制图像:
Mat bw;
uint8_t data[14] = { 10, 10, 10, 10, 10, 10, 20, 20, 54, 54, 54, 54, 55, 55 };
Mat M(1, 14, CV_8UC1, &data);
threshold(M, bw, 0, 1, CV_THRESH_BINARY | CV_THRESH_OTSU);
函数 cv::threshold()
returns 如果设置 THRESH_OTSU
标志则计算阈值。
double thres_val = cv::threshold(M, bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
有关详细信息,请参阅 cv::threshold()。
如果你想避免执行阈值而你只想要值,请执行 OpenCV 中的操作:
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;
}
将它放在您自己的命名空间中,或放在匿名命名空间中,以避免可能的冲突。
如何像Matlab函数graythresh一样使用OpenCV只获取Otsu Threshold值。
例如,如果我编写这段代码,我会像使用 Matlab 函数 im2bw 一样得到二进制图像:
Mat bw;
uint8_t data[14] = { 10, 10, 10, 10, 10, 10, 20, 20, 54, 54, 54, 54, 55, 55 };
Mat M(1, 14, CV_8UC1, &data);
threshold(M, bw, 0, 1, CV_THRESH_BINARY | CV_THRESH_OTSU);
函数 cv::threshold()
returns 如果设置 THRESH_OTSU
标志则计算阈值。
double thres_val = cv::threshold(M, bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
有关详细信息,请参阅 cv::threshold()。
如果你想避免执行阈值而你只想要值,请执行 OpenCV 中的操作:
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;
}
将它放在您自己的命名空间中,或放在匿名命名空间中,以避免可能的冲突。