【OpenCV3】阈值化操作——cv::threshold()与cv::adaptiveThreshold()详解
2017-03-29 09:21
405 查看
阈值化操作在图像处理中是一种常用的算法,比如图像的二值化就是一种最常见的一种阈值化操作。opencv2和opencv3中提供了直接阈值化操作cv::threshold()和自适应阈值化操作cv::adaptiveThreshold()两种阈值化操作接口,这里将对这两个接口进行介绍和对比。
1、直接阈值化——cv::threshold()
阈值化操作的基本思想是,给定一个输入数组和一个阈值,数组中的每个元素将根据其与阈值之间的大小发生相应的改变。opencv3中支持这一操作的接口是cv::threshold(),具体调用方法如下:
如下表所示,每一种阈值化操作类型,对应着一种源图像上每一个像素点与阈值thresh之间比较操作。根据源图像像素和阈值之间的大小关系,目标像素可能被置为0、原像素值、或者设定的最大值maxValue。
下图将会帮助大家理解不同的阈值化类型所表示的确切含义。
实用上面的代码进行阈值化处理,原图和五种不同方式阈值化的结果分别如下:
另外,在opencv3中cv::threshold()函数还支持一种特殊的阈值化操作方式,即Otsu算法。该算法的主要思想是,在进行阈值化时,考虑所有可能的阈值,分别计算低于阈值和高于阈值像素的方差,使下式最小化的值作为阈值:
其中,两类像素方差的权值由两类像素的个数决定。这种阈值化的结果相对来说比较理想,可以避免寻找合适阈值的操作,但是这种方式运算量较大,费时。处理的结果如下:
但是,直接阈值化操作是一种一刀切的方式,对于亮度分布差异较大的图像,常常无法找到一个合适的阈值。如下所示,对棋盘格进行二值化操作,由于图像右上角区域和图像下部的亮度差异较为大,无法找到一个合适的阈值,将棋盘上的所有棋盘格给区分开来。
针对于上述情况,我们需要一种改进的阈值化算法,即自适应阈值化。
2、自适应阈值化——cv::adaptiveThreshold()
自适应阈值化能够根据图像不同区域亮度分布的,改变阈值,具体调用方法如下:
cv::adaptiveThreshold()支持两种自适应方法,即cv::ADAPTIVE_THRESH_MEAN_C(平均)和cv::ADAPTIVE_THRESH_GAUSSIAN_C(高斯)。在两种情况下,自适应阈值T(x, y)。通过计算每个像素周围bxb大小像素块的加权均值并减去常量C得到。其中,b由blockSize给出,大小必须为奇数;如果使用平均的方法,则所有像素周围的权值相同;如果使用高斯的方法,则(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到。
测试代码如下:
我们分别使用了平均和高斯两种自适应方法,结果如下:
2017.03.29
1、直接阈值化——cv::threshold()
阈值化操作的基本思想是,给定一个输入数组和一个阈值,数组中的每个元素将根据其与阈值之间的大小发生相应的改变。opencv3中支持这一操作的接口是cv::threshold(),具体调用方法如下:
double cv::threshold( cv::InputArray src, // 输入图像 cv::OutputArray dst, // 输出图像 double thresh, // 阈值 double maxValue, // 向上最大值 int thresholdType // 阈值化操作的类型 );
如下表所示,每一种阈值化操作类型,对应着一种源图像上每一个像素点与阈值thresh之间比较操作。根据源图像像素和阈值之间的大小关系,目标像素可能被置为0、原像素值、或者设定的最大值maxValue。
下图将会帮助大家理解不同的阈值化类型所表示的确切含义。
void test_threshold() { cv::Mat src = cv::imread("lena.jpg", cv::IMREAD_GRAYSCALE); cv::Mat dst; double thresh = 100; int maxVal = 255; cv::threshold(src, dst, thresh, maxVal, cv::THRESH_BINARY); cv::imshow("threshold", dst); cv::waitKey(0); return; }
实用上面的代码进行阈值化处理,原图和五种不同方式阈值化的结果分别如下:
另外,在opencv3中cv::threshold()函数还支持一种特殊的阈值化操作方式,即Otsu算法。该算法的主要思想是,在进行阈值化时,考虑所有可能的阈值,分别计算低于阈值和高于阈值像素的方差,使下式最小化的值作为阈值:
其中,两类像素方差的权值由两类像素的个数决定。这种阈值化的结果相对来说比较理想,可以避免寻找合适阈值的操作,但是这种方式运算量较大,费时。处理的结果如下:
但是,直接阈值化操作是一种一刀切的方式,对于亮度分布差异较大的图像,常常无法找到一个合适的阈值。如下所示,对棋盘格进行二值化操作,由于图像右上角区域和图像下部的亮度差异较为大,无法找到一个合适的阈值,将棋盘上的所有棋盘格给区分开来。
针对于上述情况,我们需要一种改进的阈值化算法,即自适应阈值化。
2、自适应阈值化——cv::adaptiveThreshold()
自适应阈值化能够根据图像不同区域亮度分布的,改变阈值,具体调用方法如下:
void cv::adaptiveThreshold( cv::InputArray src, // 输入图像 cv::OutputArray dst, // 输出图像 double maxValue, // 向上最大值 int adaptiveMethod, // 自适应方法,平均或高斯 int thresholdType // 阈值化类型 int blockSize, // 块大小 double C // 常量 );
cv::adaptiveThreshold()支持两种自适应方法,即cv::ADAPTIVE_THRESH_MEAN_C(平均)和cv::ADAPTIVE_THRESH_GAUSSIAN_C(高斯)。在两种情况下,自适应阈值T(x, y)。通过计算每个像素周围bxb大小像素块的加权均值并减去常量C得到。其中,b由blockSize给出,大小必须为奇数;如果使用平均的方法,则所有像素周围的权值相同;如果使用高斯的方法,则(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到。
测试代码如下:
void test_adaptive_threshold() { cv::Mat src = cv::imread("chessboard.png", cv::IMREAD_GRAYSCALE); cv::Mat dst; int maxVal = 255; int blockSize = 41; double C = 0; cv::adaptiveThreshold(src, dst, maxVal, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, blockSize, C); cv::imshow("threshold", dst); cv::waitKey(0); return; }
我们分别使用了平均和高斯两种自适应方法,结果如下:
2017.03.29
相关文章推荐
- Learning OpenCV cvAdaptiveThreshold 自适应阈值
- Learning OpenCV cvAdaptiveThreshold 自适应阈值
- OpenCV 阈值化操作cvThreshold 和 自适应阈值cvAdaptiveThreshold操作
- opencv2函数学习之threshold:实现图像阈值化 在opencv2中,threshold函数可以进行阈值化操作。 double threshold( const Mat& src, M
- cvAdaptiveThreshold用法(opencv参考手册)
- OpenCV Tutorial: 自適應閾值(threshold、CV_THRESH_OTSU)
- 自适应阈值 cvAdaptiveThreshold
- OpenCV3_C++_Threshold()阈值化处理 实例
- 利用OpenCV的threshold函数实现双阈值法二值化操作的源码!
- Opencv固定阀值操作-Threshold函数
- 【OpenCV3】彩色映射——cv::applyColorMap()与cv::LUT()详解
- opencv源码解析之(7):CvAdaptiveSkinDetectorl类
- 【OpenCV3】角点检测——cv::goodFeaturesToTrack()与cv::cornerSubPix()详解
- Opencv YAML和XML格式文件操作详解
- 【OpenCV3】cv::Mat块访问与操作(ROI区域的选取)
- opencv3_java 图像直接阈值化操作 AdaptiveThreshold
- 【OpenCV3图像处理】阈值化操作得到二值图像(附Otsu算法和三角法原理与源码)
- 【OpenCV3】透视变换——cv::getPerspectiveTransform()与cv::warpPerspective()详解
- OpenCV :: adaptiveThreshold()
- cvAdaptiveThreshold函数能解决图像分割中的什么问题