用于光照不均匀图片阈值化的Bernsen算法的OpenCV实现

Bernsen算法的中心思想:

设当前像素为P,计算以P为中心的大小为(2k+1)*(2k+1)窗口内的所有像素的最大值Max与最小值Min,两者的均值T,

伪代码如下:

    if(Max-Min)> S

        则当前点P的阈值为T。

    else

        当前窗口所在区域的灰度级差别较小,那么窗口在目标区或在背景区,若T>Th则当前点灰度值为255,否则,当前点灰度值为0.

S和Th可以根据需要进行调整,本文中将S最初设为15, Th设为128。

//Bernsen算法
void Bernsen(const cv::Mat &src,cv::Mat &dst,int blockSize,int Th,int S){
    cv::Mat padded(src);
    //对原图的边缘进行扩展
    cv::copyMakeBorder(src,padded,blockSize,blockSize,blockSize,blockSize,cv::BORDER_CONSTANT,cv::Scalar::all(0));
    int row=padded.rows;
    int col=padded.cols;
    for(int i=blockSize;i<row-blockSize;i++){
        const uchar* p=padded.ptr<const uchar>(i);
        uchar* q=dst.ptr<uchar>(i-blockSize);
        for(int j=blockSize;j<col-blockSize;j++){
            //求(i,j)像素点邻域内的最大值和最小值
            int max=0,min=256;
            int T=0;
            for(int k=i-blockSize;k<i+blockSize;k++){
                const uchar* ptr=padded.ptr<const uchar>(k);
                for(int l=j-blockSize;l<j+blockSize;l++){
                    if(ptr[l]>max)
                        max=ptr[l];
                    if(ptr[l]<min)
                        min=ptr[l];
                }
            }
            //求max和min的均值
            T=(max+min)>>1;
 
 
            if((max-min)>S){//如果max-min>S,那么阈值设为T
                q[j-blockSize]=p[j]>T ? 255:0;
            }
            else{//若T>Th,则当前像素点灰度值为255;否则,当前像素点灰度值为0.
                q[j-blockSize]=T>Th ? 255:0;
            }
        }
    }
}

效果图如下:

         

                                    原图                                                                                效果图

整体效果来看还是不错,只是时间复杂度太大,计算过程太耗时间!

这种最原始的算法的效果总体来说还行,但一般所用的Bernsen算法都是经过各种改进的。

猜你喜欢

转载自blog.csdn.net/Leon_yy/article/details/80314380