Gonzalez R. C. and Woods R. E. Digital Image Processing (Forth Edition).

令\(r_k, k = 0, 1,2, \cdots, L-1\) 表示图片密度值为\(k\),

\[h(r_k) = n_k, \: k = 0, 1, \cdots, L-1,
\]

整个图片\(f(x, y)\)中密度值为\(r_k\)的pixel的数量, 定义概率

\[p(r_k) = \frac{h(r_k)}{MN} = \frac{n_k}{MN},
\]

其中\(M, N\)分别表示图片的高和宽(注意, 如果是多通道的图, 则应该\(CMN\)). 下图即为例子, 统计了\(r_k\)的分布.

HISTOGRAM EQUALIZATION

上面的四幅图, \(r_k\)呈现了不同的分布, 其中第四幅图, 拥有最佳的对比度, 可以发现其\(r_k\)的分布近似一个均匀分布, histogram equalization就是这样一种方法, 寻找一个变换

\[s = T(r), \quad 0 \le r \le L-1,
\]

使得\(s\)的分布近似满足一个均匀分布.

当然了, 这种分布显然不能破坏图片结构, 需要满足以下条件:

  1. \(T(r)\)在\(0\le r \le L-1\)熵是一个单调函数;
  2. \(0 \le T(r) \le L-1, \quad \forall 0 \le r \le L-1\).

我们首先把\(r\)看成连续的, 且假设\(p_r(r)\)是一个连续的密度函数, 则定义

\[s = T(r) = (L-1) \int_0^r p_r(w) \mathrm{d} w.
\]

显然\(\int_0^r p_r(w) \mathrm{d}w\)单调, 故\(T(r)\)也是单调的, 又\(0\le \int_0^r p_r(w) \mathrm{d}w \le 1\), 故第二个条件也是满足的.

既然\(u = \int_0^r p_r(w) \mathrm{d}w\)是满足均匀分布的随机变量(\([0, 1]\)), 故

\[s \sim U[0, L-1].
\]

即严格来说, 如果考虑连续的情况, 那么这种变换\(T\)一定能够得到我们所希望的最佳对比度.

将上述过程转换为离散的情况, 即

\[s_k = T(r_k) = (L - 1) \sum_{j=0}^k p_r (r_j), \: k=0,1,\cdots, L-1.
\]

为什么这种情况不能保证\(s_k\)满足均匀分布, 因为\(s_k\)可能是小数, 在图片中需要经过四舍五入操作, 就导致了不平衡.

代码示例

import cv2
import matplotlib.pyplot as plt
import numpy as np
# 加载图片
pollen = cv2.imread("./pics/pollen.png")
pollen.shape # (377, 376, 3) 由于是截的图, 所以是3通道的
pollen = cv2.cvtColor(pollen, cv2.COLOR_BGR2GRAY) # 先转成灰度图
pollen.shape # (377, 376)
plt.imshow(pollen, cmap='gray')

# 来看一下r的分布
hist = cv2.calcHist([pollen], [0], None, [256], (0, 255)).squeeze()
plt.bar(x=np.arange(256), height=hist)

# 自己的实现 img 是灰度图, 且 0, 1, ..., 255
def equalizeHist(img):
m, n = img.shape
hist = cv2.calcHist([img], [0], None, [256], (0, 255)).squeeze() / (m * n)
links = dict()
cum_sum = 0
for r in range(256):
cum_sum += hist[r]
links[r] = round(cum_sum * 255)
img2 = img.copy()
for i in range(m):
for j in range(n):
r = img[i, j].item()
img2[i, j] = links[r]
return np.array(img2)
pollen2 = equalizeHist(pollen)
plt.imshow(pollen2, cmap='gray')

hist = cv2.calcHist([pollen2], [0], None, [256], (0, 255)).squeeze()
plt.bar(x=np.arange(256), height=hist)

# cv2 官方实现
pollen3 = cv2.equalizeHist(pollen)
plt.imshow(pollen3, cmap='gray')

hist = cv2.calcHist([pollen3], [0], None, [256], (0, 255)).squeeze()
plt.bar(x=np.arange(256), height=hist)

HISTOGRAM MATCHING (SPECIFICATION)

正如上面所说的, equalize只在连续的情况下是能够保证转换后的分布是均匀的, 当离散的时候, 实际上, 当分布特别聚集的时候, 出现的分布会与均匀相差甚远. 如下面的月球的表面图, 由于其分布集中在0附近, 导致变换后的图形并不能够很好的增加对比度(虽然能看清点).

此时, 我们可以预先指定一个分布\(p_z\), 回顾:

\[s = T(r) = (L-1) \int_0^r p_r (w) \mathrm{d} w,
\]

我们将\(s \rightarrow z\):

\[s = G(z) = (L-1) \int_0^z p_z (v) \mathrm{d} v,
\]

\(T(r) = s =G(z)\), 既然在连续的情况下\(s\)是均匀的, 故

\[z = G^{-1} T(r),
\]

当然需要一个额外的假设\(G\)是可逆的. 如此, 我们变把\(r\)转换成了我们期待的分布\(z\).

那么在离散的情况下, 处理流程如下:

  1. 通过

    \[T(r_k), \: k = 0, 1, \cdots, L-1,
    \]

    建立字典

    \[d_{rs}=\{r_k:\mathrm{round}(T(r_k))\}.
    \]
  2. 通过

\[G(z_k), \: k = 0, 1, \cdots, L-1,
\]

对于每一个\(s_k\), 从\(z_j, j=0,1,\cdots, L-1\)中找到一个\(z_j\)使得\(G(z_j)\)与\(s_k\)最接近, 并建立字典

