图像阈值

阈值是什么?简单点说是把图像分割的标尺,这个标尺是根据什么产生的,阈值产生算法?阈值类型。(Binary segmentation)

相关API

函数原型:

double cv::threshold    (
	InputArray  src,	//输入图像 (多通道或单通道, 8位或32位浮点型).
    OutputArray dst,	//输出图像(大小和类型和输入图像一致)
    double  thresh,	//阈值
    double  maxval,	//阈值所能达到的最大值
    int     type 	//阈值化操作的类型 (see the cv::ThresholdTypes).
)   

下方为各种阈值类型对应的数值(阈值类型本质都是数字,使用数字就能表示各种类型,在后方的代码中会实现)

enum ThresholdTypes {
		THRESH_BINARY = 0,		//大于阈值的部分被置为255,小于部分被置为0   
		THRESH_BINARY_INV = 1,	// 大于阈值部分被置为0,小于部分被置为255   
		THRESH_TRUNC = 2,		//大于阈值部分被置为threshold,小于部分保持原样 
		THRESH_TOZERO = 3,		//小于阈值部分被置为0,大于部分保持不变
		THRESH_TOZERO_INV = 4,	//大于阈值部分被置为0,小于部分保持不变 
		THRESH_MASK = 7,
		THRESH_OTSU = 8,		//图像自适应二值化,一种自动找阈值的算法
		THRESH_TRIANGLE = 16	//一种自动找阈值的算法

注意:
函数使用固定的阈值分别应用于多通道。该函数通常用于从灰度图像中获取二值图像,或者用于去除噪声,即滤除过小或过大值的像素。函数支持的阈值有几种类型。它们由参数type决定。
当时用thresh_otsu或thresh_triangle,函数确定最优阈值使用Otsu(大津法)或三角形算法,而不是指定的阈值。函数返回Otsu或三角形算法计算得到的阈值。目前,使用大津法和三角法,输入必须为单通道8位的图像。

阈值类型

在这里插入图片描述

阈值类型一阈值二值化(threshold binary)

  • 左下方的图表示图像像素点Src(x,y)值分布情况,蓝色水平线表示阈值
    在这里插入图片描述

阈值反二值化(threshold binary Inverted)

  • 左下方的图表示图像像素点Src(x,y)值分布情况,蓝色水平线表示阈值
    在这里插入图片描述

截断 (truncate)

  • 左下方的图表示图像像素点Src(x,y)值分布情况,蓝色水平线表示阈值
    在这里插入图片描述

阈值取零 (threshold to zero)

  • 左下方的图表示图像像素点Src(x,y)值分布情况,蓝色水平线表示阈值
    在这里插入图片描述

阈值反取零 (threshold to zero inverted)

  • 左下方的图表示图像像素点Src(x,y)值分布情况,蓝色水平线表示阈值
    在这里插入图片描述

结果显示

  1. 原始图像
    在这里插入图片描述
  2. 阈值类型为THRESH_BINARY (滑动条的type_value=0)时, 大于阈值的部分被置为255,小于部分被置为0
    在这里插入图片描述
  3. 阈值类型为THRESH_BINARY_INV(滑动条的type_value=1)时,大于阈值部分被置为0,小于部分被置为255
    在这里插入图片描述
  4. 阈值类型为THRESH_TRUNC(滑动条的type_value=2)时,大于阈值部分被置为threshold,小于部分保持原样
    在这里插入图片描述
  5. 阈值类型为THRESH_TOZERO(滑动条的type_value=3)时,小于阈值部分被置为0,大于部分保持不变
    在这里插入图片描述
  6. 阈值类型为THRESH_TOZERO_INV(滑动条的type_value=4)时,大于阈值部分被置为0,小于部分保持不变
    在这里插入图片描述
  7. 经过THRESH_OTSU算法二值化的结果
    在这里插入图片描述

代码实现

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;

//下方定义的全局变量都是为了在回调函数中能够使用
Mat src, gray_src, dst;	
const char* output_title = "binary image";		//定义一个全局变量存储窗口名称(以后改名时改这一处即可)

//下两行定义"Threshold Value:"滑动条(表示阈值的大小)的值
int threshold_value = 127;		//定义一个滑动条初始位置,此处表示当前阈值
int threshold_max = 255;		//定义滑动条的最大位置,此处表示阈值达到的最大值

//下两行定义"Type Value:"滑动条(表示阈值分割的类型)的值
int type_value = 2;				//定义一个滑动条初始位置,2表示为THRESH_TRUNC的类型
int type_max = 4;

void Threshold_Demo(int, void*);	//声明回调函数,使用前5个阈值类型,可针对三通道图像或二值化图像处理
void AutoThreshold_Demo(Mat &src);	//使用THRESH_OTSU或THRESH_TRIANGLE类型的算法,因其只能针对单通道图像,故在其内部进行灰度化
int main() {

	src = imread("G:/OpenCV/opencv笔记所用图片/6.jpg");
	if (!src.data) {
		printf("could not load image...\n");
		getchar();
		return -1;
	}

	namedWindow("input image", CV_WINDOW_AUTOSIZE);		//命名一个窗口,此窗口名为"input image"(可以优化,用变量代替窗口名)
	namedWindow(output_title, CV_WINDOW_AUTOSIZE);		//命名窗口 
	imshow("input image", src);							//将src图像显示在窗口"input image"上

	//对图像进行二值化
	cvtColor(src, src, CV_BGR2GRAY);

	createTrackbar("Threshold Value:", output_title, &threshold_value, threshold_max, Threshold_Demo);
	createTrackbar("Type Value:", output_title, &type_value, type_max, Threshold_Demo);
	Threshold_Demo(0, 0);	//在此调用一次回调函数,为了显示初始化结果

	//AutoThreshold_Demo(src);		//此处使用THRESH_OTSU算法进行二值化(注意执行对象只能是单通道对象)

	waitKey(0);
	return 0;
}

void Threshold_Demo(int , void*){
	
	threshold(src, dst, threshold_value, threshold_max, type_value);	//此为

	/*enum ThresholdTypes {
		THRESH_BINARY = 0,		//大于阈值的部分被置为255,小于部分被置为0   
		THRESH_BINARY_INV = 1,	// 大于阈值部分被置为0,小于部分被置为255   
		THRESH_TRUNC = 2,		//大于阈值部分被置为threshold,小于部分保持原样 
		THRESH_TOZERO = 3,		//小于阈值部分被置为0,大于部分保持不变
		THRESH_TOZERO_INV = 4,	//大于阈值部分被置为0,小于部分保持不变 
		THRESH_MASK = 7,
		THRESH_OTSU = 8,		//图像自适应二值化,一种自动找阈值的算法
		THRESH_TRIANGLE = 16	//一种自动找阈值的算法
		};*/

	imshow(output_title, dst);

}

void AutoThreshold_Demo(Mat &src){
	//如果src为3通道图像,将其灰度化变为单通道
	if (src.channels() == 3)
	{
		printf("请输入单通道图像,否则无法执行THRESH_OTSU算法!\n");
		return ;
	}

	threshold(src, dst, 0, 255, THRESH_OTSU);	//此为THRESH_OTSU算法
	//threshold(src, dst, 0, 255, THRESH_TRIANGLE);

	imshow("THRESH_OTSU", dst);
}
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