openCV——直方图处理

直方图处理

  • 直方图统计图像内各个灰度级出现的次数。
import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline 
def cvshow(name, ndarray):
    img = cv2.imshow(name, ndarray)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
  1. DIMS:表示在绘制直方图时,收集的参数的数量。一般情况下,直方图中收集的数据只有一种,就是灰度级。因此,该值为 1。
  2. RANGE:表示要统计的灰度级范围,一般为[0, 255]。0 对应的是黑色,255 对应的是白色。
  3. BINS:参数子集的数目。就是指将要统计的指标数据划分为多少个组

两种绘制直方图的方式

1. Numpy绘制直方图

matplotlib.pyplot.hist(X,BINS)

  • X:数据源,必须是一维的。图像通常是二维的,需要使用 ravel()函数将图像处理为一维数据源以后,再作为参数使用。
  • BINS:将灰度级分为多少个区间
lena = cv2.imread("lena.jpg")
plt.hist(lena.ravel(), 16)
(array([ 2447.,  7368.,  5412., 11710., 19672., 24738., 23819., 21311.,
        15392., 11566., 11007., 12159., 14515., 13735.,  9977.,  2679.]),
 array([  0.    ,  15.9375,  31.875 ,  47.8125,  63.75  ,  79.6875,
         95.625 , 111.5625, 127.5   , 143.4375, 159.375 , 175.3125,
        191.25  , 207.1875, 223.125 , 239.0625, 255.    ]),
 <BarContainer object of 16 artists>)

在这里插入图片描述

2. OpenCV绘制直方图

OpenCV 提供了函数 cv2.calcHist()用来计算图像的统计直方图,该函数能统计各个灰度级的像素点个数。利用 matplotlib.pyplot 模块中的 plot()函数,可以将函数 cv2.calcHist()的统计结果绘制成直方图。

hist = cv2.calcHist( images, channels, mask, histSize, ranges, accumulate )

  • hist:返回的统计直方图,是一个一维数组,数组内的元素是各个灰度级的像素个数。
  • images:原始图像,该图像需要使用“[ ]”括起来
  • channels:指定通道编号。通道编号需要用“[ ]”括起来,如果输入图像是单通道灰度图像,该参数的值就是[0]。对于彩色图像,它的值可以是[0]、[1]、[2],分别对应通道B、G、R。
  • mask:掩模图像。当统计整幅图像的直方图时,将这个值设为 None。当使用掩模图像获取直方图时,仅获取掩模参数 mask 指定区域的直方图。
  • histSize:BINS 的值,该值需要用“[ ]”括起来。例如,BINS 的值是 256,需要使用“[256]”作为此参数值。
  • ranges:即像素值范围。例如,8 位灰度图像的像素值范围是[0, 255]
  • accumulate:累计(累积、叠加)标识,默认值为 False。如果被设置为 True,则直方图在开始计算时不会被清零,计算的是多个直方图的累积结果,用于对一组图像计算直方图。该参数允许从多个对象中计算单个直方图,或者实时更新直方图。该参数是可选的,一般情况下不需要设置
hist_red = cv2.calcHist([lena], [2], mask=None, histSize=[16], ranges=[0, 255])
hist_green = cv2.calcHist([lena], [1], mask=None, histSize=[16], ranges=[0, 255])
hist_blue = cv2.calcHist([lena], [0], mask=None, histSize=[16], ranges=[0, 255])
print(hist_red.sum())
print(hist_green.sum())
print(hist_blue.sum())
68852.0
69169.0
69169.0





(16, 1)
plt.figure(figsize=(8, 6), dpi=80)
plt.plot(np.arange(0, 256, 16), hist_blue, color="b", label="blue")
plt.plot(np.arange(0, 256, 16), hist_green, color="g", label="green")
plt.plot(np.arange(0, 256, 16), hist_red, color="r", label="red")
plt.grid()
plt.legend()
<matplotlib.legend.Legend at 0x25d475f7400>

在这里插入图片描述

掩模

在这里插入图片描述

