opencv threshold_18、OpenCV阈值操作

在图像处理中,经常会在经过多种图像处理算法之后,需要决定最终保留哪部分像素,或者在保留其他像素的情况下忽略低于或高于某个值的像素。OpenCV函数threshold()可以完成这些任务。这就是图像阈值处理。其基本思想是给定一个阈值,然后根据灰度值是否低于或高于阈值,来决定保留哪些像素。也可以把阈值看作是一个非常简单的卷积或滤波操作,它使用1×1内核,然后在该像素上执行卷积操作:

double cv::threshold(

cv::InputArray src, // Input image

cv::OutputArray dst, // Result image

double thresh, // Threshold value

double maxValue, // Max value for upward operations

int thresholdType // Threshold type to use

);

上面是阈值函数的原型。根据像素与阈值之间的关系,目标像素dst可以被设置为0、src或给定的最大值maxValue。

表1。 threshold()的阈值类型选项

阈值类型操作说明
THRESH_BINARYDST = (SRC > thresh) ?
MAXVALUE : 0
THRESH_BINARY_INVDST = (SRC > thresh) ? 0
: MAXVALU
THRESH_TRUNCDST = (SRC > thresh) ?
THRESH : SRC
THRESH_OTSU大律法
THRESH_TOZERODST = (SRC > thresh) ?
SRC : 0
THRESH_TOZERO_INVDST = (SRC > thresh) ? 0
: SRC

看一个简单的例子。 在例1中,将图像的所有三个通道相加,然后进行各种阈值操作。

例1。 使用threshold()来求一个图像三个通道的和。

#include <opencv2/opencv.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
void sum_rgb(const cv::Mat& src, cv::Mat& dst_BINARY,cv::Mat& dst_BINARY_INV,cv::Mat& dst_TRUNC, cv::Mat& dst_OTSU, cv::Mat& dst_TOZERO, cv::Mat& dst_TOZERO_INV)
{
 vector<Mat> planes;
 split(src, planes);
 Mat b = planes[0], g = planes[1], r = planes[2], s;
 addWeighted(r, 1. / 3., g, 1. / 3., 0.0, s);
 addWeighted(s, 1., b, 1. / 3., 0.0, s);
 threshold(s, dst_BINARY, 100, 100, cv::THRESH_BINARY);
 threshold(s, dst_BINARY_INV, 100, 100, cv::THRESH_BINARY_INV);
 threshold(s, dst_TRUNC, 100, 100, cv::THRESH_TRUNC);
 threshold(s, dst_OTSU, 100, 100, cv::THRESH_OTSU);
 threshold(s, dst_TOZERO, 100, 100, cv::THRESH_TOZERO);
 threshold(s, dst_TOZERO_INV, 100, 100, cv::THRESH_TOZERO_INV);
}
int main(int argc, char** argv)
{
 Mat src = imread("E:/1.jpg",1);
 namedWindow("src", 0);
 imshow("src", src);
 Mat dst_BINARY,dst_BINARY_INV, dst_TRUNC, dst_OTSU, dst_TOZERO, dst_TOZERO_INV;
 sum_rgb(src, dst_BINARY, dst_BINARY_INV, dst_TRUNC, dst_OTSU, dst_TOZERO, dst_TOZERO_INV);
 namedWindow("dst_BINARY", 0);
 imshow("dst_BINARY", dst_BINARY);
 namedWindow("dst_BINARY_INV", 0);
 imshow("dst_BINARY_INV", dst_BINARY_INV);
 namedWindow("dst_TRUNC", 0);
 imshow("dst_TRUNC", dst_TRUNC);
 namedWindow("dst_OTSU", 0);
 imshow("dst_OTSU", dst_OTSU);
 namedWindow("dst_TOZERO", 0);
 imshow("dst_TOZERO", dst_TOZERO);
 namedWindow("dst_TOZERO_INV", 0);
 imshow("dst_TOZERO_INV", dst_TOZERO_INV);
 waitKey(0);
 return 0;
}

0e27dc07b3012c0300ecf52e4f5183d8.png
图1 原图

573644ff14d883655b6898a538d24282.png
图2 各种阈值结果图像

这里没有直接将各个通道的值相加,因为高位会溢出。相反,使用三个颜色通道的加权相加; 那么总和被截断,返回值为100。在例1中我们使用浮点型临时图像,也可以用accumulate()将8位整数图像类型累加到浮点图像中,如下所示。

cv::Mat b = planes[0], g = planes[1], r = planes[2];

cv::Mat s = cv::Mat::zeros(b.size(), CV_32F);

cv::accumulate(b, s);

cv::accumulate(g, s);

cv::accumulate(r, s);

可以通过传递THRESH_OTSU作为thresh的值来实现让threshold()确定阈值的最佳值。这就是大律法二值化算法。简言之,Otsu的算法是考虑所有可能的阈值,并计算类方差。事实证明,以这种方式最小化两个类别的方差与最大化两个类别之间的方差相同。 由于需要详尽搜索可能的阈值空间,因此速度有点受影响。

有一种改进的的阈值方法,称为自适应阈值二值化。AdaptiveThreshold()函数可以实现自适应二值化。该算法阈值本身是可变的。

void cv::adaptiveThreshold(

cv::InputArray src, // Input image

cv::OutputArray dst, // Result image

double maxValue, // Max value for upward operations

int adaptiveMethod, // mean or Gaussian

int thresholdType // Threshold type

int blockSize, // Block size

double C // Constant

);

adaptiveThreshold()允许两种不同的自适应阈值类型,具体取决于adaptiveMethod的设置。在这两种情况下,通过计算每个像素位置周围的b×b区域的加权平均值减去常数来设置自适应阈值T,其中b由blockSize给出,常数由C给出。如果该方法设置为ADAPTIVE_THRESH_MEAN_C,则该区域中的所有像素的权重相等。如果它被设置为c ADAPTIVE_THRESH_GAUSSIAN_C,则区域中的像素根据它们距该中心点的距离的高斯函数来加权。参数thresholdType threshold()相同。

自适应阈值在需要相对于一般强度梯度阈值较强的光照或反射梯度时非常有用。该函数仅处理8位单通道或浮点图像,并且要求源图像和目标图像不同。例2比较adaptiveThreshold()和threshold()。图3说明了使用这两种函数处理图像的结果。

例2。 阈值与自适应阈值对比

#include <opencv2/opencv.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
 Mat src = imread("E:/棋盘格.png", 0);
 Mat thrImg, adpImg;
 cv::threshold(src, thrImg,50,255,THRESH_BINARY);
 cv::adaptiveThreshold(src, adpImg,255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY,9,3);
 cv::imshow("src", src);
 cv::imshow("thrImg", thrImg);
 cv::imshow("Adaptive Threshold", adpImg);
 cv::waitKey(0);
 return 0;
}

8078ad5e0de634fd0f544bd4c588280a.png
图3阈值与自适应阈值对比
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值