OpenCV学习笔记17-直方图

本文详细介绍了图像处理中的直方图概念及其应用,包括直方图的绘制方法、直方图均衡化以及有限对比适应性直方图均衡化(CLAHE)。通过实例展示了如何利用OpenCV和Matplotlib实现这些技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.什么是直方图

通过直方图你可以对整幅图像的灰度分布有一个整体的了解。

  • 直方图的x轴是灰度值(0到255),y轴是图片中具有同一个灰度值的点的数目;
  • 直方图是根据灰度图像绘制的,而不是彩色图像。

这里写图片描述

关于上面这幅图片和它的直方图:直方图的左侧是暗一点的像素数量,右侧是亮一点的像素数量。从这幅图上你可以看到灰暗区域亮区域要大,而处于中间部分的像素点很少。


2.统计直方图

cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) -> hist

  • images:[],原图像(图像格式为 uint8 或 float32);
  • channels:[],表示选择一个通道来计算。如果输入图像是灰度图,它的值就是 [0];如果是彩色图像,传入的参数可以是 [0], [1], [2] 它们分别对应着通道 B, G, R。
  • mask:掩模图像。要统计整幅图像的直方图就把它设为 None。但如果统计图像某一部分的直方图的话,需要制作一个掩模图像,并使用它。
  • histSize:[],BIN的数目;
  • ranges:[],像素值范围,通常为 [0,256]。
  • hist:输出数组,[histSize x 1],每一个值代表了与之灰度值对应的像素点数目。

3.绘制直方图

使用 Matplotlib 中的绘图函数

(1)plt.hist()可以直接统计并绘制直方图


import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('1.png', 0)
plt.hist(img.ravel(), 256, [0,256])  #统计并绘制直方图
plt.show()

这里写图片描述
这里写图片描述


(2)opencv函数统计直方图+matplotlib的绘图功能

这在同时绘制多通道(BGR)的直方图,很有用。

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('1.png')
color = ('b','g','r')

#对一个列表或数组既要遍历索引又要遍历元素时,使用enumerate()函数
#enumerate()将数组或列表组成一个索引序列,既有索引又有元素
for i,col in enumerate(color):
    histr = cv2.calcHist([img], [i], None, [256], [0,256])
    plt.plot(histr, color = col)
    plt.xlim([0,256])
plt.show()

这里写图片描述

从上边的直方图可以推断出:蓝色曲线靠右侧的最多(很明显这些就是天空)


(3)使用掩膜

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

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('1.png', 0)

#创建一个mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv2.bitwise_and(img, img, mask=mask)

#统计无mask和有mask的直方图
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, cmap='gray')
plt.subplot(222), plt.imshow(mask, cmap='gray')
plt.subplot(223), plt.imshow(masked_img, cmap='gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])

plt.show()

这里写图片描述

其中蓝线是整幅图像的直方图,绿线是进行掩模之后的直方图。


4.直方图均衡化

作用:把直方图做一个横向拉伸,改善图像的对比度。

cv2.equalizeHist(src[, dst]) -> dst

  • src:输入图片,是一副灰度图像;
  • dst:输出结果,直方图均衡化之后的图像。
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('3.png', 0)
equ = cv2.equalizeHist(img)
res = np.hstack((img, equ))  #stacking images side-by-side

cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

这里写图片描述


5.有限对比适应性直方图均衡化(CLAHE)

(1)自适应的直方图均衡化:

  • 整幅图像会被分成很多小块,这些小块被称为“tiles”(OpenCV中tiles的大小默认是8x8),然后再对每一个小块分别进行直方图均衡化。
  • 优点:该算法更适合于改进图像的局部对比度以及获得更多的图像细节。
  • 缺点:如果有噪声的话,噪声会被放大。

(2)有限对比适应性直方图均衡化(CLAHE):

  • 为了避免放大噪声这种情况的出现,在自适应的直方图均衡化的基础上,使用对比度限制
  • 对于每个小块来说,如果直方图中的bin超过对比度的上限的话,就把其中的像素点均匀分散到其他 bins 中,然后在进行直方图均衡化。
  • 最后,为了去除每一个小块之间“人造的”(由于算法造成)边界,再使用双线性差值,对小块进行缝合。

cv2.createCLAHE([, clipLimit[, tileGridSize]]) -> retval

  • clipLimit代表裁剪限幅的大小
  • tileGridSize代表局部区域的大小
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('3.png', 0)

#create a CLAHE object
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cll = clahe.apply(img)

cv2.imshow('img', img)
cv2.imshow('cll', cll)
cv2.waitKey(0)
cv2.destroyAllWindows()


原图



这里写图片描述
有限对比适应性直方图均衡化(CLAHE)



这里写图片描述
整体直方图均衡化


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值