目前,我想自动获取阈值,我使用了opencv cv::mean()来获取图像的亮度,然后将该值应用到阈值函数中,但结果不是我预期的。
对于上图,我手动设置的阈值是 195,但是当使用 cv::mean() 时,我得到的值是 225,这不是我想要的结果。我也尝试过 THRESH_OTSU 但结果也不同。
_brightnessCvS = cv::mean(_grayCvMat); m_dBright = _brightnessCvs.val[0];
有没有办法自动检测阈值以获得与图片相同的结果?
我考虑仅使用边缘区域的平均值而不是整个图像。
(当然,这种方式需要另一个启发式阈值来检测边缘区域......但确定这个值可能比原始问题更容易。)
int main()
{
//Load image as gray-scale
cv::Mat SrcImg = cv::imread( "Gray.png", cv::IMREAD_GRAYSCALE );
if( SrcImg.empty() )return 0;
cv::imshow( "SrcImg", SrcImg );
//Create Edge Region Only Mask
cv::Mat Mask;
{
cv::morphologyEx(
SrcImg, Mask, cv::MORPH_GRADIENT,
cv::getStructuringElement( cv::MORPH_RECT , cv::Size(3,3) )
);
//Here, threshold for "edge or not" is decided heuristically.
double MinVal, MaxVal;
cv::minMaxLoc( Mask, &MinVal, &MaxVal );
cv::threshold( Mask, Mask, 0.25*(MinVal+MaxVal), 255, cv::THRESH_BINARY );
cv::imshow( "Mask", Mask );
}
//Decide threshold as mean value of Masked region
double Thresh = cv::mean( SrcImg, Mask )[0];
cv::threshold( SrcImg, SrcImg, Thresh, 255, cv::THRESH_BINARY );
cv::imshow( "Result", SrcImg );
std::cout << Thresh << std::endl;
cv::waitKey();
return 0;
}
为了测试这段代码,我用手粗略地从您发布的图像中剪切了源图像,因此,我的源图像会丢失边界附近的区域。
但我认为这不会对结果产生太大影响。
我得到了阈值
191.087
。这个值看起来很接近你的值。
这是二值化结果:
注意:不用说,这个简单的方法假设黑色和白色之间的边界(边缘)处的梯度值是均匀的。 因此,不能直接应用于一般图像。