openCV:直方图

作者: SwiftBirds | 来源:发表于2019-09-25 08:00 被阅读0次

    直方图

    定义

    直方图是对数据集合统计,并将统计结果分布于一系列定义的bins中。这里的数据不仅仅是灰度值,统计数据可能是任何能够有效描述图像的特征,例如颜色、梯度/边缘、形状、纹理、局部特征点、视觉词汇等。

    灰度直方图

    通过直方图你可以对整幅图像的灰度分布有一个整体的了解。直方图的 x 轴是灰度值(0 到 255),y 轴是图片中具有同一个灰度值的点的数目。
    灰度直方图其实就是对图像的另一种解释。通过直方图我们可以对图像的对比度,亮度,灰度分布等有一个直观的认识。

    灰度直方图.png

    API

    cv2.calcHist(images,channels,mask,histSize,ranges)

    • images: 原图像(图像格式为 uint8 或 float32)。当传入函数时应该用中括号 [] 括起来,例如:[img]。

    • channels: 同样需要用中括号括起来,它会告诉函数我们要统计那幅图像的直方图。如果输入图像是灰度图,它的值就是 [0];如果是彩色图像的话,传入的参数可以是 [0],[1],[2] 它们分别对应着通道 B,G,R。

    • mask: 掩模图像。要统计整幅图像的直方图就把它设为 None。但是如果你想统计图像某一部分的直方图的话,你就需要制作一个掩模图像,并使用它。(后边有例子)

    • histSize:BIN 的数目。也应该用中括号括起来,例如:[256]。

    • ranges: 像素值范围,通常为 [0,256]

    import cv2 #opencv读取的格式是BGR
    import numpy as np
    import matplotlib.pyplot as plt#Matplotlib是RGB
    %matplotlib inline 
    
    def cv_show(name,img):
        cv2.imshow(name,img)
        cv2.waitKey()
        cv2.destroyAllWindows()
    

    整幅图像操作

    numpy中的ravel()、flatten()、squeeze()都有将多维数组转换为一维数组的功能,区别:

    • ravel():如果没有必要,不会产生源数据的副本
    • flatten():返回源数据的副本
    • squeeze():只能对维数为1的维度降维

    使用 Matplotlib Matplotlib 中有直方图绘制函数:matplotlib.pyplot.hist()它可以直接统计并绘制直方图。

    img = cv2.imread('cat.jpg',0) #0表示灰度图
    hist = cv2.calcHist([img],[0],None,[256],[0,256])
    hist.shape
    
    (256, 1)
    
    plt.hist(img.ravel(),256); 
    plt.show()
    
    output_4_0.png
    img = cv2.imread('cat.jpg') 
    color = ('b','g','r')
    for i,col in enumerate(color):
        histr = cv2.calcHist([img],[i],None,[256],[0,256]) 
        plt.plot(histr,color = col) 
        plt.xlim([0,256]) 
    
    output_5_0.png

    mask操作

    要统计图像某个局部区域的直方图只需要构建一副掩模图像。将要统计的部分设置成白色,其余部分为黑色,就构成了一副掩模图像。然后把这个掩模图像传给函数就可以了。

    # 创建mast
    mask = np.zeros(img.shape[:2], np.uint8)
    print (mask.shape)
    mask[100:300, 100:400] = 255
    cv_show('mask',mask)
    
    (414, 500)
    
    掩模图像.PNG
    img = cv2.imread('cat.jpg', 0)
    cv_show('img',img)
    
    原图.PNG
    #与操作
    masked_img = cv2.bitwise_and(img, img, mask=mask)
    cv_show('masked_img',masked_img)
    
    掩膜操作后的图像.PNG
    hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
    hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])
    plt.subplot(221), plt.imshow(img, 'gray')
    plt.subplot(222), plt.imshow(mask, 'gray')
    plt.subplot(223), plt.imshow(masked_img, 'gray')
    plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
    plt.xlim([0, 256])
    plt.show()
    
    output_10_0.png

    直方图均衡化

    概念

    直方图均衡化就是将原始的直方图拉伸,使之均匀分布在全部灰度范围内,从而增强图像的对比度。

    直方图均衡化的中心思想是把原始图像的的灰度直方图从比较集中的某个区域变成在全部灰度范围内的均匀分布。旨在使得图像整体效果均匀,黑与白之间的各个像素级之间的点更均匀一点。

    原始直方图 直方图均衡化 直方图均衡化的原理
    img = cv2.imread('clahe.jpg',0) #0表示灰度图 
    plt.hist(img.ravel(),256); 
    plt.show()
    
    output_12_0.png
    equ = cv2.equalizeHist(img) 
    plt.hist(equ.ravel(),256)
    plt.show()
    
    output_13_0.png
    res = np.hstack((img,equ))
    cv_show('res',res)
    
    直方图均衡化前后对比.PNG

    自适应直方图均衡化

    自适应直方图均衡化的实现方法首先是将图像划分成不重叠的区域块,让后对每个块分别进行直方图均衡化处理。如果在图像有噪声的情况下这样处理,在每个被分割的小区域块中的噪声就会被放大。

    为了避免噪声对图像均衡化的影响,使用限制对比度的自适应直方图均衡化来处理图像的直方图均衡化。限制对比度的直方图均衡化的处理方式是先为直方图设置一个阈值,该阈值为限制对比度值,超过该阈值的值会被裁剪,然后裁剪的部分会均匀的分布到其他值上,这样就重构了直方图,接下来就可以用重构后的直方图来进行接下来的均衡化操作了。

    默认设置的“限制对比度”为40,块的大小为8X8

    cv2.createCLAHE

    • clipLimit:越大的话,对比度越低
    • tileGridSize:划分每个区域块的大小
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) 
    res_clahe = clahe.apply(img)
    res = np.hstack((img,equ,res_clahe))
    cv_show('res',res)
    
    自适应均衡化与普通均衡化的对比.PNG

    相关文章

      网友评论

        本文标题:openCV:直方图

        本文链接:https://www.haomeiwen.com/subject/zkriuctx.html