一、图像阈值二值化
比如有个原始信号,图片中的横线表示阈值,当信号大于阈值,定义为最大输出,当信号小于阈值,定义为最小输出。
阈值化可以简单地将其理解为一个信号的滤波。
固定阈值二值化
threshold()
double cv::threshold (InputArray src,
OutputArray dst,
double thresh,
double maxval,
int type
)
·src:待二值化地图像,图像只能是CV_8U和CV_32F两种数据类型。对于图像通道数目的要求和选择地二值化方法相关。
·dst:二值化后的图像,与输入图像具有相同的尺寸,数据类型和通道数。
·thresh:二值化的阈值。
·maxval:二值化过程中的最大值。
·type:选择图像二值化方法的标志
前面的几种二值化方法都是需要人为的给出一个比较阈值,若对图像充分了解,那么给出的阈值是比较合理的,可以将两者充分的分离开,如果对图像不是很了解,会造成给出的阈值,是偏离期望的阈值,就会造成二值化的时候得到非预期的结果,为了避免这种情况,在opencv中,集成了另外两种可以自动给出整幅图像阈值的两种算法,分别是OTSU大津算法和TRIANGLED三角形算法,我们调用的时候是与前面的几种算法相对应的,我们只需要在前面同一加上THRESH_...上面两种函数是自动给出阈值,也就是在阈值比较的时候,第三个参数是无用的,可以自由的给出。
示例
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv; //opencv的命名空间
using namespace std;
int main()
{
Mat img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/lenac.png");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
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("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/threshold.jpeg", IMREAD_GRAYSCALE);
Mat img_Thr_0, img_Thr_T;
threshold(img_Thr, img_Thr_0, 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_0", img_Thr_0);
imshow("img_Thr_T", img_Thr_T);
waitKey(0);
return 0;
}
结果
这种彩色图像是将每个通道单独的进行阈值化后将其进行组合,相当于是将亮色图像变白,暗色图像保留,因为这种方式是对每个通道进行处理的,所以不会出现图像中只有黑白的情况,最多会出现2^3种形式,因为第一个通道是0-255,第二个通道0-255,第三个通道也是0-255,进行这些形式组合,最后得到这样的结构。
灰度图像二值化的结果:下面是一种相对应的方式,分别将高于阈值或者将低于阈值置0,是互补形式。
下图相当于是将小于某个阈值的形式都保留了,图片中整个区域更亮的形式,但是对低于阈值的纹理也进行了保留。
下图两者也是互补形式,当两者叠加在一起时,就可以恢复原先的图像。
下面是对图片进行了自动选取阈值的方式。整个图像选取的最佳阈值 之后,均方差最大,这种方式对于全局梯度是有阴影变化的形式的时候,是没办法选出来一个很好的阈值,能够实现像人眼一样自动区分的功能。如果我们将原始图像分解为多个区域,之后再进行大津法或者三角形法,是否会得到更好的效果?当然。
为了解决上述情况,我们想要在一个比较小的区域内选取合适的阈值,在另外一个小区域内,再选取一个合适阈值,将这张图像分为多个较小的区域,之后进行二值化。opencv也提供了对应的函数。
自适应阈值的图像二值化
adaptive Threshold()
void cv::adaptive Threshold(InputArray src,
OutputArray dst,
double maxValue,
int adaptiveMethod,
int thresholdType,
int blockSize,
double C
)
·src:待二值化的图像,图像只能是CV_8UC1(0~255,灰度图(单通道))数据类型。
·dst:二值化后的图像,与输入图像具有相同的尺寸,数据类型。
·maxValue:二值化的最大值。
·adaptiveMethod:自制应确定阈值的方法,分为均值发ADAPTIVE_THRESH_MEAN_C和高斯法ADAPTIVE_THRESH_GAUSSIAN_C这两种。
·thresholdType:选择图像二值化方法的标志,只能是THRESH_BINARY和THRESH_BINARY_INV。
·blockSize:自适应确定阈值的像素邻域大小,一般为3,5,7的奇数。
·C:从平均值或者加权平均值中减去的常数,可以为正,也可以为负。
示例2:加入了自适应阈值二值化
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv; //opencv的命名空间
using namespace std;
int main()
{
Mat img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/lenac.png");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
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("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/threshold.jpeg", IMREAD_GRAYSCALE);
Mat img_Thr_0, img_Thr_T;
threshold(img_Thr, img_Thr_0, 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_0", img_Thr_0);
imshow("img_Thr_T", img_Thr_T);
//自适应阈值二值化
Mat adaptive_mean, adaptive_gauss;
adaptiveThreshold(img_Thr, adaptive_mean, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 55, 0);
adaptiveThreshold(img_Thr, adaptive_gauss, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 55, 0);
imshow("adaptive_mean", adaptive_mean);
imshow("adaptive_gauss", adaptive_gauss);
waitKey(0);
return 0;
}
结果