自适应的阈值化

对图像应用阈值创建二值图像,是提取有意义元素的好方法。但有的时候单一阈值达不到目标提取的效果。
下面比较一下几种方法的效果。例如,给定一幅图如下,将“富贵白头”四个字提取出来。
这里写图片描述
通过OpenCV阈值化函数cv::threshold(),纯手工选择参数,进行固定阈值二值化,发现当阈值设为80时效果最好。

//采用固定阈值
cv::threshold(image, binaryFixed, 80, 255, cv::THRESH_BINARY);

固定阈值(取为80)的效果,其实还行了,只不过阈值还是得手工微调:
这里写图片描述

采用最大类间方差法怎么样?自动选择最优阈值(其实还是单一阈值)。

//大津法
std::cout<<cv::threshold(image,binaryOTSU,70,255,cv::THRESH_OTSU);//经测试cout输出为143

可见大津法算出的阈值为143。但是阈值化效果是很差的:
这里写图片描述
下面采用OpenCV的自适应阈值化方法:

cv::adaptiveThreshold(image,binaryAdaptive,255,cv::ADAPTIVE_THRESH_MEAN_C,cv::THRESH_BINARY,7,-4);

效果如下,还不错,同时花树的轮廓也描绘出了:
这里写图片描述

自适应阈值是一种局部方法。它的原理是根据每个像素的邻域计算阈值,包括上面语句采用的将每个像素的值与邻域的平均值进行比较。如果某像素的值与它的局部平均值差别很大,就会被当做异常值在阈值化过程中被分离。
代码实现:
1、使用积分图像实现自适应阈值化

//自己实现自定义阈值
    cv::Mat iimage;
    cv::integral(image,iimage,CV_32S);

    cv::Mat binary;
    image.copyTo(binary);

    int blockSize = 7;
    int threshold = -4;//像素将与(mean-threshold)比较
    int halfSize = blockSize / 2;
    for (int j = halfSize; j < image.rows-halfSize-1;j++)
    {
        //j行首地址
        uchar* data = binary.ptr<uchar>(j);
        int *data1 = iimage.ptr<int>(j-halfSize);
        int *data2 = iimage.ptr<int>(j+halfSize+1);
        for (int i = halfSize; i < image.cols - halfSize - 1;i++)
        {
            int sum = (data2[i + halfSize + 1] - 
                data2[i-halfSize] - 
                data1[i + halfSize + 1] + 
                data1[i-halfSize])/
                (blockSize*blockSize);
            if (data[i] > (sum - threshold))
                data[i] = 255;
            else
                data[i] = 0;
        }
    }
    cv::imshow("thresholdAdaptive",binary);

为了简化计算,计算像素周围方形邻域像素的和,采用了积分图像。假设邻域块的大小为blockSize*blockSize,不采用积分图像,每次需要计算blockSize*blockSize次加法运算;而采用积分图像,运算复杂度并不随邻域大小而改变,每次只需计算2次加法和2次减法。
2、使用盒子滤波实现自适应阈值化

cv::Mat filtered;
cv::Mat binaryFiltered;
cv::boxFilter(image,filtered,CV_8U,cv::Size(7,7));//这个盒子滤波相当于平均的效果
filtered = filtered + 4;
binaryFiltered = image >= filtered;
imshow("thresholdBox",binaryFiltered);
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值