OpenCV中提供了阈值(threshold)函数: threshold 。
这个函数有8种阈值化类型
- CV_THRESH_BINARY =0, /**< value = value > threshold ? max_value : 0 */
- CV_THRESH_BINARY_INV =1, /**< value = value > threshold ? 0 : max_value */
- CV_THRESH_TRUNC =2, /**< value = value > threshold ? threshold : value */
- CV_THRESH_TOZERO =3, /**< value = value > threshold ? value : 0 */
- CV_THRESH_TOZERO_INV =4, /**< value = value > threshold ? 0 : value */
- CV_THRESH_MASK =7,
- CV_THRESH_OTSU =8, 使用Otsu算法选择最优阈值; 将标志与以上CV_THRESH_ *值之一组合
- CV_THRESH_TRIANGLE =16 使用Triangle算法选择最佳阈值
为了解释阈值分割的过程,我们来看一个简单有关像素灰度的图片,该图如下。该图中的蓝色水平线代表着具体的一个阈值。
该阈值化类型如下式所示:
解释:在运用该阈值类型的时候,先要选定一个特定的阈值量,比如:125,这样,新的阈值产生规则可以解释为大于125的像素点的灰度值设定为最大值(如8位灰度值最大为255),灰度值小于125的像素点的灰度值设定为0。
该阈值类型如下式所示:
解释:该阈值化与二进制阈值化相似,先选定一个特定的灰度值作为阈值,不过最后的设定值相反。(在8位灰度图中,例如大于阈值的设定为0,而小于该阈值的设定为255)。
解释:同样首先需要选定一个阈值,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变。(例如:阈值选取为125,那小于125的阈值不改变,大于125的灰度值(230)的像素点就设定为该阈值)。
解释:先选定一个阈值,然后对图像做如下处理:1 像素点的灰度值大于该阈值的不进行任何改变;2 像素点的灰度值小于该阈值的,其灰度值全部变为0。
解释:原理类似于0阈值,但是在对图像做处理的时候相反,即:像素点的灰度值小于该阈值的不进行任何改变,而大于该阈值的部分,其灰度值全部变为0。
threshold(srcImg,0,255,THRESH_BINARY | THRESH_OTSU)
我们自己不一定能够找到一个最好的阈值,去二分化图像,所以我们需要算法自己去寻找一个阈值,而THRESH_OTSU就可以满足这个需求,去找到一个最好的阈值。 注意:它非常适用于图像灰度直方图具有双峰的情况,他会在双峰之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。 因为THRESH_OTSU方法会产生一个阈值,那么函数threshold的的第二个参数(设置阈值)就是0(None)了,并且在threshold的方法参数中还得加上语句THRESH_OTSU。
threshold(gray,0,255,THRESH_BINARY | THRESH_TRIANGLE)
THRESH_OTSU和THRESH_TRIANGLE和前面的说到的二值化方法组合使用,好处是不用自己指定thresh值,系统会进行计算并且作为返回值返回。
区别是: THRESH_OTSU最适用于双波峰 THRESH_TRIANGLE最适用于单个波峰,最开始用于医学分割细胞等。
函数原型:
CV_EXPORTS_W double threshold( InputArray src, OutputArray dst,
double thresh, double maxval, int type );
/** @brief Applies a fixed-level threshold to each array element.对每个数组元素应用一个固定级别的阈值。
The function applies fixed-level thresholding to a multiple-channel array. The function is typically
used to get a bi-level (binary) image out of a grayscale image ( #compare could be also used for
this purpose) or for removing a noise, that is, filtering out pixels with too small or too large
values. There are several types of thresholding supported by the function. They are determined by
type parameter.
该函数对多通道矩阵应用固定级别阈值。该函数通常用于从灰度图像中获得一个二值图像(#compare也可用于此目的)或去除噪声,即过滤出值过小或过大的像素。该函数支持几种类型的阈值设置。它们由类型参数决定。
Also, the special values #THRESH_OTSU or #THRESH_TRIANGLE may be combined with one of the
above values. In these cases, the function determines the optimal threshold value using the Otsu's
or Triangle algorithm and uses it instead of the specified thresh.
另外,特殊值#THRESH OTSU或#THRESH TRIANGLE也可以与上述值中的一个结合使用。在这些情况下,函数使用Otsu的或Triangle算法确定最佳阈值,并使用它而不是指定的阈值。
@note Currently, the Otsu's and Triangle methods are implemented only for 8-bit single-channel images.当前,仅对8位单通道图像实施Otsu和Triangle方法。
@param src input array (multiple-channel, 8-bit or 32-bit floating point).输入数组(多通道,8位或32位浮点)。
@param dst output array of the same size and type and the same number of channels as src.输出数组的大小和类型与src具有相同的通道数。
@param thresh threshold value.阈值。
@param maxval maximum value to use with the #THRESH_BINARY and #THRESH_BINARY_INV thresholding types. #THRESH_BINARY和#THRESH_BINARY_INV阈值使用的最大值类型。
@param type thresholding type (see #ThresholdTypes).阈值类型(请参阅#ThresholdTypes)。
@return the computed threshold value if Otsu's or Triangle methods used .如果使用Otsu或Triangle方法,则返回计算出的阈值。
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int threshold_value = 0;
int threshold_type = 3;
int const max_value = 255;
int const max_type = 4;
int const max_BINARY_value = 255;
Mat src, src_gray, dst;
const char* window_name = "Threshold Demo";
const char* trackbar_type = "Type: \n 0: Binary \n 1: Binary Inverted \n 2: Truncate \n 3: To Zero \n 4: To Zero Inverted";
const char* trackbar_value = "Value";
void Threshold_Demo(int, void*);
int main(int argc, char** argv)
{
String imageName("2.jpg"); // by default
if (argc > 1)
{
imageName = argv[1];
}
src = imread(imageName, IMREAD_COLOR); // Load an image
if (src.empty())
{
return -1;
}
cvtColor(src, src_gray, COLOR_BGR2GRAY); // Convert the image to Gray
namedWindow(window_name, WINDOW_AUTOSIZE); // Create a window to display results
createTrackbar(trackbar_type,
window_name, &threshold_type,
max_type, Threshold_Demo); // Create Trackbar to choose type of Threshold
createTrackbar(trackbar_value,
window_name, &threshold_value,
max_value, Threshold_Demo); // Create Trackbar to choose Threshold value
Threshold_Demo(0, 0); // Call the function to initialize
for (;;)
{
char c = (char)waitKey(20);
if (c == 27)
{
break;
}
}
}
void Threshold_Demo(int, void*)
{
/* 0: Binary 二进制阈值
1: Binary Inverted 反二进制阈值
2: Threshold Truncated 截断阈值
3: Threshold to Zero 0阈值
4: Threshold to Zero Inverted 反0阈值
*/
threshold(src_gray, dst, threshold_value, max_BINARY_value, threshold_type);
imshow(window_name, dst);
}
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
using namespace cv;
using namespace std;
void main()
{
//定义变量
Mat img,result1,result2;
//设定阈值
int threshval = 170;
//载入图片
img = imread("4.jpg", 0);
// 方法一,使用阈值操作转为二值图
//使用二进制阈值化THRESH_BINARY,像素值大于阈值threshval的变为255,小于threshval的变为0
threshold(img, result1, 0, 255, THRESH_OTSU);
//方法二,如果阈值小于100,那么中间为真,即像素值小于160的为1,大于160的为0;如果阈值大于100,那么右边为真,即像素值大于160的为1,小于160的为0.
result2 = threshval < 100 ? (img < 160) : (img > 160);//二值化
//显示原图
namedWindow("Image");
imshow("Image", img);
// 显示二值图
namedWindow("使用阈值操作二值化后的图像");
imshow("使用阈值操作二值化后的图像", result1);
namedWindow("二值化后的图像");
imshow("二值化后的图像", result2);
waitKey(0);
}