zoukankan      html  css  js  c++  java
  • opencv-python教程学习系列12-图像阈值

    前言

    opencv-python教程学习系列记录学习python-opencv过程的点滴,本文主要介绍图像阈值/二值化,坚持学习,共同进步。

    系列教程参照OpenCV-Python中文教程

    系统环境

    系统:win7_x64;

    python版本:python3.5.2;

    opencv版本:opencv3.3.1;

    内容安排

    1.知识点介绍;

    2.测试代码;

    具体内容

    1.知识点介绍;

    图像的阈值处理一般使得图像的像素值更单一、图像更简单。阈值可以分为全局性质的阈值,也可以分为局部性质的阈值,可以是单阈值的也可以是多阈值的。当然阈值越多是越复杂的。下面将介绍opencv下的三种阈值方法。主要涉及的函数是cv2.threshold , cv2.adaptiveThreshold;

    1.1 简单阈值;

    简单阈值当然是最简单,选取一个全局阈值,然后把整幅图像分成了非黑即白的二值图像。

    使用的函数是cv2.threshold,包括四个参数,第一个是原图像(灰度图像),第二个是进行分类的阈值,第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数,常用的方法有: 
    • cv2.THRESH_BINARY(黑白二值) 
    • cv2.THRESH_BINARY_INV(黑白二值反转) 
    • cv2.THRESH_TRUNC (得到的图像为多像素值) 
    • cv2.THRESH_TOZERO 
    • cv2.THRESH_TOZERO_INV 
    该函数有两个返回值,第一个retVal(得到的分割阈值),第二个就是阈值化后的图像。 

    ret , thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
    

    1.2 自适应阈值;

    自适应阈值可以看成一种局部性的阈值,通过规定一个区域大小,比较这个点与区域大小里面像素点的平均值(或者其他特征)的大小关系确定这个像素点是属于黑或者白(如果是二值情况)。使用的函数为cv2.adaptiveThreshold,该函数有6个参数,分别是原始灰度图像、像素值上限、自适应方法、赋值方法、邻域大小、常数,其中自适应方法包含cv2.ADAPTIVE_THRESH_MEAN_C (邻域均值)和cv2.ADAPTIVE_THRESH_GAUSSIAN_C(邻域加权和)两种,常数表示阈值等于均值或者加权值减去这个常数;

    ret , th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    # 11为block size,2为C值
    th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C , cv2.THRESH_BINARY,11,2 )
    

    1.3 大津法OTSU;

    Otsu方法试图自动找到一个最好的阈值,可以最小化加权的类内方差,并且Otsu非常适合于图像灰度直方图具有双峰的情况,在双峰(bimodal )之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。

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

    2.测试代码;

    2.1 自适应阈值;

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    img = cv2.imread('test.jpg',0)
    #中值滤波
    img = cv2.medianBlur(img,5)
    
    ret , th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    # 11为block size,2为C值
    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()
    

    2.2 OTSU方法;

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    img = cv2.imread('test.jpg',0)
    
    ret1,th1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    
    ret2,th2=cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    #(5,5)为高斯核的大小,0为标准差
    blur= cv2.GaussianBlur(img,(5,5),0)#高斯滤波平滑
    
    #阀值一定要设为0
    ret3,th3=cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    
    images=[img,0,th1,
             img,0,th2,
             img,0,th3]
    titles =['original noisy image','histogram','global thresholding(v=127)',
              'original noisy image','histogram',"otsu's thresholding",
              'gaussian filtered image','histogram',"otus's thresholding"]
    #这里使用了pyplot中画直方图的方法,plt.hist要注意的是他的参数是一维数组
    #所以这里使用了(numpy)ravel方法,将多维数组转换成一维,也可以使用flatten方法
    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()
    

    2.3 OTSU的实现;

    #opencv官网https://docs.opencv.org/3.3.1/d7/d4d/tutorial_py_thresholding.html
    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    img = cv2.imread('test.jpg',0)
    blur = cv2.GaussianBlur(img,(5,5),0)
    # find normalized_histogram, and its cumulative distribution function
    hist = cv2.calcHist([blur],[0],None,[256],[0,256])
    hist_norm = hist.ravel()/hist.max()
    Q = hist_norm.cumsum()
    bins = np.arange(256)
    fn_min = np.inf
    thresh = -1
    for i in range(1,256):
        p1,p2 = np.hsplit(hist_norm,[i]) # probabilities
        q1,q2 = Q[i],Q[255]-Q[i] # cum sum of classes
        b1,b2 = np.hsplit(bins,[i]) # weights
        # finding means and variances
        m1,m2 = np.sum(p1*b1)/q1, np.sum(p2*b2)/q2
        v1,v2 = np.sum(((b1-m1)**2)*p1)/q1,np.sum(((b2-m2)**2)*p2)/q2
        # calculates the minimization function
        fn = v1*q1 + v2*q2
        if fn < fn_min:
            fn_min = fn
            thresh = i
    # find otsu's threshold value with OpenCV function
    ret, otsu = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    print( "{} {}".format(thresh,ret) )#ret表示得到的分割阈值;
    

    参考

    1.图像阈值

    2.CSDN图像阈值

    3.opencv官网

  • 相关阅读:
    使用react hook做一个小型完整项目(包括二级路由,动态路由,redux,tab切换,列表跳详情,登录, 守卫)
    项目实战【vue,react,微信小程序】(1705E)
    Vue(1706E)
    加入购物车动画(css)
    React从入门到精通(1704B)
    React(1702H)文章管理-cms系统
    React(1702H)文件上传和分页查找
    React (1702H) 点击复制、滚动条、图形验证码、ridis、密码rsa加密、token、发邮件、文件上传、sql语句
    位图算法
    def跨域+jwt
  • 原文地址:https://www.cnblogs.com/happyamyhope/p/8127656.html
Copyright © 2011-2022 走看看