自适应阈值分割_opencv自适应阈值分割 - CSDN
精华内容
参与话题
  • 自适应阈值(adaptiveThreshold)分割原理及实现

    万次阅读 热门讨论 2019-05-14 20:27:54
    前面介绍了OTSU算法和最大熵算法,但这两种算法都属于全局阈值法,所以对于某些光照不均的图像,这种全局阈值分割的方法会显得苍白无力,如下图: 显然,这样的阈值处理结果不是我们想要的,那么就需要一种方法...

    背景介绍及原理

    前面介绍了OTSU算法和最大熵算法,但这两种算法都属于全局阈值法,所以对于某些光照不均的图像,这种全局阈值分割的方法会显得苍白无力,如下图:

                      

    显然,这样的阈值处理结果不是我们想要的,那么就需要一种方法来应对这样的情况。

    这种办法就是自适应阈值法(adaptiveThreshold),它的思想不是计算全局图像的阈值,而是根据图像不同区域亮度分布,计算其局部阈值,所以对于图像不同区域,能够自适应计算不同的阈值,因此被称为自适应阈值法。(其实就是局部阈值法)

    如何确定局部阈值呢?可以计算某个邻域(局部)的均值、中值、高斯加权平均(高斯滤波)来确定阈值。值得说明的是:如果用局部的均值作为局部的阈值,就是常说的移动平均法(听起来挺高大上,其实......逃)。

     

    OpenCV提供的API:

    void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue,
                          int adaptiveMethod, int thresholdType, int blockSize, double C)

    说明下各参数:

    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实现

    #include <iostream>
    #include <opencv2/core.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/imgproc.hpp>
    
    enum adaptiveMethod{meanFilter,gaaussianFilter,medianFilter};
    
    void AdaptiveThreshold(cv::Mat& src, cv::Mat& dst, double Maxval, int Subsize, double c, adaptiveMethod method = meanFilter){
    
    	if (src.channels() > 1)
    		cv::cvtColor(src, src, CV_RGB2GRAY);
    
    	cv::Mat smooth;
    	switch (method)
    	{
    	case  meanFilter:
    		cv::blur(src, smooth, cv::Size(Subsize, Subsize));  //均值滤波
    		break;
    	case gaaussianFilter:
    		cv::GaussianBlur(src, smooth, cv::Size(Subsize, Subsize),0,0); //高斯滤波
    		break;
    	case medianFilter:
    		cv::medianBlur(src, smooth, Subsize);   //中值滤波
    		break;
    	default:
    		break;
    	}
    
    	smooth = smooth - c;
    	
    	//阈值处理
    	src.copyTo(dst);
    	for (int r = 0; r < src.rows;++r){
    		const uchar* srcptr = src.ptr<uchar>(r);
    		const uchar* smoothptr = smooth.ptr<uchar>(r);
    		uchar* dstptr = dst.ptr<uchar>(r);
    		for (int c = 0; c < src.cols; ++c){
    			if (srcptr[c]>smoothptr[c]){
    				dstptr[c] = Maxval;
    			}
    			else
    				dstptr[c] = 0;
    		}
    	}
    
    }
    
    int main(){
    	cv::Mat src = cv::imread("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Img\\Fig1049(a)(spot_shaded_text_image).tif");
    	if (src.empty()){
    		return -1;
    	}
    	if (src.channels() > 1)
    		cv::cvtColor(src, src, CV_RGB2GRAY);
    
    	cv::Mat dst, dst2;
    	double t2 = (double)cv::getTickCount();
    	AdaptiveThreshold(src, dst, 255, 21, 10, meanFilter);  //
    	t2 = (double)cv::getTickCount() - t2;
    	double time2 = (t2 *1000.) / ((double)cv::getTickFrequency());
    	std::cout << "my_process=" << time2 << " ms. " << std::endl << std::endl;
    
    
    	cv::adaptiveThreshold(src, dst2, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 21, 10);
    
    
    	cv::namedWindow("src", CV_WINDOW_NORMAL);
    	cv::imshow("src", src);
    	cv::namedWindow("dst", CV_WINDOW_NORMAL);
    	cv::imshow("dst", dst);
    	cv::namedWindow("dst2", CV_WINDOW_NORMAL);
    	cv::imshow("dst2", dst2);
    	//cv::imwrite("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Image Filtering\\MeanFilter\\TXT.jpg",dst);
    	cv::waitKey(0);
    }

    效果

    这个效果就好很多了。

    展开全文
  • 自适应阈值分割

    2020-04-22 14:56:16
    这种方法一般称为全局阈值分割,接下来想介绍的是一种局部阈值分割算法,其原理很简单,通俗地讲就是图片的每个局部都会通过处理得到一个阈值,这个区域就用这个阈值来进行分割,同理,每个区域都有不同的阈值来处理...

    1.原理
           最简单的阈值分割即为手动设置阈值对图像进行二值化,大于设定的阈值像素值设置为255,小于设定阈值则为0.这种方法一般称为全局阈值分割,接下来想介绍的是一种局部阈值分割算法,其原理很简单,通俗地讲就是图片的每个局部都会通过处理得到一个阈值,这个区域就用这个阈值来进行分割,同理,每个区域都有不同的阈值来处理,如何来获取这个阈值就是整个算法的关键。
           这里用opencv的API接口来进行说明,opencv库有接口函数
    void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
    src为输入图像,
    dst为输出图像,
    maxValue为设定的像素最大值,
    adptiveMethod为使用的滤波方法,opencv给出了两种方法,分别为ADAPTIVE_THRESH_MEAN_C 和ADAPTIVE_THRESH_GAUSSIAN_C,
    thresholdType为阈值类型,THRESH_BINARY 和THRESH_BINARY_INV,
    blockSize指的是邻域的大小,也就是通常说的核的大小,一般为奇数,
    C为阈值的偏移量。
            当使用ADAPTIVE_THRESH_MEAN_C方法时阈值为邻域的均值减去C,当使用ADAPTIVE_THRESH_GAUSSIAN_C方法时,阈值为邻域的高斯均值减去C。

    2.代码展示
    自己的自适应阈值分割方法,加入了中值滤波

    #include<opencv2/opencv.hpp>
    #include<iostream>
    
    using namespace std;
    using namespace cv;
    
    enum FliterMethod {
     meanFliter,
     gaaussianFliter,
     medianFliter
    };
    void AdaptiveThreshold(Mat &src, Mat &dst,double Maxval, int Subsize,double C ,FliterMethod method )
    {
     if (src.channels() > 1)
      cvtColor(src,src,CV_RGB2GRAY);
     Mat smooth;
     switch (method)
     {
     case meanFliter:
      blur(src, smooth, Size(Subsize, Subsize));
      break;
     case gaaussianFliter:
      GaussianBlur(src, smooth, Size(Subsize, Subsize), 0, 0);
      break;
     case medianFliter:
      medianBlur(src, smooth, Subsize);
      break;
     default:
      break;
     }
     smooth = smooth - C;
     src.copyTo(dst);
     int r = dst.rows;
     int c = dst.cols;
     for (int i = 0; i < r; i++)
     {
      for (int j = 0; j < c; j++)
      {
       if (dst.at<uchar>(i,j) > smooth.at<uchar>(i,j))
        dst.at<uchar>(i,j) = Maxval;
       else
        dst.at<uchar>(i,j) = 0;
      }
     }
    }
    

    为了看下实时处理的效果,调用了电脑摄像头,代码如下

    int Capture() {
     VideoCapture cap;
     cap.open(0);
     Mat frame;
     //Mat src;
     if (!cap.isOpened())
      return -1;
     while (1)
     {
      cap.read(frame);
      if (frame.empty())
       break;
      //GaussianBlur(frame, src, Size(5, 5), 3, 3);
      Mat src,tmp;
      AdaptiveThreshold(frame, src, 255, 7, 5, meanFliter);
      adaptiveThreshold(frame, tmp, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 7, 10);
      //imshow(" ", frame);
      imshow("AdaptiveThreshold",src);
      imshow("opencv", tmp);
      waitKey(10);
     }
     cap.release();
     destroyAllWindows();
    }

    以下为测试代码

    int main()
    {
     Mat img = imread("C:/Users/94077/Desktop/QQ截图20200307162029.bmp");
     Mat src,tmp;
     AdaptiveThreshold(img, src, 255, 7, 10, gaaussianFliter);
     adaptiveThreshold(img, tmp, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY,7, 10);
     imshow("function", src);
     imshow("opencv", tmp);
     waitKey(0);
     //Capture();
     return 0}
    

    3.结果展示
           这里放几张处理的图片对比一下,发现还是opencv的库函数处理效果好一点,但是针对不同的图片,在某些时候中值滤波的效果可能要比其余两种效果好。
    在这里插入图片描述在这里插入图片描述

    展开全文
  • 阈值分割、自适应阈值分割 一、threshold()函数 1.1 threshold()函数各参数详解 doublethreshold(InputArraysrc,OutputArraydst,doublethresh,doublemaxval,inttype) Ø 第一个参数,InputArray类型的src,输入...

                                                                               阈值分割、自适应阈值分割

    一、threshold()函数

    1.1 threshold()函数各参数详解

    doublethreshold(InputArray src,OutputArray dst,double thresh,double maxval,int type)

    Ø  第一个参数,InputArray类型的src,输入数组,填单通道 , 8或32位浮点类型的Mat即可。

    Ø  第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放输出结果,且和第一个参数中的Mat变量有一样的尺寸和类型。

    Ø  第三个参数,double类型的thresh,阈值的具体值。

    Ø  第四个参数,double类型的maxval,当第五个参数阈值类型type取 THRESH_BINARY 或THRESH_BINARY_INV阈值类型时的最大值.

    Ø  第五个参数,int类型的type,阈值类型。

    第五参数有以下几种类型

    0: THRESH_BINARY  当前点值大于阈值时,取Maxval,也就是第四个参数,下面再不说明,否则设置为0

    1: THRESH_BINARY_INV 当前点值大于阈值时,设置为0,否则设置为Maxval

    2: THRESH_TRUNC 当前点值大于阈值时,设置为阈值,否则不改变

    3: THRESH_TOZERO 当前点值大于阈值时,不改变,否则设置为0

    4:THRESH_TOZERO_INV  当前点值大于阈值时,设置为0,否则不改变

     

    1.2调用示例 

    Mat ScrImage, OutImage, OutImage1, OutImage2, OutImage3;

    ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");

    threshold(ScrImage, OutImage1, 200, 255, CV_THRESH_BINARY);//固定阈值分割

    imshow("【固定阈值处理:二值化】", OutImage1);

     

    二、adapativeThreshold()函数

    2.1 adapativeThreshold()函数各参数详解

    void cvAdaptiveThreshold(constCvArr* src,CvArr* dst,double max_value,int adaptive_method =CV_ADAPTIVE_THRESH_MEAN_C,int threshold_type =CV_THRESH_BINARY,int block_size = 3,double param1= 5);

    Ø  src 输入图像.

    Ø  dst 输出图像.

    Ø  max_value使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV的最大值.

    Ø  adaptive_method自适应阈值算法使用:CV_ADAPTIVE_THRESH_MEAN_C 或 CV_ADAPTIVE_THRESH_GAUSSIAN_C (见讨论).

    Ø  threshold_type

    Ø  取阈值类型:必须是下者之一

    CV_THRESH_BINARY,

    CV_THRESH_BINARY_INV

    block_size用来计算阈值的象素邻域大小: 3, 5, 7,...

    param1与方法有关的参数。对方法CV_ADAPTIVE_THRESH_MEAN_C 和CV_ADAPTIVE_THRESH_GAUSSIAN_C, 它是一个从均值或加权均值提取的常数(见讨论), 尽管它可以是负数。

    2.2调用示例 

    Mat ScrImage, OutImage, OutImage1, OutImage2, OutImage3;

    ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");

    adaptiveThreshold(ScrImage, OutImage2, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 31, 10);//自适应阈值分割

    imshow("【自动阈值处理:二值化】", OutImage2);

     

    三、完整程序

    #include <opencv2/core/core.hpp>

    #include <opencv2/imgproc/imgproc.hpp>

    #include <opencv2/opencv.hpp>

     

    #include <vector>

    #include <cstdio>

     

    using namespacestd;

    using namespacecv;

     

    int main()

    {

       Mat ScrImage, ScrImgaeCopy1, OutImage, OutImage1, OutImage2,OutImage3, OutImage4, OutImage5, OutImage6, OutImage7, OutImage8, OutImage9;

       ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg",0); //读入图像 \\image1.jpg brownbug.jpg whitebug.jpg

       imshow("【原图】", ScrImage);

     

       threshold(ScrImage,OutImage1, 200, 255, CV_THRESH_BINARY);//固定阈值分割

       adaptiveThreshold(ScrImage,OutImage2, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 31, 10);//自适应阈值分割

     

       imshow("【固定阈值处理:二值化】", OutImage1);

       imshow("【自动阈值处理:二值化】", OutImage2);

     

       waitKey(0);

       return NULL;

    }

    展开全文
  • 最大类间方差法是由日本学者大津(Nobuyuki Otsu)于1979年提出的,是一种自适应阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标两部分,或者说,是寻找一个阈值为K,将图像的颜色...

     

    最大类间方差法是由日本学者大津(Nobuyuki Otsu)于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标两部分,或者说,是寻找一个阈值为K,将图像的颜色分为1,2.....K和K+1.....256两部分。

    如何确定这个阈值K?算法分类的原理是让背景和目标之间的类间方差最大,因为背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,错分的可能性越小。下面进行公式推导:

    首先是符号说明:对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均灰度记为μ,类间方差记为g。假设图像的背景较暗,并且图像的大小为M×N,图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1

       

    采用遍历的方法得到寻找到类间方差最大值,对应的阈值,即为所求。

    代码区:

    int myOtsu(const IplImage *frame) //大津法求阈值
    {
    #define GrayScale 256    //frame灰度级
        int width = frame->width;
        int height = frame->height;
        int pixelCount[GrayScale]={0};
        float pixelPro[GrayScale]={0};
        int i, j, pixelSum = width * height, threshold = 0;
        uchar* data = (uchar*)frame->imageData;
    
        //统计每个灰度级中像素的个数
        for(i = 0; i < height; i++)
        {
            for(j = 0;j < width;j++)
            {
                pixelCount[(int)data[i * width + j]]++;
            }
        }
    
        //计算每个灰度级的像素数目占整幅图像的比例
        for(i = 0; i < GrayScale; i++)
        {
            pixelPro[i] = (float)pixelCount[i] / pixelSum;
        }
    
        //遍历灰度级[0,255],寻找合适的threshold
        float w0, w1, u0tmp, u1tmp, u0, u1, deltaTmp, deltaMax = 0;
        for(i = 0; i < GrayScale; i++)
        {
            w0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = 0;
            for(j = 0; j < GrayScale; j++)
            {
                if(j <= i)   //背景部分
                {
                    w0 += pixelPro[j];
                    u0tmp += j * pixelPro[j];
                }
                else   //前景部分
                {
                    w1 += pixelPro[j];
                    u1tmp += j * pixelPro[j];
                }
            }
            u0 = u0tmp / w0;
            u1 = u1tmp / w1;
            deltaTmp = (float)(w0 *w1* pow((u0 - u1), 2)) ;
            if(deltaTmp > deltaMax)
            {
                deltaMax = deltaTmp;
                threshold = i;
            }
        }
        return threshold;
    }

    代码亲测有效,成功实现阈值分割

    代码部分参考:https://blog.csdn.net/daxiamit/article/details/6619075 
    本文针对灰度图像,彩色图像可以参考:https://blog.csdn.net/guoyk1990/article/details/7606032

    展开全文
  • MATLAB自适应阈值分割代码

    热门讨论 2020-07-27 23:31:51
    目前有很多阈值分割的程序,但是大部分需要自己手动设置阈值,这样就导致分割精度不高,此程序可以自动求取最佳阈值,分割效果很好。
  • 自适应阈值分割—大津法(OTSU算法)C++实现

    万次阅读 多人点赞 2018-12-26 16:23:37
    大津法是一种图像灰度自适应阈值分割算法,是1979年由日本学者大津提出,并由他的名字命名的。大津法按照图像上灰度值的分布,将图像分成背景和前景两部分看待,前景就是我们要按照阈值分割出来的部分。背景和前景...
  • python+openCV 自适应阈值分割

    千次阅读 2019-04-26 17:03:16
    因此提出了自适应阈值,即在图像的不同区域采用不同的阈值进行分割。利用函数cv2.adaptiveThreshold()进行分割。 cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C) 参数: ...
  • 局部自适应阈值分割方法

    万次阅读 2018-03-22 09:53:39
    Local_Yanowitz 由于光照的影响,图像的灰度可能是不均匀分布的,此时...Yanowitz提出了一种局部阈值分割方法。结合边缘和灰度信息找到阈值表面(treshhold surface)。在阈值表面上的就是目标。 算法的主要...
  • 固定阈值分割、自适应阈值分割 一、threshold()函数 1.1 threshold()函数各参数详解 doublethreshold(InputArray src, OutputArray dst, double thresh, double maxval, int type) Ø 第一个参数,InputArray类型...
  • 前面博客所讲的简单阈值分割是一种全局分割,但是当一幅图上面的不同部分具有不同的亮度的时候,此时需要采取自适应阈值分割。就是对图像中的各个部分进行分割,即采用邻域分割,在一个邻域范围内进行图像阈值分割。...
  • matlab大律法求自适应阈值

    千次阅读 2012-10-23 21:36:59
    I=imread(''); level=graythresh(I); BW=im2bw(I,level); imshow(BW);
  • 最近写了一个基于直方图的图像阈值分割作业,代码如下: clear all; g=imread('Test_Img_1.jpg');  %g=rgb2gray(I); %thresh(g,99,130,150); %figure(2) %绘制直方图 [cnts, x] = imhist(g, 256); [m, n] =...
  • OpenCV_基于局部自适应阈值的图像二值化

    万次阅读 多人点赞 2013-07-30 22:11:13
    在图像处理应用中二值化操作是一个很常用的处理方式,例如零器件图片的处理、文本图片和验证码图片中字符的提取、车牌识别中的字符分割,以及视频图像中的运动目标检测中的前景分割,等等。 较为常用的图像二值化...
  • 自动全局阈值分割方法: 1
  • OpenCV自适应阈值分割函数:adaptiveThreshold()介绍 【注意】adaptiveThreshold()函数的ThresholdTypes参数只能设置为CV_THRESH_BINARY和CV_THRESH_BINARY_INV。
  • 基于Otsu算法的图像自适应阈值分割

    万次阅读 多人点赞 2020-04-17 03:09:02
    其中,参数level是一个介于0~1之间的值,也就是用于分割图像的阈值。默认情况下,它可取值是0.5。 现在问题来了,有没有一种根据图像自身特点来自适应地选择阈值的方法呢?答案是肯定的!我们今天就来介绍其中...
  • 七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法): https://blog.csdn.net/qq_33485434/article/details/78328681 均值迭代算法: ...Canny边缘检测及自适应门限:(重点) ...
  • http://www.cnblogs.com/skyseraph/archive/2010/12/21/1913058.html
  • opencv局部自适应阈值 二值化
  • 自适应模糊阈值分割

    千次阅读 2017-03-24 11:13:31
    在找到波峰后,下一步就是利用模糊数学的概念找到最佳阈值,进行分割。 什么是模糊数学?  个人理解就是不确定,像天气怎么样?这样的大雨中雨小雨之间的界限,就是不确定的,它和确定数学是相对的。 在2个波峰之间...
1 2 3 4 5 ... 20
收藏数 5,922
精华内容 2,368
关键字:

自适应阈值分割