直方图处理(基于opencv)

一. 灰度直方图

r_{k},其中k=0,1,2,...,L-1,表示一幅L级灰度数字图像f(x,y)的灰度。f的非归一化直方图定义为:

h(r_{k})=n_{k}k=1,2,...,L-1

式中,n_{k}是f中灰度为r_{k}的像素的数量,并且细分的灰度级称为直方图容器。

f的归一化直方图定义为:

p(r_{k})=\frac{h(r_{k})}{MN}=\frac{n_{k}}{MN}

式中,M和N分别是一幅数字图像的行列数。在大多数情况下,处理的都是归一化直方图。对k所有值,p(r_{k})的和总是1,p(r_{k})的分量是对图像中出现的灰度级的概率估计。

在matplotlib中有绘制直方图的函数:plt.hist(),可以直接统计计算并绘制颜色直方图。

plt.figure(figsize=(5,4), dpi=200)
plt.rcParams["font.family"] = "Times New Roman"
plt.hist(image_gray.ravel(),256,[0,256], color='gray')
plt.title('Gray Histograms')
plt.show()

                     

如果是三通道,则循环遍历各通道,依次绘制每个通道的颜色直方图。

color = ('b','g','r')
plt.figure(figsize=(5,4), dpi=200)
for i,col in enumerate(color):
    hist = cv2.calcHist([image_brg],[i],None,[256],[0,256])
    plt.plot(hist,color = col)
    plt.xlim([0,256])
plt.show()

plt.figure(figsize=(5,4), dpi=200)
plt.imshow(cv2.cvtColor(image_brg, cv2.COLOR_BGR2RGB))
plt.axis('off')

                  

如果在绘制直方图的时候,需要对指定图像位置进行绘制,可以利用掩模提取目标区域再绘制直方图。

 二. 直方图均衡化

直方图均衡化通常会增加图像的全局对比度,尤其是当图像由较窄的灰度(强度)值范围表示时。通过这个方法可以更好地利用整个强度范围均匀地分布在直方图上。这允许局部对比度较低的区域获得较高的对比度

直方图均衡化在背景和前景都很亮或都很暗的图像中很有用。特别是,该方法可以在 X 射线图像中更好地观察骨骼结构,并在曝光过度或曝光不足的照片中获得更好的细节。该方法的一个关键优点是,它是一种相当简单的技术,适用于输入图像和可逆运算符。所以从理论上讲,如果直方图均衡函数是已知的,那么原始直方图就可以恢复。

图像的灰度可视为区间[0,L-1]内的随机变量。令p_{r}(r)p_{s}(s)表示两幅不同图像中灰度值r和s的PDF,若已知p_{r}(r)T(r),且T(r)在定义域范围内是连续可微的,则变换后的变量s的PDF是:

p_{s}(s)=p_{r}(r)\left | \frac{dr}{ds} \right |

可见,输出灰度变量的PDF是由输入灰度的PDF和所用的变换函数确定。

图像处理中的一个很重要的变换函数:

s=T(r)=(L-1)\int_{0}^{r} p_{r}(w)dw

式中,w是一个假积分变量,右侧的积分是随机变量r的累积分布函数(CDF)。

\frac{ds}{dr}=\frac{dT(r)}{dr}=(L-1)\frac{d}{dr}[\int_{0}^{r}p_{r}(w)dw]=(L-1)p_{r}(r)

因此,输出灰度的PDF:

p_{s}(s)=p_{r}(r)\left | \frac{dr}{ds} \right |=\frac{1}{L-1}

 可见,p_{s}(s)是均匀分布概率密度函数。

opencv中提供了库函数进行图像的直方图均衡化

equ_image = cv2.equalizeHist(image_gray)

plt.figure(figsize=(20,5), dpi=200)
plt.rcParams["font.family"] = "Times New Roman"
plt.subplots_adjust(wspace=0.03)

plt.subplot(1, 4, 1)
plt.imshow(cv2.cvtColor(image_gray, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.title('original image', fontsize=18)

plt.subplot(1, 4, 2)
plt.hist(image_gray.ravel(), 256, [0, 256])
plt.tick_params(labelbottom=False, labelleft=False, direction='in')
plt.axis('on')

plt.subplot(1, 4, 3)
plt.imshow(cv2.cvtColor(equ_image, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.title('equalized image', fontsize=18)

plt.subplot(1, 4, 4)
plt.hist(equ_image.ravel(), 256, [0, 256])
plt.tick_params(labelbottom=False, labelleft=False, direction='in')
plt.axis('on')

三. 直方图匹配

在有些应用中使用直方图均衡化是不合适的,有时候可以规定待处理图像的直方图形状是有用的。这种用于生成具有规定直方图的方法称为直方图匹配直方图规定化

假设连续灰度r和z,r和z分别是输入图像和输出图像的灰度级,其PDF函数是p_{r}(r)p_{z}(z)p_{z}(z)是规定化的PDF。

对于连续形式:

令s是一个具有如下性质的随机变量:s=T(r)=(L-1)\int_{0}^{r}p_{r}(w)dw

再定义一个关于变量z的函数G:G(z)=(L-1)\int_{0}^{z}p_{z}(u)du

所以:z=G^{-1}(s)=G^{-1}[T(r)]

得到具有规定PDF的图像步骤:

  1. 由输入图像得到p_{r}(r)
  2. G(z)=(L-1)\int_{0}^{z}p_{z}(u)du得到G(z)
  3. 计算反变换z=G^{-1}(s),s到z的映射;
  4. s=T(r)得到均匀化的输出图像;输出图像的像素值是s,对于均衡化后的图像中的像素值为s的每个像素执行逆变换z=G^{-1}(s),得到输出图像中的对应像素。使用这个变化后得到的PDF就是规定的PDF。

对于离散形式:

输入图像的变换:s_{k}=T(r_{k})=(L-1)\sum_{j=0}^{k}p_{r}(r_{j})

对于变量z:G(z_{q})=(L-1)\sum_{i=0}^{q}p_{z}(z_{i})

所以,由反变换得到规定化的:z_{q}=G^{-1}(s_{k})

对所有像素执行这些变换后得到的就是一个从s到z的一个映射。

def histogram_matching(source, template):
    source_hist, bins = np.histogram(source.flatten(), 256, [0, 256])
    template_hist, bins = np.histogram(template.flatten(), 256, [0, 256])
    # 计算累积分布函数(CDF)
    source_cdf = source_hist.cumsum()
    template_cdf = template_hist.cumsum()
    # 创建映射表
    mapping = np.zeros(256, dtype=np.uint8)
    template_cdf_idx = 0
    for source_cdf_idx in range(256):
        while template_cdf_idx < 256 and template_cdf[template_cdf_idx] < source_cdf[source_cdf_idx]:
            template_cdf_idx += 1
        mapping[source_cdf_idx] = template_cdf_idx
        
    matched = cv2.LUT(source, mapping)

    return matched

source_image = cv2.imread(r'D:\pythonwork\imagepro\data\Fig0011.tif', cv2.IMREAD_GRAYSCALE)
template_image = cv2.imread(r'D:\pythonwork\imagepro\data\Fig0014.tif', cv2.IMREAD_GRAYSCALE)

matched_image = histogram_matching(source_image, template_image)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值