图像处理过程中经常会遇到这种情况:在已经完成很多处理步骤后,需要做出一个最终的决定,或者将高于或者低于某一个像素值的像素置为零,而其他像素保持不变,其中这个像素值就是我们需要的阈值。
在opencv 中阈值操作可以分为全局阈值和局部阈值
先说全局阈值,用的API是threshold(),它的原理:对于数组中每个值,根据其高于或者低于这个阈值做出相应的处理,给定一个数组和阈值。根据个人喜欢,也可以把阈值化操作理解成一个1*1的卷积核,对每个像素进行一次性的操作。
API:threshold(src,dst,double thresh,double maxValue,int thresholdType)
src:原图,dst:目标图,thresh:阈值,maxValue:最大值。
thresholdType有5种类型,在运用API时,可以直接用数字代替类型,程序中有写:
(1) THRESH_BINAY:二直化阈值操作,当前点大于阈值时,取maxValue,否则为0
(2)THRESH_BINARY_INV:反二直化阈值操作,当前点大于阈值时,取0,否则为maxValue
(3)THRESH_TRUNC:截断 当前点大于阈值时,设为thresh,否则不改变
(4)THRESH_TOZERO:阈值取零 当前点大于阈值时,不变,否则为0
(5)THRESH_TOZERO_INV:反阈值取零 ,当前点大于阈值时,为0,否则不变
举个例子看看结果,程序中用到了窗口滑动函数,可以方便的调节阈值查看效果。
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
//设置全局变量,阈值的初始值,阈值的最大值,阈值类型的初始值,阈值类型的最大值,窗口的标题。
Mat src,dst,gray_src;
int threshold_value = 127;
int threshold_max = 255;
int type_value = 2;
int type_max = 4;
const char* output_title = "binary image";
void Threshold_Demo(int, void*);
int main(int argv, char** argc) {
src = imread("D:\\Pycharm\\picture\\cat.jpg");
if (!src.data) {
printf("can not open the picture!\n");
return -1;
}
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(output_title, src);
//建立一个滑动窗口,两个滑动按钮,其一是阈值的范围,其二是阈值的5种类型。
createTrackbar("Threshold Value", output_title, &threshold_value, threshold_max, Threshold_Demo);
createTrackbar("Type Value", output_title, &type_value, type_max, Threshold_Demo);
waitKey(0);
return 0;
}
//阈值操作函数
//先转换成灰度图像,在阈值操作。下面是各个阈值类型代表的整数类型。但是如果选用自适应阈值
//那么,滑动按钮就不起作用。
//0,THRESH_BINARY
//1,THRESH_BINARY_INV
//2,THRESH_TRUNC
//3,THRESH_TOZREO
//4,THRESH_TOZEARO_INV
void Threshold_Demo(int, void*) {
cvtColor(src, gray_src, CV_BGR2GRAY);
threshold(gray_src, dst,threshold_value,threshold_max, type_value);
//threshold(gray_src, dst, threshold_value, threshold_max, THRESH_OTSU|type_value);
imshow(output_title, dst);
}