先来说明一下什么叫阈值,通俗来讲阈值就是一条分界线,像素点显示范围是0-255,阈值就是在0-255这个范围,取一个数作为分界线,对于比这条分界线大的数一种处理方式,比这条分界线小的数采取另一种处理方式。我们使用函threshould()来实现这些功能。
double threshold(
InputArray src, //原始图像
OutputArray dst, //处理后图像
double thresh, //阈值
double maxValue, //某规定像素点的值
int threshouldType //可选的处理类型
);
thresholdType的可选参数列表
enum
{
THRESH_BINARY, //目标像素点=(当前像素点>阈值)?maxValue:0
THRESH_BINARY_INV, //目标像素点=(当前像素点>阈值)?0:maxValue
THRESH_TRUNC, //目标像素点=(当前像素点>阈值)?阈值:当前像素点
THRESH_TOZERO, //目标像素点=(当前像素点>阈值)?当前像素点:0
THRESH_TOZERO_INV //目标像素点=(当前像素点>阈值)?0:当前像素点
};
这里插入一个小小的知识点,这是《学习opencv3》中遇到的
void cvAddWeighted(
const CvArr* src1,
double alpha,
const CvArr* src2,
double beta,
double gamma,
CvArr* dst
);
参数1:src1,第一个原数组.
参数2:alpha,第一个数组元素权重
参数3:src2第二个原数组
参数4:beta,第二个数组元素权重
参数5:gamma,图1与图2作和后添加的数值。不要太大,不然图片一片白。总和等于255以上就是纯白色了。
参数6:dst,输出图片
/**
这一部分转载的【opencv 常用的数据类型(vector、contours的解释)】https://mbd.baidu.com/ma/s/e81ffJkb
关于vector类的使用(这也是在《学习opencv3》中不明白的知识点)
vector< Vec4i > hierarchy;
首先,他是一个数组的容器,里面放的是4个int的整数。
可能新司机 会有点绕。看这个解释:
vector h ,一次只放一个整数,赋值一个int
vector h1, 一次放四个整数。 给它赋一个 vec4i就可以
Vec4i int4,temp;//四维整数;
//可以直接赋值 int4(2,3,4,5);
temp = { 2,3,4,5 };
int4 = { 1,2,3,4};
vector hierarchy;
hierarchy.push_back(temp);//vector的添加元素,自行查看c++11
hierarchy.push_back(int4);
cout << hierarchy[0] << endl;
//输出{ 2,3,4,5 };
cout<
*/
设t为设定的阈值,比t大的称为前景比t小的称为背景
wo: 前景像素点数占图像的比例
uo: 前景像素点的平均灰度
w1:背景像素点数占图像的比例
u1: 背景像素点的平均灰度
u=w0*u0 + w1*u1 :图像总平均灰度
从L个灰度级遍历t,使得t为某个值的时候,前景和背景的方差最大, 则 这个 t 值便是我们要求得的阈值。
其中,方差的计算公式如下:
g=wo * (uo - u) * (uo - u) + w1 * (u1 - u) * (u1 - u)
这个函数使用非常简单对threshold()传入参数THRESH_OTSU就可以了
利用图像局部阈值替换全局阈值进行图像计算的一种方法,具体针对光影变化过大的图片,或者范围内颜色差异不太明显的图片(摘自百度百科),我们来解释一下什么叫光影变化较大,比如说你有一副图片,这张图由于光线原因,在某些比较暗的位置因为反光这一块整体却比较亮,那么如果从整张图片的角度来看很有可能这一部分就会被误划入前景范围,这不是我们想要的结果,我们可以考虑把这一部分单独提取出来,那么我们就不用担心会误判了,因为这一部分光线比较平均,我们不会因此损失这一部分的特征值。
好了我们到此已经明白什么是自适应阈值了,一句话就是将图像分成很多小区域,分别进行阈值操作。
下面我们来看看自适应阈值函数
void adaptiveThreshold(
InputArray src, //原图像
OutputArray dst, //处理后图像
double maxValue, //某一固定值
int adaptiveMethod, //自适应阈值方式,高斯和平均值两种方式
int thresholdType, //阈值化方式,同上述表中的参数一样
int blockSize, //区块大小
double C //常数
);
这个函数中我们主要看第五六七这三个参数,一到四和普通阈值化没有区别。
对于参数thresholdType,我们可以有两种参数选择传入
1.ADAPTIVE_THRESH_GAUSSIAN_C,
这种取阈值的方式,是通过对一个区块的像素点的灰度值进行高斯加权,再加上或者减去常数C作为阈值,这个权数是通过每个像素到中点的距离通过高斯方程得到。(这个算法相对复杂我后面会单独开一篇博客进行讲解)
2.ADAPTIVE_THRESH_MEAN_C
这种取阈值的方式是通过所取均值的方法,就是以计算区域像素点灰度值的平均值再加上或者减去常数C,作为该区域的阈值。