查看原文
其他

干货 | 简单粗暴二分类分割方法Riddler-Calvard 详解!

gloomyfish OpenCV学堂 2020-02-04

点击上方蓝字关注我们

微信公众号:OpenCV学堂
关注获取更多计算机视觉与深度学习知识

二值图像

图像二值化就就是把灰度图像分割为只有白色(前景)与黑色(背景)两种颜色的图像,通常用

0-表示黑色

1-表示白色(255)

一个典型的二值图像表示如下:

图像二值化,根据阈值使用的方法不同可以分为如下三类:

1.全局阈值法,意思是通过一个阈值实现对所有像素的二值化分割

2.局部阈值法,通过多个局部阈值实现二值化分割

3.自适应阈值法,通过与自身周围像素比较,直接二值化

Riddler-Calvard算法

Riddler-Calvard阈值法是基于直方图的二值化算法,是经典的全局阈值法,可惜OpenCV的全局阈值只支持OTSU大律法与Triangle两种,不支持Riddler-Calvard阈值法,其实Riddler-Calvard跟OTSU与Triangle一样都是基于直方图计算得到阈值的二值化分割算法,唯一个不同的是Riddler-Calvard是基于迭代查找实现,它的算法步骤描述如下:

首先假设初始阈值T比如T=127,然后得到分割后的两个像素cluster。计算它们的均值分别如下:

其中g表示图像像素灰度值,灰度值范围g={0,1,2,3,,,,,L-1},其中L=256表示256个灰度级别。P(g)表示图像直方图统计概率百分比。下标:f表示前景,b表示背景。计算得到新的阈值:

计算两个阈值之间的差值

如果差值大于指定错误,则用新阈值来计算(1)、(2)、然后计算(3),不断更新阈值,直到错误小于指定错误或者迭代次数超过指定次数为止。根据最终得到阈值T实现图像二值分割。

代码实现

初始化变量与定义

1// 初始化变量
2float mf = 0.0;
3float mb = 0.0;
4float hist[256];
5float t = 127.0;
6float t1 = 0.0;
7float err = 1;
8int max_count = 5;
9for (int i = 0; i < 256; i++) {
10    hist[i] = 0;
11}

计算直方图分布

1// 计算直方图
2int h = gray.rows;
3int w = gray.cols;
4for (int row = 0; row < h; row++) {
5    for (int col = 0; col < w; col++) {
6        int pv = gray.at<uchar>(row, col);
7        hist[pv]++;
8    }
9}
10
11// 归一化
12float total = w*h;
13for (int i = 0; i < 256; i++) {
14    hist[i] = hist[i]/total;
15}

迭代寻找阈值

1// 寻找阈值
2int index = 0;
3while (true) {
4    for (int i = 0; i < 256; i++) {
5        if (i > t) {
6            mf += hist[i] * i;
7        }
8        else {
9            mb += hist[i] * i;
10        }
11    }
12    t1 = (mb + mf) / 2.0;
13    index++;
14    if (abs(t1 - t) <= err || index > max_count) {
15        break;
16    }
17    else {
18        mf = 0.0;
19        mb = 0.0;
20        t = t1;
21    }
22}
23printf("final threshold value: %.2f \n", t);

使用阈值完成二值化

1// 阈值使用
2for (int row = 0; row < h; row++) {
3    for (int col = 0; col < w; col++) {
4        int pv = gray.at<uchar>(row, col);
5        if (pv > t) {
6            binary.at<uchar>(row, col) = 255;
7        }
8        else {
9            binary.at<uchar>(row, col) = 0;
10        }
11    }
12}

测试运行结果如下:

推荐阅读

OpenCV加速与优化,让代码执行速度飞起来

详解对象检测网络性能评价指标mAP计算

OpenCV中图像二值化函数调用几个关键点详解

OpenCV中如何提取不规则ROI区域

对象检测新趋势anchor-free模型之CenterNet

anchor-free对象检测网络CornerNet详解

升级到tensorflow2.0,我整个人都不好了

CPU上跑深度学习模型,FPS也可以达100帧

OpenVINO深度学习推理框架 开发技术系列文章汇总

OpenCV4 | 如何一行代码搞定SSD模型推理与结果解析

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存