阈值化和阈值
阈值化和阈值就是对图像上的像素数据进行分类,也就是我们常说的图像分割
Opencv提供了阈值化分割方法,下面来介绍
threshold(Mat src, Mat dst, double thresh, double maxval, int type)
- src:输入图像,一般为8位通道的灰度图像
- dst:输出图像 类型与输入图像相同
- thresh:阈值的值 T
- maxval:最大灰度值,一般为255
- type:阈值化方法必须是下面的方法之一,最常见的是阈值二值化
阈值化的方法
- THRESH_BINARY = 0, 阈值二值化
- THRESH_BINARY_INV = 1, 反阈值二值化
- THRESH_TRUNC = 2, 阈值截断
- THRESH_TOZERO = 3, 阈值取零
- THRESH_TOZERO_INV = 4, 反阈值取零
- THRESH_OTSU = 8,全局阈值
- THRESH_TRIANGLE = 16; 三角阈值
阈值二值化 和 反阈值二值化
阈值二值化就是对灰度图像进行分割
给定一个值 T 如果像素点的值大于 T 则是白色(255)小于 T 则是黑色(0)
下面来看代码展示
Mat m1 = Imgcodecs.imread("C:\\test\\256_256_t1.png" );
HighGui.imshow("原图",m1);
Imgproc.cvtColor(m1,m1,Imgproc.COLOR_BGR2GRAY);//先转换灰度图像
Mat s1 = new Mat();
Imgproc.threshold(m1,s1,180,255,Imgproc.THRESH_BINARY);
Mat s2 = new Mat();
Imgproc.threshold(m1,s2,180,255,Imgproc.THRESH_BINARY_INV);
HighGui.imshow("阈值二值化",s1);
HighGui.imshow("反阈值二值化",s2);
阈值截断、阈值取零和反阈值取零
-
阈值截断
阈值截断就是在阈值的时候,超过阈值T的时候到此截断只保留T像素值 -
阈值取零
在阈值的时候 如果低于阈值T 就取 零(涂黑) -
反阈值取零
在阈值是时候如果高于T 就取零
下面用代码来演示
Mat m1 = Imgcodecs.imread("C:\\test\\256_256_t1.png" );
HighGui.imshow("原图",m1);
Imgproc.cvtColor(m1,m1,Imgproc.COLOR_BGR2GRAY);
Mat s1 = new Mat();
Imgproc.threshold(m1,s1,180,255,Imgproc.THRESH_TRUNC);
Mat s2 = new Mat();
Imgproc.threshold(m1,s2,180,255,Imgproc.THRESH_TOZERO);
Mat s3 = new Mat();
Imgproc.threshold(m1,s3,180,255,Imgproc.THRESH_TOZERO_INV);
HighGui.imshow("阈值截断",s1);
HighGui.imshow("阈值取零",s2);
HighGui.imshow("反阈值取零",s3);
全局阈值
假设阈值值为T 将图片分割成两部分,计算他们的类内方差最终最小类内方差或者最大类间方差对应的灰度值就是计算得到的阈值T
下面用代码来演示
Mat m1 = Imgcodecs.imread("C:\\test\\256_256_t1.png" );
HighGui.imshow("原图",m1);
Imgproc.cvtColor(m1,m1,Imgproc.COLOR_BGR2GRAY);
Mat s1 = new Mat(); //在这里我们添加了 Imgproc.THRESH_OTSU 之后就是全局
Imgproc.threshold(m1,s1,150,255,Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
Mat s2 = new Mat();
Imgproc.threshold(m1,s2,150,255,Imgproc.THRESH_BINARY);//二值化
HighGui.imshow("全局阈值",s1);
HighGui.imshow("阈值二值化",s2);
三角阈值
三角阈值是寻找最大峰值,从最大峰值到垂直45°方向的三角形,计算最大斜边的距离d 对应的直方图灰度即阈值T
下面请看代码实现
Mat m1 = Imgcodecs.imread("C:\\test\\256_256_t1.png" );
HighGui.imshow("原图",m1);
Imgproc.cvtColor(m1,m1,Imgproc.COLOR_BGR2GRAY);
Mat s1 = new Mat();
Imgproc.threshold(m1,s1,180,255,Imgproc.THRESH_BINARY | Imgproc.THRESH_TRIANGLE);
Mat s2 = new Mat();
Imgproc.threshold(m1,s2,0,255,Imgproc.THRESH_BINARY | Imgproc.THRESH_TRIANGLE);
HighGui.imshow("三角1",s1);
HighGui.imshow("三角2",s2);
自适应阈值
自适应阈值计算方法有 C均值 和 C 高斯均值 两种
下面看 一下实现方法
adaptiveThreshold(Mat src, Mat dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
- src:输入图像,一般为8位单通道的灰度图像
- dst:输出图像,类型与输入图像一致
- maxValue:最大灰度阈值 这里一般为255
- thresholdType:自适应阈值方法,C均值或C高斯均值
- blockSize 分块大小 必须为奇数
- C:计算阈值后 +C做阈值化分割(可以叫做微调)
下面请看代码实现
Mat m1 = Imgcodecs.imread("C:\\test\\256_256_t1.png" );
HighGui.imshow("原图",m1);
Imgproc.cvtColor(m1,m1,Imgproc.COLOR_BGR2GRAY);
Mat s1 = new Mat();
Imgproc.adaptiveThreshold(m1,s1,255,Imgproc.ADAPTIVE_THRESH_MEAN_C,Imgproc.THRESH_BINARY,3,0);
Mat s2 = new Mat();
Imgproc.adaptiveThreshold(m1,s2,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY,3,0);
Mat s3 = new Mat();
Imgproc.adaptiveThreshold(m1,s3,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY,9,0);
Mat s4 = new Mat();
Imgproc.adaptiveThreshold(m1,s4,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY,3,15);
HighGui.imshow("C均值",s1);
HighGui.imshow("C高斯",s2);
HighGui.imshow("分块为9",s3);
HighGui.imshow("C + 15",s4);