\[d_{sz} = \{s_k:z_j\}.
\]
  1. \(r \rightarrow z\):
\[z = d_{sz}[d_{rs}[r]].
\]

在实际中, 一般取原图\(r\)分布一个光滑近似, 如下图所示(个人觉得, 此处核密度函数估计大有可为):

其它

有些时候, 我们只需要对一部分的区域进行上述的处理, 就是LOCAL HISTOGRAM PROCESSING.

另外, 可以用一些统计信息来处理, 比如常见的矩

\[\mu_n = \sum_{i=0}^{L-1} (r_i-m)^n p(r_i), \\
m = \sum_{i=0}^{L-1}r_i p(r_i),
\]

这里\(m\)是均值. 常用的二阶矩, 方差:

\[\sigma^2 = \sum_{i=0}^{L-1} (r_i - m)^2 p(r_i),
\]

是图片对比度的一种衡量的手段.

对于以\((x, y)\)为中心的区域, 也可以各自定义其矩\(\mu_{S_{xy}}\). 下图就是通过区域的一阶矩和二阶矩的信息来让黑色部分的对比度增加.

Histogram Processing的更多相关文章

  1. 数字图像处理实验(16):PROJECT 06-03,Color Image Enhancement by Histogram Processing 标签: 图像处理MATLAB 2017

    实验要求: Objective: To know how to implement image enhancement for color images by histogram processing ...

  2. 【Duke-Image】Week_3 Spatial processing

    Chapter_3 Intensity Transsformations and Spatial Filtering 灰度变换与空间滤波 Intensity transformation functi ...

  3. 数字图像处理实验(总计23个)汇总 标签: 图像处理MATLAB 2017-05-31 10:30 175人阅读 评论(0)

    以下这些实验中的代码全部是我自己编写调试通过的,到此,最后进行一下汇总. 数字图像处理实验(1):PROJECT 02-01, Image Printing Program Based on Half ...

  4. [OpenCV] Image Processing - Grayscale Transform & Histogram

    颜色直方图 首先,先介绍一些Hist的基本使用. Ref:[OpenCV]数字图像灰度直方图 官方文档:https://docs.opencv.org/trunk/d8/dbc/tutorial_hi ...

  5. Digital Image Processing 学习笔记3

    第三章 灰度变换与空间滤波 3.1 背景知识 3.1.1 灰度变换和空间滤波基础 本章节所讨论的图像处理技术都是在空间域进行的.可以表示为下式: $$g(x, y) = T[f(x,y)]$$ 其中$ ...

  6. Linux command line exercises for NGS data processing

    by Umer Zeeshan Ijaz The purpose of this tutorial is to introduce students to the frequently used to ...

  7. CUDA Samples: Calculate Histogram(atomicAdd)

    以下CUDA sample是分别用C++和CUDA实现的计算一维直方图,并对其中使用到的CUDA函数进行了解说,code参考了<GPU高性能编程CUDA实战>一书的第九章,各个文件内容如下 ...

  8. Video processing systems and methods

    BACKGROUND The present invention relates to video processing systems. Advances in imaging technology ...

  9. Image Processing and Analysis_15_Image Registration:HAIRIS: A Method for Automatic Image Registration Through Histogram-Based Image Segmentation——2011

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

随机推荐

  1. 带你全面了解 OAuth2.0

    最开始接触 OAuth2.0 的时候,经常将它和 SSO单点登录搞混.后来因为工作需要,在项目中实现了一套SSO,通过对SSO的逐渐了解,也把它和OAuth2.0区分开了.所以当时自己也整理了一篇文章 ...

  2. Identity Server 4 从入门到落地(七)—— 控制台客户端

    前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...

  3. TCP中的TIME_WAIT状态

    TIME_WAIT的存在有两大理由 1.可靠地实现TCP全双工连接的终止 2.允许老的可重复分节在网络中消失. 对于理由1,我们知道TCP结束需要四次挥手,若最后一次的客户端的挥手ACK丢失(假设是客 ...

  4. KMP算法中的next函数

    原文链接:http://blog.csdn.net/joylnwang/article/details/6778316/ 其实后面大段的代码都可以不看 KMP的关键是next的产生 这里使用了中间变量 ...

  5. Simulating final class in C++

    Ever wondered how can you design a class in C++ which can't be inherited. Java and C# programming la ...

  6. linux 配置本地yum

    1.挂载光盘 #挂载光盘 mount /dev/cdrom /mnt/cdrom 2.修改yum.conf, 运行 vi /etc/yum.conf,文件替换成如下内容 [main] cachedir ...

  7. Java Log4j 配置文件

    ### 设置### log4j.rootLogger = debug,stdout,D,E ### 输出信息到控制抬 ### log4j.appender.stdout = org.apache.lo ...

  8. java中二维数组初始化的几种方法

    /* 第一种方式 */ int tdarr1[][] = { { 1, 3, 5 }, { 5, 9, 10 } }; /* 第二种方式 */ int tdarr2[][] = new int[][] ...

  9. 网络通信引擎ICE的使用

    ICE是一种网络通信引擎,在javaWeb的开发中可以用于解决局域网内部服务器端与客户端之间的网络通信问题.即可以在 1.在服务器和客户端都安装好ICE 2.服务器端(java)在java项目中引入I ...

  10. 因Console.Read()导致Centos 后台运行.net core程序报错

    .net 控制台程序通常用 Console.Read(),或者Console.ReadKey()让进程阻塞保持,不退出. 但在.net core 需要将程序放在后台执行时 用Console.Read( ...