zoukankan      html  css  js  c++  java
  • opencv2——直方图5

    (一)图像直方图

    图像的构成是有像素点构成的,每个像素点的值代表着该点的颜色(灰度图或者彩色图)。所谓直方图就是对图像的中的这些像素点的值进行统计,得到一个统一的整体的灰度概念。直方图的好处就在于可以清晰了解图像的整体灰度分布,这对于后面依据直方图处理图像来说至关重要。

    一般情况下直方图都是灰度图像,直方图x轴是灰度值(一般0~255),y轴就是图像中每一个灰度级对应的像素点的个数。

    那么如何获得图像的直方图?首先来了解绘制直方图需要的一些量:灰度级,正常情况下就是0-255共256个灰度级,从最黑一直到最亮(白)(也有可能统计其中的某部分灰度范围),那么每一个灰度级对应一个数来储存该灰度对应的点数目。也就是说直方图其实就是一个1*m(灰度级)的一个数组而已。但是有的时候我们不希望一个一个灰度的递增,比如现在我想15个灰度一起作为一个灰度级来花直方图,这个时候我们可能只需要1*(m/15)这样一个数组就够了。那么这里的15就是直方图的间隔宽度了。

    Opencv给我们提供的函数是cv2.calcHist(),该函数有5个参数:

    image输入图像,传入时应该用中括号[]括起来
    channels::传入图像的通道,如果是灰度图像,那就不用说了,只有一个通道,值为0,如果是彩色图像(有3个通道),那么值为0,1,2,中选择一个,对应着BGR各个通道。这个值也得用[]传入。
    mask:掩膜图像。如果统计整幅图,那么为none。主要是如果要统计部分图的直方图,就得构造相应的炎掩膜来计算。
    histSize:灰度级的个数,需要中括号,比如[256]
    ranges:像素值的范围,通常[0,256],有的图像如果不是0-256,比如说你来回各种变换导致像素值负值、很大,则需要调整后才可以。
    除此之外,强大的numpy也有函数用于统计直方图的,通用的一个函数np.histogram,还有一个函数是np.bincount()(用于以为统计直方图,速度更快)。这三个方式的传入参数基本上差不多,不同的是opencv自带的需要中括号括起来。
    对于直方图的显示也是比较简单的,直接plt.plot()就可以。一个实例如下:

     1 import cv2
     2 import numpy as np
     3 import matplotlib.pyplot as plt
     4 img = cv2.imread('test.jpg', 0)  # 直接读为灰度图像
     5 
     6 # opencv方法读取-cv2.calcHist(速度最快)
     7 # 图像,通道[0]-灰度图,掩膜-无,灰度级,像素范围
     8 hist_cv = cv2.calcHist([img], [0], None, [256], [0, 256])
     9 
    10 # numpy方法读取-np.histogram()
    11 hist_np, bins = np.histogram(img.ravel(), 256, [0, 256])
    12 
    13 # numpy的另一种方法读取-np.bincount()(速度=10倍法2)
    14 hist_np2 = np.bincount(img.ravel(), minlength=256)
    15 
    16 plt.subplot(221), plt.imshow(img, 'gray')
    17 plt.subplot(222), plt.plot(hist_cv)
    18 plt.subplot(223), plt.plot(hist_np)
    19 plt.subplot(224),plt.plot(hist_np2)
    20 plt.show()

    执行结果:

    现在来考虑opencv的直方图函数中掩膜的使用,这个掩膜就是一个区域大小,表示你接下来的直方图统计就是这个区域的像素统计。一个例子如下:

     1 import cv2
     2 import numpy as np
     3 import matplotlib.pyplot as plt
     4 
     5 img = cv2.imread('test.jpg', 0)  # 直接读为灰度图像
     6 mask = np.zeros(img.shape[:2], np.uint8)
     7 mask[100:200, 100:200] = 255
     8 masked_img = cv2.bitwise_and(img, img, mask=mask)
     9 
    10 # opencv方法读取-cv2.calcHist(速度最快)
    11 # 图像,通道[0]-灰度图,掩膜-无,灰度级,像素范围
    12 hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
    13 
    14 hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])
    15 
    16 plt.subplot(221), plt.imshow(img, 'gray')
    17 plt.subplot(222), plt.imshow(mask, 'gray')
    18 plt.subplot(223), plt.imshow(masked_img, 'gray')
    19 plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
    20 plt.show()

    执行结果:

    (二)直方图均衡化

    图像的直方图是对图像对比度效果上的一种处理,旨在使得图像整体效果均匀,黑与白之间的各个像素级之间的点更均匀一点。
    直方图均衡化只要包括三个步骤:

    1、统计直方图中每个灰度级出现的次数;
    2、计算累计归一化直方图;
    3、重新计算像素点的像素值;
    关于原理的详细部分给一个参考:

    直方图均衡化原理

    百度百科的解释也很棒

    http://baike.baidu.com/link?url=RUjahehgkTMDGKwAEyMsHyeMyWWTw9a0KUx2CzLbXtxdZyoF6zqDbJsfEffUQYAwvr7kD9p6cbOxJGYGk1nkZq

    在opencv有专门函数对直方图进行均衡化使用的函数就是cv2.equalizeHist().一个实例如:

    import cv2
    import matplotlib.pyplot as plt
    
    img = cv2.imread('flower.jpg',0) #直接读为灰度图像
    res = cv2.equalizeHist(img)
    
    plt.subplot(121),plt.imshow(img,'gray')
    plt.subplot(122),plt.imshow(res,'gray')

    上述的直方图均衡化可以可能到是一种全局意义上的均衡化,但是有的时候这种操作并不是很好,会把某些不该调整的部分给调整了。Opencv中还有一种直方图均衡化,它是一种局部局部来的均衡化,也就是是说把整个图像分成许多小块(比如按10*10作为一个小块),那么对每个小块进行均衡化。这种方法主要对于图像直方图不是那么单一的(比如存在多峰情况)图像比较实用。Opencv中将这种方法称之为CLAHE,使用到的函数就是cv2.createCLAHE(),一个实例如下:

    import cv2
    import matplotlib.pyplot as plt
    
    img = cv2.imread('flower.jpg',0) #直接读为灰度图像
    clahe = cv2.createCLAHE(clipLimit=2,tileGridSize=(10,10))
    cl1 = clahe.apply(img)
    
    plt.subplot(121),plt.imshow(img,'gray')
    plt.subplot(122),plt.imshow(cl1,'gray')



    可以看到,相对于全局的直方图均衡化,这个局部的均衡化似乎得到的效果更自然一点。
    ————————————————
    版权声明:本文为CSDN博主「on2way」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/on2way/article/details/46881599

    1

  • 相关阅读:
    微信视频号里的视频如何保存下来呢?
    jQuery实现平面图区域标记
    npm安装教程 yarn 基本安装和使用
    VitePress :VuePress 下一代建站工具
    基于CentOS的ECS实例实现OSS反向代理
    备份MySQL数据库到七牛云的shell脚本
    ShedLock 解决分布式结构下定时任务重复执行问题
    linux清除日志和文件缓存
    Communications link failure:The last packet successfully received from the server was 0 millisecond ago
    CentOS7安装nodeJs
  • 原文地址:https://www.cnblogs.com/weststar/p/11512991.html
Copyright © 2011-2022 走看看