⾃适应阈值(adaptiveThreshold )分割原理及实现背景介绍及原理
前⾯介绍了OTSU算法和最⼤熵算法,但这两种算法都属于全局阈值法,所以对于某些光照不均的图像,这种全局阈值分割的⽅法会显得苍⽩⽆⼒,如下图:
显然,这样的阈值处理结果不是我们想要的,那么就需要⼀种⽅法来应对这样的情况。
这种办法就是⾃适应阈值法(adaptiveThreshold),它的思想不是计算全局图像的阈值,⽽是根据图像不同区域亮度分布,计算其局部阈值,所以对于图像不同区域,能够⾃适应计算不同的阈值,因此被称为⾃适应阈值法。(其实就是局部阈值法)
如何确定局部阈值呢?可以计算某个邻域(局部)的均值、中值、⾼斯加权平均(⾼斯滤波)来确定阈值。值得说明的是:如果⽤局部的均值作为局部的阈值,就是常说的移动平均法(听起来挺⾼⼤上,其实......逃)。
OpenCV提供的API:
说明下各参数:
InputArray src:源图像
OutputArray dst:输出图像,与源图像⼤⼩⼀致
int adaptiveMethod:在⼀个邻域内计算阈值所采⽤的算法,有两个取值,分别为 ADAPTIVE_THRESH_MEAN_C 和ADAPTIVE_THRESH_GAUSSIAN_C 。
ADAPTIVE_THRESH_MEAN_C的计算⽅法是计算出领域的平均值再减去第七个参数double C的值。
ADAPTIVE_THRESH_GAUSSIAN_C的计算⽅法是计算出领域的⾼斯均值再减去第七个参数double C的值。
int thresholdType:这是阈值类型,只有两个取值,分别为 THRESH_BINARY 和THRESH_BINARY_INV  具体的请看官⽅的说明,这⾥不多做解释。
int blockSize:adaptiveThreshold的计算单位是像素的邻域块,这是局部邻域⼤⼩,3、5、7等。
double C:这个参数实际上是⼀个偏移值调整量,⽤均值和⾼斯计算阈值后,再减或加这个值就是最终阈值。
注:相⽐OpenCV的API,我多⽤了⼀个中值法确定阈值。
基于OpenCV 实现
1void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue,2                      int adaptiveMethod, int thresholdType, int blockSize, double C)
1#include <iostream>
2#include <opencv2/core.hpp>
3#include <opencv2/highgui.hpp>
4#include <opencv2/imgproc.hpp>
5
6enum adaptiveMethod{meanFilter,gaaussianFilter,medianFilter};
7
8void AdaptiveThreshold(cv::Mat& src, cv::Mat& dst, double Maxval, int Subsize, double c, adaptiveMethod method = meanFilter){
9
10 if (src.channels() > 1)
11  cv::cvtColor(src, src, CV_RGB2GRAY);
12
13 cv::Mat smooth;
14 switch (method)
15 {
16 case  meanFilter:
17  cv::blur(src, smooth, cv::Size(Subsize, Subsize));  //均值滤波
18  break;
19 case gaaussianFilter:
20  cv::GaussianBlur(src, smooth, cv::Size(Subsize, Subsize),0,0); //⾼斯滤波
21  break;
22 case medianFilter:
23  cv::medianBlur(src, smooth, Subsize);  //中值滤波
24  break;
25 default:
26  break;
27 }
28
29 smooth = smooth - c;
30
31 //阈值处理
pyTo(dst);
33 for (int r = 0; r < ws;++r){
34  const uchar* srcptr = src.ptr<uchar>(r);
35  const uchar* smoothptr = smooth.ptr<uchar>(r);
36  uchar* dstptr = dst.ptr<uchar>(r);
37  for (int c = 0; c < ls; ++c){
38  if (srcptr[c]>smoothptr[c]){
39    dstptr[c] = Maxval;
40  }
41  else
42    dstptr[c] = 0;
43  }
44 }
45
46}
47
48int main(){
49 cv::Mat src = cv::imread("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Img\\Fig1049(a)(spot_shaded_text_image).tif");
50 if (pty()){
51  return -1;
52 }
53 if (src.channels() > 1)
54  cv::cvtColor(src, src, CV_RGB2GRAY);
55
56 cv::Mat dst, dst2;
57 double t2 = (double)cv::getTickCount();
58 AdaptiveThreshold(src, dst, 255, 21, 10, meanFilter);  //
59 t2 = (double)cv::getTickCount() - t2;
60 double time2 = (t2 *1000.) / ((double)cv::getTickFrequency());
61 std::cout << "my_process=" << time2 << " ms. " << std::endl << std::endl;
62
63
64 cv::adaptiveThreshold(src, dst2, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 21, 10);
65
65
66
67 cv::namedWindow("src", CV_WINDOW_NORMAL);
68 cv::imshow("src", src);
69 cv::namedWindow("dst", CV_WINDOW_NORMAL);
70 cv::imshow("dst", dst);
71 cv::namedWindow("dst2", CV_WINDOW_NORMAL);adaptive
72 cv::imshow("dst2", dst2);
73 //cv::imwrite("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Image Filtering\\MeanFilter\\TXT.jpg",dst);
74 cv::waitKey(0);
75}
效果
这个效果就好很多了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。