OpenCV版本:OpenCV4.1
二值图像:图像中的像素灰度值无论在什么数据类型中都只有最大值和最小值两种取值。这种“非黑即白”的图像称为二值图像。
将非二值图像经过计算变成二值图像的过程称为图像的二值化。
double cv::threshold(InputArray src,
OutputArray dst,
double thresh,
double maxval,
int type)
/*
* src:待二值化的图像,图像只能是CV_8U和CV_32F两种数据类型。
* 对于图像通道数目的要求与选择的二值化方法相关。
* dst:二值化后的图像,与输入图像具有相同的尺寸、数据类型和通道数。
* thresh:二值化的阈值
* maxval:二值化过程的最大值,它只在THRESH_BINARY和THRESH_BINARY_INV
* 两种二值化方法中才使用。
* type:选择图像二值化方法的标志
*/
type标志参数 | 简记 | 作用 |
---|---|---|
THRESH_BINARY | 0 | 灰度值大于阈值的为最大值,其他值为0 |
THRESH_BINARY_INV | 1 | 灰度值大于阈值的为0,其他值为最大值 |
THRESH_TRUNC | 2 | 灰度值大于阈值的为阈值,其他值不变 |
THRESH_TOZERO | 3 | 灰度值大于阈值的不变,其他值为0 |
THRESH_TOZERO_INV | 4 | 灰度值大于阈值的为0,其他值不变 |
THRESH_OTSU | 8 | 大津法自动寻求全局阈值 |
THRESH_TRIANGLE | 16 | 三角形法自动寻找全局阈值 |
这两个标志是相反的二值化方法,THRESH_BINARY是将灰度值与阈值(第三个参数thresh)进行比较,如果灰度值大于阈值,就将灰度值改为函数中第四个参数maxval的值,否则将灰度值改为0.THRESH_BINARY_INV标志正好与这个过程相反,如果灰度值大于阈值,就将灰度值改为0,否则将灰度值改为maxval的值。
公式:
这个标志相当于重新给图像的灰度值设定一个新的最大值,将大于新的最大值的灰度值全部重新设置为新的最大值,具体逻辑为将灰度值与阈值thresh进行比较,如果灰度值大于thresh,则将灰度值改为thresh,否则保持灰度值不变。这种方法没用使用到函数中的第四个参数maxval的值,因此maxval的值对本方法不产生影响。
公式:
这两个标志是相反的阈值比较方法,THRESH_TOZERO表示将灰度值与阈值thresh进行比较,如果灰度值大于thresh,则将保持不变,否则将灰度值改为0。THRESH_TOZERO_INV方法与其相反,将灰度值与阈值thresh进行比较,如果灰度值小于或等于thresh,则将保持不变,否则将灰度值改为0。这两种方法没有使用到函数中的第四个参数maxval的值,因此maxval的值对本方法不产生影响。
公式:
这两种标志是获取阈值的方法,并不是阈值比较方法的标志,这两个标志可以与前面5中标志一起使用,例如“THRESH_BINARY | THRESH_OTSU”。前面5种标志在调用函数时都需要人为地设置阈值,如果对图像不太了解,设置的阈值不合理,就会对处理后的效果造成严重的影响。
这两个标志分别表示利用大津法(OTSU)和三角形法(TRIANGLE)结合图像灰度值分布特性获取二值化的阈值,并将阈值以函数返回值的形式给出。因此,如果该函数最后一个参数设置了这两个标志中的任何一个,那么该函数第三个参数thresh将由系统自动给出,但是在调用函数时仍然不能默认,只是程序不会使用这个数值。需要注意的是,到目前,OpenCV4中针对这两个标志只支持输入CV_8UC1类型的图像。
threshold()函数全局只使用一个阈值,在实际情况中,由于光照不均匀以及阴影的存在,全局只有一个阈值会使得在阴影处的白色区域也会被函数二值化成黑色,因此adaptiveThreshold()函数提供了两种全局自适应阈值的二值化方法。
void cv::adaptiveThreshold(InputArray src,
OutputArray dst,
double maxValue,
int adaptiveMethod,
int thresholdType,
int blockSize,
double C)
/*
* src:待二值化的图像,图像只能是CV_8UC1数据类型
* dst:二值化后的图像,与输入图像具有相同的尺寸,数据类型
* maxValue:二值化的最大值
* adaptiveMethod:自适应确定阈值的方法,
* 分为均值法ADAPTIVE_THRESH_MEAN_C和高斯法ADAPTIVE_THRESH_GAUSSIAN_C两种
* thresholdType:选择图像二值化方法的标志,只能是THRESH_BINARY和THRESH_BINARY_INV
* blockSize:自适应确定阈值的像素邻域大小,一般为3、5、7的奇数
* C:从平均值或者加权值中减去的常数,可以为正,也可以为负
*/
该函数将灰度图转换为二值图像,通过均值法和高斯法自适应地计算blockSize*blockSize邻域内的阈值,之后进行二值化。
#include
#include
using namespace std;
using namespace cv;
int main(void)
{
Mat img = imread("lena.png");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
imshow("img", img);
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
imshow("gray", gray);
Mat img_B, img_B_V, gray_B, gray_B_V, gray_T, gray_T_V, gray_TRUNC;
// 彩色图像二值化
threshold(img, img_B, 125, 255, THRESH_BINARY);
threshold(img, img_B_V, 125, 255, THRESH_BINARY_INV);
imshow("img_B", img_B);
imshow("img_B_V", img_B_V);
// 灰度图BINARY二值化
threshold(gray, gray_B, 125, 255, THRESH_BINARY);
threshold(gray, gray_B_V, 125, 255, THRESH_BINARY_INV);
imshow("gray_B", gray_B);
imshow("gray_B_V", gray_B_V);
// 灰度图像TOZERO变换
threshold(gray, gray_T, 125, 255, THRESH_TOZERO);
threshold(gray, gray_T_V, 125, 255, THRESH_TOZERO_INV);
imshow("gray_T", gray_T);
imshow("gray_T_V", gray_T_V);
// 灰度图像TRUNC变换
threshold(gray, gray_TRUNC, 125, 255, THRESH_TRUNC);
imshow("gray_TRUNC", gray_TRUNC);
// 灰度图像大律法和三角形法二值化
Mat img_Thr = imread("threshold.png", IMREAD_GRAYSCALE);
Mat img_Thr_O, img_Thr_T;
threshold(img_Thr, img_Thr_O, 100, 255, THRESH_BINARY | THRESH_OTSU);
threshold(img_Thr, img_Thr_T, 125, 255, THRESH_BINARY | THRESH_TRIANGLE);
imshow("img_Thr", img_Thr);
imshow("img_Thr_O", img_Thr_O);
imshow("img_Thr_T", img_Thr_T);
// 灰度图像自适应二值化
Mat adaptive_mean, adaptive_guass;
adaptiveThreshold(img_Thr, adaptive_mean, 255, ADAPTIVE_THRESH_MEAN_C,
THRESH_BINARY, 55, 0);
adaptiveThreshold(img_Thr, adaptive_guass, 255, ADAPTIVE_THRESH_GAUSSIAN_C,
THRESH_BINARY, 55, 0);
imshow("adaptive_mean", adaptive_mean);
imshow("adaptive_guass", adaptive_guass);
waitKey(0);
return 0;
}