在二维数字图像中,其每个像素点对应了不同的像素值,其像素值各不相同。可以对像素值特定范围内的图像图像进行操作,划分这个范围的值就被称为图像阈值,它不是一个固定的量级,是根据每幅图像和处理要求动态改变。例如我们可以从图像中利用阈值分割出我们需要的部分,利用其像素值与背景在灰度特性上的差异,图像具有了不同的灰度等级,可据此指定一个合理的阈值从而确定图像中的像素值是否属于这个区域。所以其是像素操作的一种形式。
opencv官方文件中给出的解释是:为了从一幅图像中提取我们需要的部分,应该用图像中的每一个像素点的灰度值与选取的阈值进行比较,并作出相应的判断(阈值的选取依赖于具体的问题,物体在不同的图像中可能会有不同的灰度值)。
一旦找到了需要分割的物体像素点,我们可以对这些像素点设定一些特定的值来标识(例如:可以将物体的像素点的灰度值设定为:’0’黑色,其他的像素点灰度值设置为:’255’白色;当然像素点的灰度值可以任意,但最好设定两种颜色对比度较强,方便观察结果)。
给出一个简单的有关像素灰度的图片,如下:
图中的蓝色水平线代表着具体的一个阈值。
opencv提供了threshold()函数对图像的阈值进行处理,threshold()共支持五中类型的阈值化方式,分别是二进制阈值化、反二进制阈值化、截断阈值化、阈值化为0和反阈值化为0。
1.二进制阈值化
二进制阈值化的数学公式如下:
在运用二进制阈值化操作时,首先指定一个阈值量即像素的灰度值,遍历图像中像素值,大于这个阈值的像素均设置为最大像素值(如8位灰度值最大为255),灰度值小于设定阈值的像素点像素值重新赋值为0.得到如下图所示图像,借用二进制概念,超过该阈值即为1,否则为0.
2.反二进制阈值化
反二进制阈值化顾名思义就是与第一个阈值化类型相反,其数学公式如下:
与二进制阈值化相同的是也要首先指定一个阈值,不同的是在对图像进行阈值化操作时正好与二进制阈值化相反,当图像像素点超过这个阈值的时候像素点重新赋值为0,当像素值低于该阈值时即赋值为最大值,其阈值化后示意图如下所示:
3.截断阈值化
截断阈值化数学模型公式如下:
根据给定的像素值阈值,图像中大于该阈值的像素点被重新设置为该阈值,而小于该阈值的像素值保持不变。其阈值化后示意图如下:
与截断阈值化不同,阈值化为0类型像素点的灰度值如果大于该阈值则像素值不变,如果像素点的灰度值小于该阈值,则像素值设置为0.其示意图如下:
其原理类似于阈值化为0类型只不过在对图像进行操作时相反,像素值大于该阈值的像素重新赋值为0,而小于该阈值的像素值则保持不变,其示意图如下所示:
threshold()函数原型如下:
double cv::threshold ( InputArray src,
OutputArray dst,
double thresh,
double maxval,
int type
)
参数解释:
. InputArray src: 输入图像,可以是Mat类型,图像必须为单通道8位或32位浮点型图像
. OutputArray dst: 输出图像,与输入图像尺寸和类型相同
. double thresh: 设定的阈值
. double maxval: 使用THRESH_BINARY和THRESH_BINARY_INV类型的最大值
. int type: 阈值化类型,可以通过ThresholdTypes查看,下面给出opencv中五种阈值化类型及其对应公式:
示例程序如下:
/*
*程序通过创建trackbar来控制阈值化类型
*通过调节trackbar来调节
*其具体阈值化类型如下:
*0: THRESH_BINARY 二进制阈值化
*1: THRESH_BINARY_INV 反二进制阈值化
*2: THRESH_TRUNC 截断阈值化
*3: THRESH_TOZERO 阈值化为0
*4: THRESH_TOZERO_INV 反阈值化为0
*/
#include
#include
#include
#include
using namespace std;
using namespace cv;
//定义全局变量
Mat g_srcImage, g_srcGrayImage, g_dstImage;
const int typeMaxValue = 4;
int typeValue = 0;
const int binaryMaxValue = 255;
const int thresholdMaxValue = 255; //阈值的最大值
int thresholdValue = 0; //阈值的初始值
//定义回调函数
void thresholdFun(int, void*);
int main()
{
g_srcImage = imread("lena.jpg");
//判断图像是否加载成功
if(g_srcImage.empty())
{
cout << "图像记载失败!" << endl;
return -1;
}
else
cout << "图像加载成功!" << endl << endl;
cvtColor(g_srcImage, g_srcGrayImage, COLOR_RGB2GRAY); //将图像转化为灰度图
//创建轨迹条及其依附窗口
namedWindow("图像阈值化处理", WINDOW_AUTOSIZE);
char threasholdTypeName[20];
sprintf(threasholdTypeName, "阈值化类型 %d", typeMaxValue);
createTrackbar(threasholdTypeName, "图像阈值化处理", &typeValue, typeMaxValue, thresholdFun);
thresholdFun(typeValue, 0);
char thresholdValueName[20];
sprintf(thresholdValueName, "阈 值 %", thresholdMaxValue);
createTrackbar(thresholdValueName, "图像阈值化处理", &thresholdValue, thresholdMaxValue, thresholdFun);
thresholdFun(thresholdValue, 0);
waitKey(0);
return 0;
}
//回调函数
void thresholdFun(int, void*)
{
int thresholdType;
switch(typeValue)
{
case 0:
thresholdType = THRESH_BINARY;
break;
case 1:
thresholdType = THRESH_BINARY_INV;
break;
case 2:
thresholdType = THRESH_TRUNC;
break;
case 3:
thresholdType = THRESH_TOZERO;
break;
case 4:
thresholdType = THRESH_TOZERO_INV;
break;
default:
break;
}
//图像阈值化处理
threshold(g_srcGrayImage, g_dstImage, thresholdValue, binaryMaxValue, thresholdType);
imshow("图像阈值化处理", g_dstImage);
}