精华内容
下载资源
问答
  • opencv大津阈值分割

    2012-08-08 22:14:48
    opencv大津阈值分割 很不错的算法
  • 大津阈值Opencv实现

    2020-07-11 23:35:55
    } 使用大津算法实现分割 Mat Binarize_Otsu(Mat gray) { int width = gray.cols; int height = gray.rows; // determine threshold double w0 = 0, w1 = 0; double m0 = 0, m1 = 0; double max_sb = 0, sb = ...

    问题一 灰度化

    在这里插入图片描述

    Mat BGR2GRAY(Mat img) {
    	// get height and width
    	int width = img.cols;
    	int height = img.rows;
    
    	// prepare output
    	Mat out = Mat::zeros(height, width, CV_8UC1);
    
    	// each y, x
    	for (int y = 0; y < height; y++) {
    		for (int x = 0; x < width; x++) {
    			// BGR -> Gray
    			out.at<uchar>(y, x) = 0.2126 * (float)img.at<Vec3b>(y, x)[2] \
    				+ 0.7152 * (float)img.at<Vec3b>(y, x)[1] \
    				+ 0.0722 * (float)img.at<Vec3b>(y, x)[0];
    		}
    	}
    
    	return out;
    }
    

    使用大津算法实现分割

    在这里插入图片描述

    Mat Binarize_Otsu(Mat gray) {
    	int width = gray.cols;
    	int height = gray.rows;
    
    	// determine threshold
    	double w0 = 0, w1 = 0;
    	double m0 = 0, m1 = 0;
    	double max_sb = 0, sb = 0;
    	int th = 0;
    	int val;
    
    	// Get threshold
    	for (int t = 0; t < 156; t++) {
    		w0 = 0;
    		w1 = 0;
    		m0 = 0;
    		m1 = 0;
    		for (int y = 0; y < height; y++) {
    			for (int x = 0; x < width; x++) {
    				val = (int)(gray.at<uchar>(y, x));
    
    				if (val < t) {
    					w0++;
    					m0 += val;
    				}
    				else {
    					w1++;
    					m1 += val;
    				}
    			}
    		}
    
    		m0 /= w0;
    		m1 /= w1;
    		w0 /= (height * width);
    		w1 /= (height * width);
    		sb = w0 * w1 * pow((m0 - m1), 2);
    
    		if (sb > max_sb) {
    			max_sb = sb;
    			th = t;
    		}
    	}
    
    	std::cout << "threshold:" << th << std::endl;
    
    	// prepare output
    	Mat out = Mat::zeros(height, width, CV_8UC1);
    
    	// each y, x
    	for (int y = 0; y < height; y++) {
    		for (int x = 0; x < width; x++) {
    			// Binarize
    			if (gray.at<uchar>(y, x) > th) {
    				out.at<uchar>(y, x) = 255;
    			}
    			else {
    				out.at<uchar>(y, x) = 0;
    			}
    
    		}
    	}
    
    	return out;
    }
    

    成果展示
    在这里插入图片描述
    在这里插入图片描述
    平均池化:

    Mat average_pooling(Mat img) {
    	int height = img.rows;
    	int width = img.cols;
    	int channel = img.channels();
    
    	// prepare output
    	Mat out = Mat::zeros(height, width, CV_8UC3);
    
    	int r = 8;
    	double v = 0;
    
    	for (int y = 0; y < height; y += r) {
    		for (int x = 0; x < width; x += r) {
    			for (int c = 0; c < channel; c++) {
    				v = 0;
    				for (int dy = 0; dy < r; dy++) {
    					for (int dx = 0; dx < r; dx++) {
    						v += (double)img.at<Vec3b>(y + dy, x + dx)[c];
    					}
    				}
    				v /= (r * r);
    				for (int dy = 0; dy < r; dy++) {
    					for (int dx = 0; dx < r; dx++) {
    						out.at<Vec3b>(y + dy, x + dx)[c] = (uchar)v;
    					}
    				}
    			}
    		}
    	}
    	return out;
    }
    

    在这里插入图片描述

    展开全文
  • OpenCV与图像处理学习七——传统图像分割之阈值法(固定阈值、自适应阈值、大津阈值)一、固定阈值图像分割1.1 直方图双峰法1.2 OpenCV中的固定阈值分割二、自适应阈值图像分割三、迭代法阈值分割四、Otsu大津阈值法...

    前面的笔记介绍了一些OpenCV基本的图像处理,后面将学习使用OpenCV的传统的图像分割方法,这次笔记的内容是阈值法进行图像分割。

    图像分割是指将图像分成若干具有相似性质的区域的过程,主要有基于阈值、基于区域、基于边缘、基于聚类、基于图论和基于深度学习的图像分割方法等。图像分割分为语义分割实例分割。下图是一个实例分割的例子,与语义分割不同的地方在于,它能将同类别的物体的每个个体都区分开,如下图中每个人的轮廓都被分割开:

    在这里插入图片描述
    分割的原则就是使划分后的子图在内部保持相似度最大,而子图之间的相似度最小,将G = (V, E) 分成两个子集A,B,使得:
    在这里插入图片描述
    在这里插入图片描述

    一、固定阈值图像分割

    即设定一个固定的阈值,整张图片的每个像素的像素值都与该值进行比较,若小于该阈值则将像素值改为一个固定的值(常用0),若大于该阈值则将像素值改为另一个固定的值(常用255),则可以将图像进行二值分割,得到一张二值图。

    1.1 直方图双峰法

    六十年代中期提出的直方图双峰法(也称mode法)是典型的全局单阈值分割方法。
    在这里插入图片描述
    基本思想:假设图像中有明显的目标和背景,则其灰度直方图呈双峰分布,当灰度级直方图具有双峰特性时选取两峰之间的谷对应的灰度级作为阈值,大于阈值的作为前景,小于的作为背景。

    缺点:对图像的要求太高,很多图像的直方图并不满足双峰的分布。

    1.2 OpenCV中的固定阈值分割

    在OpenCV中的函数:

    retval, dst	= cv2.threshold( src, thresh, maxval, type[, dst] )
    

    参数:

    1. src:输入图像,单通道或四通道图像。
    2. thresh:设定的固定阈值。
    3. maxval:当type参数设置为THRESH_BINARY时,表示像素值大于阈值时设置的值,或设置为THRESH_BINARY_INV时,表示像素值小于阈值时设置的值。
    4. type:阈值类型,如下图所示,前五种类型是基本类型,最后两种(大津阈值和三角形阈值)与前面的基本类型结合可以实现特殊的阈值分割:在这里插入图片描述

    这里也需要注意一下这个函数的输出:

    1. retval:第一个参数返回的是阈值,在使用五种基本类型时就等于你设置的阈值,而在使用大津阈值法和三角形阈值法时将会得到它计算出来的阈值,一般用的不多。
    2. dst:第二个参数返回的才是分割之后的图像。

    下面看几个例子:

    # 加载opencv和matplotlib
    import cv2
    import matplotlib.pyplot as plt
    
    # 灰度图读入
    img = cv2.imread('./image/thresh.png', 0)
    threshold = 127
    # 阈值分割
    ret, th = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY)
    print(ret)
    
    cv2.imshow('Original', img)
    cv2.imshow('thresh', th)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    结果如下:
    在这里插入图片描述
    返回的第一个参数就是设置的阈值:

    127.0
    

    即像素值低于127的都被赋予0,高于的都被赋予255,得到一张二值化的图像。

    再来看一下五种基本的阈值分割方法的区别

    # 导入第三方包
    import cv2
    from matplotlib import pyplot as plt
    # opencv读取图像
    img = cv2.imread('./image/person.png',0)
    # 5种阈值法图像分割
    ret1, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    ret2, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
    ret3, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
    ret4, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
    ret5, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
    
    images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
    # 使用for循环进行遍历,matplotlib进行显示
    for i in range(6):
        plt.subplot(2, 3, i+1)
        plt.imshow(images[i], cmap='gray')
        plt.xticks([])
        plt.yticks([])
    
    plt.suptitle('fixed threshold')
    plt.show()
    

    结果为:
    在这里插入图片描述
    注意:除了前两种方法是二值化图像,后三种并不是,因为它们会保留一部分的原像素值。

    如果这个图不够直观,将输入图像换成上一个例子里的渐变灰度图,结果如下:
    在这里插入图片描述

    二、自动阈值图像分割

    2.1 自适应阈值法

    很明显,设置一个固定阈值对全局像素进行分割是不合理的,如果这张图片的光照角度不好,一边比较亮一边比较暗,但是我们想分割图里的细节,只用一个固定阈值的话很可能会出现下面的结果:
    在这里插入图片描述
    而自适应阈值分割则将图像分成很多个小块(region),对每个小块单独计算其阈值,然后用这个计算得到的阈值对该小块进行分割,这样的好处是,即使受到光照影响,某一块较暗或较亮,但是可以单独计算这一块的合理阈值来进行分割而不用使用全局的固定阈值,换句话说,亮的小块对应的阈值较大,暗的小块对应的阈值较小,从而可以达到很好的分割效果。

    函数:

    dst	= cv2.adaptiveThreshold( src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]	)
    

    参数:

    1. src:输入图像,只能是单通道灰度图。
    2. maxValue:最大阈值,即小块计算的阈值不能超过这个值,一般设置为255.
    3. adaptiveMethod:计算小块阈值的方法,包括cv2.ADAPTIVE_THRESH_MEAN_Ccv.ADAPTIVE_THRESH_GAUSSIAN_C,即求小块内的均值或高斯加权求和:在这里插入图片描述
    4. thresholdType:阈值方法,这里只能是THRESH_BINARYTHRESH_BINARY_INV,即在这里插入图片描述
    5. blockSize:小块的尺寸,如11就是11×11。
    6. C:最终阈值等于小区域计算出的阈值再减去这个常数。

    看一下刚刚用固定阈值分割效果很差的那个图用自适应阈值来分割的效果:

    # 自适应阈值与固定阈值对比
    import cv2
    import matplotlib.pyplot as plt
    img = cv2.imread('./image/paper2.png', 0)
    
    # 固定阈值
    ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    # 自适应阈值
    th2 = cv2.adaptiveThreshold(
        img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 4)
    th3 = cv2.adaptiveThreshold(
        img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 4)
    # 全局阈值,均值自适应,高斯加权自适应对比
    titles = ['Original', 'Global(v = 127)', 'Adaptive Mean', 'Adaptive Gaussian']
    images = [img, th1, th2, th3]
    for i in range(4):
        plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
        plt.title(titles[i], fontsize=8)
        plt.xticks([]), plt.yticks([])
    plt.show()
    

    在这里插入图片描述
    可以看出效果还是很好的,相比之下,高斯方法的自适应阈值能获得更好的效果,其噪点更少。

    2.2 迭代法阈值分割

    步骤:

    1. 求出图像的最大灰度值和最小灰度值,分别记为Zmax和Zmin,另初始阈值为T0 = (Zmax + Zmin) / 2。
    2. 根据阈值Tk将图像分割为前景和背景,分别求出两者的平均灰度值Zo和Zb。
    3. 求出新的阈值Tk+1 = (Zo + Zb) / 2。
    4. 若Tk == Tk+1,则即为所求的阈值,否则转到步骤2继续迭代。
    5. 使用计算后的阈值进行阈值分割。

    其实迭代法就是将固定阈值分割里手动给定阈值改为了迭代计算阈值,可以适用的范围更多一些,但是本质还是固定阈值变换

    看个例子:

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.cm as cm
    
    def best_thresh(img):
        # step 1: 设置初始阈值
        img_array = np.array(img).astype(np.float32)    # 转化成数组
        I = img_array
        zmax = np.max(I)
        zmin = np.min(I)
        tk = (zmax+zmin)/2
        # step 2: 根据阈值将图像进行分割为前景和背景,分别求出两者的平均灰度zo和zb
        b = 1
        m, n = I.shape;
        while b == 0:
            ifg = 0
            ibg = 0
            fnum = 0
            bnum = 0
            for i in range(1, m):
                 for j in range(1, n):
                    tmp = I(i, j)
                    if tmp >= tk:
                        ifg = ifg + 1
                        fnum = fnum + int(tmp)  # 前景像素的个数以及像素值的总和
                    else:
                        ibg = ibg+1
                        bnum = bnum + int(tmp)  # 背景像素的个数以及像素值的总和
            # step 3: 计算前景和背景的新平均值
            zo = int(fnum / ifg)
            zb = int(bnum / ibg)
            # step 4: 比较tk是否等于新平均值
            if tk == int((zo+zb) / 2):
                b = 0
            else:
                tk = int((zo+zb)/2)
        # step 5: 返回的就是迭代计算后的阈值
        return tk
    
    img = cv2.imread("./image/bird.png")
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    img = cv2.resize(gray, (200, 200))  # 大小
    yvzhi = best_thresh(img)
    ret1, th1 = cv2.threshold(img, yvzhi, 255, cv2.THRESH_BINARY)
    print(ret1)
    plt.imshow(th1, cmap=cm.gray)
    plt.show()
    

    结果为:
    在这里插入图片描述

    2.3 Otsu大津阈值法

    大津法:也叫最大类间方差法,1979年日本学者大津提出,是一种基于全局阈值的自适应方法。

    图像分为前景和背景,当取最佳阈值时,两部分之间的差别应该是最大的,衡量差别的方法为最大类间方差。

    直方图有两个峰值的图像,用大津法求得的阈值近似为谷底,如下图所示,即代替了手动输入阈值。
    在这里插入图片描述
    大津法中类间方差是需要最大化的目标函数,那么它的定义如下图所示:
    在这里插入图片描述
    在OpenCV中大津阈值法只是在固定阈值法的函数cv2.threshold的阈值方法type这个参数后加上cv2.THRESH_OTSU,同时将参数2thresh忽视(设置多少无所谓,一般使用0),例如:

    ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    

    看一个例子:

    import cv2
    from matplotlib import pyplot as plt
    
    img = cv2.imread('./image/noisy.png', 0)
    # 固定阈值法
    ret1, th1 = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)
    # Otsu阈值法
    ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    
    # 先进行高斯滤波,再使用Otsu阈值法
    blur = cv2.GaussianBlur(img, (5, 5), 0)
    ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    images = [img, 0, th1, img, 0, th2, blur, 0, th3]
    titles = ['Original', 'Histogram', 'Global(v=100)',
              'Original', 'Histogram', "Otsu's",
              'Gaussian filtered Image', 'Histogram', "Otsu's"]
    
    for i in range(3):
        # 绘制原图
        plt.subplot(3, 3, i * 3 + 1)
        plt.imshow(images[i * 3], 'gray')
        plt.title(titles[i * 3], fontsize=8)
        plt.xticks([]), plt.yticks([])
    
        # 绘制直方图plt.hist, ravel函数将数组降成一维
        plt.subplot(3, 3, i * 3 + 2)
        plt.hist(images[i * 3].ravel(), 256)
        plt.title(titles[i * 3 + 1], fontsize=8)
        plt.xticks([]), plt.yticks([])
    
        # 绘制阈值图
        plt.subplot(3, 3, i * 3 + 3)
        plt.imshow(images[i * 3 + 2], 'gray')
        plt.title(titles[i * 3 + 2], fontsize=8)
        plt.xticks([]), plt.yticks([])
    plt.show()
    

    这里比较了固定阈值法、大津阈值法和加上高斯滤波的大津阈值法,效果如下所示:
    在这里插入图片描述
    相比之下,高斯滤波加大津阈值法的效果是最好的,也是实际使用中最常用的。

    以上就是基于阈值的传统图像分割中常用的几种阈值分割方法。

    展开全文
  • OpenCV大津法二值化

    2021-01-29 15:53:03
    OpenCV大津法二值化 大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与...

    OpenCV大津法二值化

    大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。是求图像全局阈值的最佳方法。

    优点:计算简单快速,不受图像亮度和对比度的影响。

    缺点:对图像噪声敏感;只能针对单一目标分割;当目标和背景大小比例悬殊、类间方差函数可能呈现双峰或者多峰,这个时候效果不好。

    #include <iostream>
    #include <opencv2/core.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/imgproc.hpp>
    
    cv::Mat Binarize(cv::Mat gray, int th){
      int width = gray.cols;
      int height = gray.rows;
    
      cv::Mat out = cv::Mat::zeros(height,width,CV_8UC1);
    
      for(int y = 0;y<height;y++){
        for(int x = 0;x<width;x++){
          if(gray.at<uchar>(y,x) > th){out.at<uchar>(y,x) = 255;}
        }
      }
      return out;
    }
     
    int Otsu(cv::Mat& src, cv::Mat& dst, int thresh){
    	const int Grayscale = 256;
    	int graynum[Grayscale] = { 0 };
    	int r = src.rows;
    	int c = src.cols;
    	for (int i = 0; i < r; ++i){
    		const uchar* ptr = src.ptr<uchar>(i);
    		for (int j = 0; j < c; ++j){
    			graynum[ptr[j]]++;
    		}
    	}
     
        double P[Grayscale] = { 0 };   
    	double PK[Grayscale] = { 0 };
    	double MK[Grayscale] = { 0 };
    	double srcpixnum = r*c, sumtmpPK = 0, sumtmpMK = 0;
    	for (int i = 0; i < Grayscale; ++i){
    		P[i] = graynum[i] / srcpixnum;   //每个灰度级出现的概率
    		PK[i] = sumtmpPK + P[i];         //概率累计和 
    		sumtmpPK = PK[i];
    		MK[i] = sumtmpMK + i*P[i];       //灰度级的累加均值                                                                                                                                                                                                                                                                                                                                                                                                        
    		sumtmpMK = MK[i];
    	}
    	
    	//计算类间方差
    	double Var=0;
    	for (int k = 0; k < Grayscale; ++k){
    		if ((MK[Grayscale-1] * PK[k] - MK[k])*(MK[Grayscale-1] * PK[k] - MK[k]) / (PK[k] * (1 - PK[k])) > Var){
    			Var = (MK[Grayscale-1] * PK[k] - MK[k])*(MK[Grayscale-1] * PK[k] - MK[k]) / (PK[k] * (1 - PK[k]));
    			thresh = k;
    		}
    	}
     
    	src.copyTo(dst);
        dst = Binarize(src,thresh);
    	return thresh;
    }
     
     
    int main(){
    	cv::Mat src = cv::imread("C:/Users/GTTONE/Pictures/Image/SharedScreenshot.jpg");
    	if (src.empty()){
    		return -1;
    	}
    	if (src.channels() > 1)
    		cv::cvtColor(src, src, cv::COLOR_RGB2GRAY);
     
    	cv::Mat m_dst,dst;
    	int thresh=0;
    	double m_t = (double)cv::getTickCount();
    	thresh=Otsu(src , m_dst, thresh); //Otsu
    	std::cout << "m_thresh=" << thresh << std::endl;
    	m_t = (double)cv::getTickCount() - m_t;
    	double m_time = (m_t *1000.) / ((double)cv::getTickFrequency());
    	std::cout << "m_process=" << m_time << " ms. " << std::endl << std::endl;
    
        double  otsuthresh = 0;
    	otsuthresh=cv::threshold(src, dst, otsuthresh, 255, cv::THRESH_OTSU);
    	std::cout << "thresh=" << otsuthresh << std::endl;
     
    	cv::imshow("src", src);
    	cv::imshow("m_dst", dst);
    	cv::imshow("dst", dst);
    	cv::waitKey(0);
    }
    
    展开全文
  • 主要为大家详细介绍了python+opencv实现阈值分割的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 大津阈值算法源码

    2018-09-04 16:11:17
    基于opencv实现的大津阈值,这是封装好的C++借口,调用这个借口,传入一张图(Mat格式),就会返回一个阀值。
  • opencv python 图像二值化/简单阈值化/大津阈值法 参考:https://segmentfault.com/a/1190000015647247 1简单的阈值化 cv2.threshold第一个参数是源图像,它应该是灰度图像. 第二个参数是用于对像素值进行分类的...

    opencv python 图像二值化/简单阈值化/大津阈值法

    参考:https://segmentfault.com/a/1190000015647247

    1简单的阈值化

    cv2.threshold第一个参数是源图像,它应该是灰度图像. 第二个参数是用于对像素值进行分类的阈值, 第三个参数是maxVal,它表示如果像素值大于(有时小于)阈值则要给出的值. OpenCV提供不同类型的阈值,它由函数的第四个参数决定. 不同的类型是:

    cv2.THRESH_BINARY如果 src(x,y)>threshold ,dst(x,y) = max_value; 否则,dst(x,y)=0
    cv.THRESH_BINARY_INV如果 src(x,y)>threshold,dst(x,y) = 0; 否则,dst(x,y) = max_value
    cv.THRESH_TRUNC如果 src(x,y)>threshold,dst(x,y) = max_value; 否则dst(x,y) = src(x,y)
    cv.THRESH_TOZERO如果src(x,y)>threshold,dst(x,y) = src(x,y) ; 否则 dst(x,y) = 0
    cv.THRESH_TOZERO_INV如果 src(x,y)>threshold,dst(x,y) = 0 ; 否则dst(x,y) = src(x,y)
    import cv2
    import numpy as np
    import matplotlib.pylab  as plt
    
    img = cv2.imread('img.jpg',0)
    ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
    ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
    ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
    ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
    
    titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
    images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
    
    for i in range(6):
        plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
        plt.title(titles[i])
        plt.xticks([]),plt.yticks([])
    
    plt.show()

    2自适应阈值化

    图像在不同区域具有不同照明条件时,应进行自适应阈值处理.因此,我们为同一图像的不同区域获得不同的阈值,并且它为具有不同照明的图像提供了更好的结果.
    cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
    adaptiveMethod:决定如何计算阈值

    • cv2.ADAPTIVE_THRESH_MEAN_C:阈值是邻域的平均值
    • cv2.ADAPTIVE_THRESH_GAUSSIAN_C:阈值是邻域值的加权和,其中权重是高斯窗口

    blockSize:决定了邻域的大小
    C:从计算的平均值或加权平均值中减去的常数

    import cv2
    import numpy as np
    import matplotlib.pylab  as plt
    
    img = cv2.imread('img.jpg',0)
    img = cv2.medianBlur(img,5)
    
    ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
                cv2.THRESH_BINARY,11,2)
    th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
                cv2.THRESH_BINARY,11,2)
    
    titles = ['Original Image', 'Global Thresholding (v = 127)',
                'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
    images = [img, th1, th2, th3]
    
    for i in range(4):
        plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
        plt.title(titles[i])
        plt.xticks([]),plt.yticks([])
    plt.show()

    3 大津阈值法

    根据双峰图像的图像直方图自动计算阈值。 (对于非双峰图像,二值化不准确。)

    使用cv.threshold()但是传递了一个额外的标志v.THRESH_OTSU.对于阈值,只需传递零.然后算法找到最佳阈值并返回为第二个输出retVal。如果未使用Otsu阈值法,则retVal与之前使用的阈值相同.

    在第一种情况下,将全局阈值应用为值127.在第二种情况下,直接应用了Otsu的阈值.在第三种情况下,使用5x5高斯内核过滤图像以消除噪声,然后应用Otsu阈值处理.

    import cv2
    import numpy as np
    import matplotlib.pylab  as plt
    
    img = cv2.imread('img.jpg',0)
    # global thresholding
    ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    
    # Otsu's thresholding
    ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    
    # Otsu's thresholding after Gaussian filtering
    blur = cv2.GaussianBlur(img,(5,5),0)
    ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    
    # plot all the images and their histograms
    images = [img, 0, th1,
              img, 0, th2,
              blur, 0, th3]
    titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
              'Original Noisy Image','Histogram',"Otsu's Thresholding",
              'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]
    
    for i in range(3):
        plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
        plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
        plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
        plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
        plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
        plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
    
    plt.show()
    

     

    展开全文
  • opencv大津算法二值化

    2020-07-23 15:21:07
    大津二值化又叫最大类间方差法,可以自动确定二值化的阈值。基本思想是遍历阈值,当某个阈值下分割的两类像素点之间灰度方差最大的时候,就是最优的阈值。(因为类间方差越大,两类的差别越大,不管是前景错分到背景...
  • opencv 大津算法讲解与实现

    千次阅读 2019-07-01 14:26:34
    opencv 中对图像进行二值化的过程中我们可能会使用大津算法,大津算法的主要作用是分割前景与背景部分区域,先将图像灰度化,假设图像有 [0,255] 个灰度等级,在数学中有方差这个概念,如果两个事物之间的方差越...
  • 大津阈值的原理与应用,内含 图像处理 用OpenCV平台 C++实现,并附有PPT讲解原理以及代码实现过程
  • OpenCV -阈值

    2021-06-29 00:50:47
    OpenCV提供了cv2.threshold()和cv2.adaptiveThreshold用于实现阈值处理 1.ret, dst = cv2.threshold(src, thresh, maxval, type) ret:代表返回的阈值。 src:原图,可以是多通道的,8位或32位浮点型数值。 dst: ...
  • 使用python实现大津二值化算法,简单直白地讲解大津二值化算法。
  • opencv图像阈值分割

    千次阅读 2019-03-11 22:41:07
    opencv中提供了不同的阈值准则,以python操作opencv为例: ret, dst = cv2.threshold(src, thresh, maxval, type) src:输入图,只能输入单通道图像,通常来说为灰度图 dst:输出图,一般为二值图像 thr...
  • OpenCV-阈值处理

    2021-01-13 10:28:50
    OpenCV中已经实现了常用的阈值处理方式,可以通过关键字进行选择(开头均以 THRESH 表示): 阈值 thresh , 值 maxval 对应函数 threshold 中的 maxval. 1. THRESH_BINARY 大于thresh的置为 maxval , 小于 thresh ...
  • Python+OpenCV大津法源代码编写

    千次阅读 2019-04-04 20:35:46
    OTSU算法是由日本学者大津于1979年提出的一种对图像进行二值化的高效算法。具体原理CSDN上一大堆,在此不再赘述,直接上自己写的源代码之前先说一下本人的算法步骤: (1)读入一幅图像; (2)将读入的图像灰度...
  • opencv阈值二值化

    2020-04-28 21:34:55
    阈值分割(二值化) 阈值分类 1.全局阈值 定义:全局只使用一个阈值进行二值划分 缺点:没有考虑光照,明暗变化,用全局阈值可能...1.大津阈值(最大类间方差法) 原理:选取类间方差最大的阈值作为全局阈值划分 ...
  • 最大类间方差法(大津阈值法) 大津法又叫最大类间方差法、最大类间阈值法(OTSU)。它的基本思想是,用一个阈值将图像中的数据分为两类,一类中图像的像素点的灰度均小于这个阈值,另一类中的图像的像素点的灰度均...
  • opencv-阈值分割

    2019-09-27 13:00:42
    自适应阈值分割—大津法(OTSU算法)C++实现 灰度图像的自动阈值分割(Otsu 法) 在实际运用过程中,大津法表现得最稳定,且无需参数,对于现实图像保持了最好的均匀性和形状特性,而且被商业软件GIMP ...
  • 1简单的阈值化cv2.threshold第一个参数是源图像,它应该是灰度图像.... OpenCV提供不同类型的阈值,它由函数的第四个参数决定. 不同的类型是:cv2.THRESH_BINARY如果 src(x,y)>threshold ,dst(x,y) = max_value; 否...
  • 最后两种方法是计算一个自适应阈值来对图像进行二值化,前者是大津阈值,后者使用三角算法选择最佳阈值。 这些枚举类型的名字空间为cv。 在后面的程序中,我会以具体的数值来说明二值化的方式。 threshold函数原型 ...
  • 学更好的别人,做更好的自己。——《微卡智享》本文长度为1245字,预计阅读3分钟前言上篇《C++ OpenCV自适应阈值Canny边缘检测》中,使用的求中值的方式来获取自适应阈值,有小伙伴...
  • pip install matplotlib1简单的阈值化cv2.threshold第一个参数是源图像,它应该是灰度图像.... OpenCV提供不同类型的阈值,它由函数的第四个参数决定. 不同的类型是:cv2.THRESH_BINARY如果 src(x,y)>threshold ,d...
  • opencv自动阈值分割

    2021-01-24 17:27:32
    #自适应阈值与固定阈值对比 import cv2 import matplotlib.pyplot as plt img = cv2.imread('test.jpg',0) ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY) th2 = cv2.adaptiveThreshold(img,255,cv2....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,065
精华内容 426
关键字:

opencv大津阈值