左图是原始图像 O,中间的是掩模图像 M,右图是使用掩模图像 M 对原始图像 O 进行掩模运算的结果图像 R。可以将掩模图像看作一块玻璃板,玻璃板上的白色区域是透明的,黑色区
域是不透明的。掩模运算就是将该玻璃板覆盖在原始图像上,透过玻璃板显示出来的部分就是掩模运算的结果图像。

  • 根据与运算的规则,任意一个数值与数值 1 进行与运算,结果等于其自身的值。因此,任意一个 8 位像素值与二进制数“1111 1111”进行按位与运算,得到的都是自身的值。二进制值“1111 1111”对应的十进制值是“255”,所以任意一个 8 位像素值与“255”进行按位与运算,得到的都是自身原来的值。

在这里插入图片描述

可以将掩模图像的白色背景部分设置为 255,黑色背景部分设置为 0

在这里插入图片描述

lena = cv2.imread("lena.jpg", cv2.IMREAD_GRAYSCALE)
print(lena.shape)
mask = np.zeros((lena.shape[0], lena.shape[1]), np.uint8)
mask[70:180, 70:180]=255
cvshow("mask", mask)
#bitwise_and按位操作时,两个数据的shape要一致,注意:彩色图像是三维的
dst = cv2.bitwise_and(lena, mask)
cvshow("dst", dst)
# 并且可以将这个mask直接传入cv2.calcHist()函数中
(263, 263)

直方图均衡化

如果一幅图像拥有全部可能的灰度级,并且像素值的灰度均匀分布,那么这幅图像就具有高对比度和多变的灰度色调,灰度级丰富且覆盖范围较大。在外观上,这样的图像具有更丰富
的色彩,不会过暗或过亮。

  • 直方图均衡化的主要目的是将原始图像的灰度级均匀地映射到整个灰度级范围内,得到一个灰度级分布均匀的图像.这种均衡化,既实现了灰度值统计上的概率均衡,也实现了人类视觉系统(Human Visual System,HVS)上的视觉均衡

在这里插入图片描述

  • 情况A:每一个灰度级在图像内出现的次数都是 1,灰度级均匀地映射到当前的灰度级范围内,所以可以理解为其直方图是均衡的。
  • 情况B:灰度级 1、2、3 出现的次数都是 1 次,灰度级 103 出现的次数是 3 次,灰度级101、102 出现的次数是 0 次。从表面上看,灰度级是不均衡的。但是,从 HVS的角度说,人眼的敏感度不足以区分 1 个像素值的差异,即人眼会将灰度级 1、2 和 3 看作是相同的,会将灰度级 101、102 和 103 看作是相同的。也就是说,HVS 会自动地将灰度级划分为两组,灰度级[1, 3]为一组,灰度级[101, 103]为另一组。在整幅图像内,这组的灰度级出现的次数都是 3 次,概率是相等的。在均衡化处理中,综合考虑了统计概率和 HVS 的均衡。

直方图均衡化原理

直方图均衡化的算法主要包括两个步骤:

  1. 计算累计直方图。
  2. 对累计直方图进行区间转换

在这里插入图片描述

图像 A 如图 ,它是一幅 3 位的位图,即共有 8(0-7)个灰度级,有 49 个像素

  • 得到统计直方图:

在这里插入图片描述

  • 得到归一化直方图:

在这里插入图片描述

  • 得到累计统计直方图:

在这里插入图片描述

在原有范围内实现均衡化

在原有范围内实现直方图均衡化时,用当前灰度级的累计概率乘以当前灰度级的最大值 7,并四舍五入得到新的灰度级,并作为均衡化的结果。

在这里插入图片描述

  • 原始图像 A 中的灰度级 1 和 2 经直方图均衡化后调整为灰度级 3。在原始图像 A 中,灰度级 1 共有 9 个像素点,灰度级 2 共有 6 个像素点,所以在均衡化后的图像中,灰度级 3 共有 9 + 6 = 15 个像素点。 其他的以此类推

在这里插入图片描述

在更广泛的范围内实现均衡化

在更广泛的范围内实现直方图均衡化时,用当前灰度级的累计概率乘以更广泛范围灰度级的最大值,得到新的灰度级,并作为均衡化的结果。例如,要将灰度级空间扩展为[0, 255]共256 个灰度级,就必须将原灰度级的累计概率乘以 255,得到新的灰度级。其他步骤均一致

API

dst = cv2.equalizeHist( src )

  • src 是 8 位单通道原始图像,dst 是直方图均衡化处理的结果
mary = cv2.imread("mary.png", cv2.IMREAD_GRAYSCALE)
cvshow("mary", mary)
pro = cv2.equalizeHist(mary)
res = np.hstack((mary, pro))
cvshow("res", res)

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值