如何自动获取阈值

问题描述 投票:0回答:1

目前,我想自动获取阈值,我使用了opencv cv::mean()来获取图像的亮度,然后将该值应用到阈值函数中,但结果不是我预期的。

对于上图,我手动设置的阈值是 195,但是当使用 cv::mean() 时,我得到的值是 225,这不是我想要的结果。我也尝试过 THRESH_OTSU 但结果也不同。

_brightnessCvS = cv::mean(_grayCvMat); m_dBright = _brightnessCvs.val[0];

有没有办法自动检测阈值以获得与图片相同的结果?

c++ opencv computer-vision
1个回答
2
投票

我考虑仅使用边缘区域的平均值而不是整个图像。
(当然,这种方式需要另一个启发式阈值来检测边缘区域......但确定这个值可能比原始问题更容易。)

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
。这个值看起来很接近你的值。

这是二值化结果:

注意:不用说,这个简单的方法假设黑色和白色之间的边界(边缘)处的梯度值是均匀的。 因此,不能直接应用于一般图像。

© www.soinside.com 2019 - 2024. All rights reserved.