OpenCV学习笔记(十一):阈值化:threshold(),adaptivethreshold()
一、定义:
1)固定阈值操作
double threshold(
InputArray src, // 输入图像,单通道
OutputArray dst, // 输出图像
double thresh, // 阈值的具体值
double maxval, // 最大值,生成二值图时用到
int type); // 阈值类型// 常用的两种阈值化类型// THRESH_BINARY = 0, 阈值化处理生成二值图像// THRESH_BINARY_INV = 1, 阈值化处理并反转生成二值图
==阈值类型:==
0 = THRESH_BINARY二进制阈值化:
将灰度值大于thresh的设置为maxval,不大于thresh设置为0。1 = THRESH_BINARY_INV反二进制阈值化:
将灰度值大于thresh的设置为0,不大于thresh设置为maxval。2 = THRESH_TRUNC截断阈值化:
将灰度值大于thresh的设置为threshold,不大于thresh的灰度值不变。3 = THRESH_TOZERO阈值化为0:
将灰度值大于thresh的不变,超过阈值置为0。4 = THRESH_TOZERO_INV反阈值化为0:
将灰度值大于thresh的不变,低于阈值置为0。THRESH_MASKTHRESH_OTSU 使用Otsu算法选择最优阈值,使这个阈值可以将前景色和背景色尽可能分开。 THRESH_TRIANGLE 使用三角形算法选择最优阈值
2)自适应阈值化操作
void adaptiveThreshold(
InoutArray src, // 源图像数组
OutputArray dst, // 输出图像组
double maxValue, // 最大值,生成二值图时用到
int adaptiveMethod, // 自适应阈值算法选择 ADAPTIVE_THRESH_MEAN_C或ADAPTIVE_THRESH_GAUSSIAN_C;
int thresholdType, // 阈值类型THRESH_BINARY或THRESH_BINARY_INV
int blockSize, // 邻域块大小,用来计算区域阈值,一般选择3、5、7……;
double C // 它是一个从均匀或加权均值提取的常数,可以是负数
)==自适应阈值算法==
ADAPTIVE_THRESH_MEAN_C 的计算方法是
计算出邻域的平均值再减去第七个参数double C的值ADAPTIVE_THRESH_GAUSSIAN_C 的计算方法是
计算出邻域的高斯均匀值再减去第七个参数double C的值
二、固定阈值threshold() 代码示例:
1)主函数
#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;int g_nThresholdValue1 = 124,g_nThresholdValue2=175;
int g_nThresholdType = 0; // 阈值类型 标识
Mat g_srcImage,g_grayImage,g_dstImage,g_dstImage1,g_dstImage2;int main()
{// 显示欢迎和帮助文字ShowHelpText( );// 1、读入源图片g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/pellets.png");if(!g_srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }imshow("原始图",g_srcImage);// 2、存留一份原图的灰度图cvtColor( g_srcImage, g_grayImage, COLOR_RGB2GRAY );// 3、创建窗口并显示原始图namedWindow( "【程序窗口】", WINDOW_AUTOSIZE );// 4、创建滑动条来控制阈值createTrackbar( "模式", "【程序窗口】", &g_nThresholdType,4, on_Threshold );createTrackbar( "min阈值1","【程序窗口】", &g_nThresholdValue1,255, on_Threshold );createTrackbar( "max阈值2","【程序窗口】", &g_nThresholdValue2,255, on_Threshold );// 5、初始化自定义的阈值回调函数on_Threshold( 0, 0 );// 6、轮询等待用户按键,如果ESC键按下则退出程序while(1){int key;key = waitKey( 20 );if( (char)key == 27 ){ break; }}return 0;
}
2)获取区间像素点总数:
int getWhitePixel(Mat& img)
{int area=0;for(int i=0 ; i<img.rows ; i++)for(int j=0 ; j<img.cols ; j++)if(img.at<uchar>(i,j)==255)area ++;return area;// int area=0;
// int rowNumber = img.rows; //行数
// int colNumber = img.cols*img.channels(); //列数 x 通道数=每一行元素的个数
// //双重循环,遍历所有的像素值
// for (int i = 0; i < rowNumber; i++) //行循环
// {
// uchar *data = img.ptr<uchar>(i); //获取第i行的首地址
// for (int j = 0; j < colNumber; j++)
// if(data[j] ==255)
// area ++;
// }
// return area;
}
3)区间阈值实现函数:
void on_Threshold( int, void* )
{//调用阈值函数//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 */threshold(g_grayImage,g_dstImage1,g_nThresholdValue1,255,g_nThresholdType); // CV_THRESH_BINARYimshow( "threshold1", g_dstImage1 );threshold(g_grayImage,g_dstImage2,g_nThresholdValue2,255,g_nThresholdType);imshow( "threshold2", g_dstImage2 );// 两图相减 g_dstImage1-g_dstImage2=g_dstImageaddWeighted(g_dstImage1,1.0,g_dstImage2,-1,0,g_dstImage);// 显示区间像素点数int area = getWhitePixel(g_dstImage);printf("\n 区间面积area =%d pixel",area);//更新效果图imshow( "【程序窗口】", g_dstImage );
}
static void ShowHelpText()
{//输出一些帮助信息printf( "\n\t欢迎来到【基本阈值操作】示例程序~\n\n");printf( "\n\t按键操作说明: \n\n""\t\t键盘按键【ESC】- 退出程序\n""\t\t滚动条模式0- 二进制阈值\n""\t\t滚动条模式1- 反二进制阈值\n""\t\t滚动条模式2- 截断阈值\n""\t\t滚动条模式3- 反阈值化为0\n""\t\t滚动条模式4- 阈值化为0\n" );
}
结果:
在这里插入图片描述
Halcon对比:
二、固定阈值threshold() 代码示例:
1)主函数
#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;Mat g_srcImage, g_grayImage,g_matAdaptive;
int g_nadaptiveMethod = ADAPTIVE_THRESH_MEAN_C;
int g_C = 5;
int g_blockSize=1;int main()
{// 1、读入源图片g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/pellets.png");if(!g_srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }imshow("原始图",g_srcImage);// 2、存留一份原图的灰度图cvtColor( g_srcImage, g_grayImage, COLOR_RGB2GRAY );// 3、创建窗口并显示原始图namedWindow( "【自适应阈值分割】" , WINDOW_AUTOSIZE );// 4、创建滑动条来控制阈值createTrackbar( "阈值算法", "【自适应阈值分割】" , &g_nadaptiveMethod,1, on_Threshold );createTrackbar( "领域尺寸","【自适应阈值分割】" , &g_blockSize,9, on_Threshold );createTrackbar( "常数 C","【自适应阈值分割】" , &g_C,255, on_Threshold );// 5、初始化自定义的阈值回调函数on_Threshold( 0, 0 );// 6、轮询等待用户按键,如果ESC键按下则退出程序while(1){int key;key = waitKey( 20 );if( (char)key == 27 ){ break; }}return 0;
}
void on_Threshold( int, void* )
{ // 自适应阈值分割adaptiveThreshold(g_grayImage, g_matAdaptive, 255, g_nadaptiveMethod, THRESH_BINARY_INV, 2*g_blockSize+1, g_C);// 更新效果图imshow( "【自适应阈值分割】" , g_matAdaptive );
}
结果: