# 前言

CSDN博客好久没有换过头像了，想换个新头像，在相册里面翻来翻去，然后就找到以前养的小宠物的一些照片，有一张特别有意思

。。。。感觉黑乎乎的，啥也看不清

# 处理

## 对比度拉伸

# 对比度拉伸
p1, p2 = np.percentile(img, (0, 70))  # numpy计算多维数组的任意百分比分位数
rescale_img = np.uint8((np.clip(img, p1, p2) - p1) / (p2 - p1) * 255)


## log变换

O

=

g

a

i

n

l

o

g

(

1

+

I

)

O = gain*log(1 + I)

O=gainlog(1+I)

# 对数变换
log_img = np.zeros_like(img)
scale, gain = 255, 1.5
for i in range(3):
log_img[:, :, i] = np.log(img[:, :, i] / scale + 1) * scale * gain


## Gamma校正

O

=

I

γ

g

a

i

n

O = I^{gamma} * gain

O=Iγgain

# gamma变换
gamma, gain, scale = 0.7, 1, 255
gamma_img = np.zeros_like(img)
for i in range(3):
gamma_img[:, :, i] = ((img[:, :, i] / scale) ** gamma) * scale * gain


## 直方图均衡化

# 直方图均衡化
equa_img = np.zeros_like(img)
for i in range(3):
equa_img[:, :, i] = cv.equalizeHist(img[:, :, i])


## 对比度自适应直方图均衡化(CLAHE)

OpenCV提供了该方法。

# 对比度自适应直方图均衡化
clahe_img = np.zeros_like(img)
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
for i in range(3):
clahe_img[:, :, i] = clahe.apply(img[:, :, i])


# 附源码

## opencv版本

import cv2.cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

def plot_img_and_hist(image, axes, bins=256):
"""Plot an image along with its histogram and cumulative histogram.

"""
ax_img, ax_hist = axes
ax_cdf = ax_hist.twinx()

# Display image
ax_img.imshow(image, cmap=plt.cm.gray)
ax_img.set_axis_off()

# Display histogram
colors = ['red', 'green', 'blue']
for i in range(1):
ax_hist.hist(image[:, :, i].ravel(), bins=bins, histtype='step', color=colors[i])

ax_hist.ticklabel_format(axis='y', style='scientific', scilimits=(0, 0))

ax_hist.set_xlabel('Pixel intensity')
ax_hist.set_xlim(0, 255)    # 这里范围为0~255 如果使用img_as_float，则这里为0~1
ax_hist.set_yticks([])

# Display cumulative distribution
for i in range(1):
hist, bins = np.histogram(image[:, :, i].flatten(), 256, [0, 256])
cdf = hist.cumsum()
cdf = cdf * float(hist.max()) / cdf.max()
ax_cdf.plot(bins[1:], cdf, 'k')
ax_cdf.set_yticks([])

return ax_img, ax_hist, ax_cdf

def plot_all(images, titles, cols):
"""
输入titles、images、以及每一行多少列，自动计算行数、并绘制图像和其直方图
:param images:
:param titles:
:param cols: 每一行多少列
:return:
"""
fig = plt.figure(figsize=(12, 8))
img_num = len(images)  # 图片的个数
rows = int(np.ceil(img_num / cols) * 2)  # 上图下直方图 所以一共显示img_num*2个子图
axes = np.zeros((rows, cols), dtype=object)
axes = axes.ravel()
axes[0] = fig.add_subplot(rows, cols, 1)  # 先定义第一个img 单独拿出来定义它是为了下面的sharex
# 开始创建所有的子窗口
for i in range(1, img_num):  #
axes[i + i // cols * cols] = fig.add_subplot(rows, cols, i + i // cols * cols + 1, sharex=axes[0],
sharey=axes[0])
for i in range(0, img_num):
axes[i + i // cols * cols + cols] = fig.add_subplot(rows, cols, i + i // cols * cols + cols + 1)

for i in range(0, img_num):  # 这里从1开始，因为第一个在上面已经绘制过了
ax_img, ax_hist, ax_cdf = plot_img_and_hist(images[i],
(axes[i + i // cols * cols], axes[i + i // cols * cols + cols]))
ax_img.set_title(titles[i])
y_min, y_max = ax_hist.get_ylim()
ax_hist.set_ylabel('Number of pixels')
ax_hist.set_yticks(np.linspace(0, y_max, 5))

ax_cdf.set_ylabel('Fraction of total intensity')
ax_cdf.set_yticks(np.linspace(0, 1, 5))

# prevent overlap of y-axis labels
fig.tight_layout()
plt.show()
plt.close(fig)

if __name__ == '__main__':
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)

gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 对比度拉伸
p1, p2 = np.percentile(img, (0, 70))  # numpy计算多维数组的任意百分比分位数
rescale_img = np.uint8((np.clip(img, p1, p2) - p1) / (p2 - p1) * 255)

# 对数变换
log_img = np.zeros_like(img)
scale, gain = 255, 1.5
for i in range(3):
log_img[:, :, i] = np.log(img[:, :, i] / scale + 1) * scale * gain

# gamma变换
gamma, gain, scale = 0.7, 1, 255
gamma_img = np.zeros_like(img)
for i in range(3):
gamma_img[:, :, i] = ((img[:, :, i] / scale) ** gamma) * scale * gain

# 彩色图直方图均衡化
# 直方图均衡化
equa_img = np.zeros_like(img)
for i in range(3):
equa_img[:, :, i] = cv.equalizeHist(img[:, :, i])
# 对比度自适应直方图均衡化
clahe_img = np.zeros_like(img)
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
for i in range(3):
clahe_img[:, :, i] = clahe.apply(img[:, :, i])

titles = ['img', 'rescale', 'log', 'gamma', 'equalizeHist', 'CLAHE']
images = [img, rescale_img, log_img, gamma_img, equa_img, clahe_img]
plot_all(images, titles, 3)



## skimage版本

from skimage import exposure, util, io, color, filters, morphology
import matplotlib.pyplot as plt
import numpy as np

def plot_img_and_hist(image, axes, bins=256):
"""Plot an image along with its histogram and cumulative histogram.

"""
image = util.img_as_float(image)
ax_img, ax_hist = axes
ax_cdf = ax_hist.twinx()

# Display image
ax_img.imshow(image, cmap=plt.cm.gray)
ax_img.set_axis_off()

# Display histogram
colors = ['red', 'green', 'blue']
for i in range(1):
ax_hist.hist(image[:, :, i].ravel(), bins=bins, histtype='step', color=colors[i])

ax_hist.ticklabel_format(axis='y', style='scientific', scilimits=(0, 0))
ax_hist.set_xlabel('Pixel intensity')
ax_hist.set_xlim(0, 1)
ax_hist.set_yticks([])

# Display cumulative distribution
for i in range(1):
img_cdf, bins = exposure.cumulative_distribution(image[:, :, i], bins)
ax_cdf.plot(bins, img_cdf, 'k')
ax_cdf.set_yticks([])

return ax_img, ax_hist, ax_cdf

def plot_all(images, titles, cols):
"""
输入titles、images、以及每一行多少列，自动计算行数、并绘制图像和其直方图
:param images:
:param titles:
:param cols: 每一行多少列
:return:
"""
fig = plt.figure(figsize=(12, 8))
img_num = len(images)  # 图片的个数
rows = int(np.ceil(img_num / cols) * 2)  # 上图下直方图 所以一共显示img_num*2个子图
axes = np.zeros((rows, cols), dtype=object)
axes = axes.ravel()
axes[0] = fig.add_subplot(rows, cols, 1)  # 先定义第一个img 单独拿出来定义它是为了下面的sharex
# 开始创建所有的子窗口
for i in range(1, img_num):  #
axes[i + i // cols * cols] = fig.add_subplot(rows, cols, i + i // cols * cols + 1, sharex=axes[0],
sharey=axes[0])
for i in range(0, img_num):
axes[i + i // cols * cols + cols] = fig.add_subplot(rows, cols, i + i // cols * cols + cols + 1)

for i in range(0, img_num):  # 这里从1开始，因为第一个在上面已经绘制过了
ax_img, ax_hist, ax_cdf = plot_img_and_hist(images[i],
(axes[i + i // cols * cols], axes[i + i // cols * cols + cols]))
ax_img.set_title(titles[i])
y_min, y_max = ax_hist.get_ylim()
ax_hist.set_ylabel('Number of pixels')
ax_hist.set_yticks(np.linspace(0, y_max, 5))

ax_cdf.set_ylabel('Fraction of total intensity')
ax_cdf.set_yticks(np.linspace(0, 1, 5))

# prevent overlap of y-axis labels
fig.tight_layout()
plt.show()
plt.close(fig)

if __name__ == '__main__':

gray = color.rgb2gray(img)
# 对比度拉伸
p1, p2 = np.percentile(img, (0, 70))  # numpy计算多维数组的任意百分比分位数
rescale_img = exposure.rescale_intensity(img, in_range=(p1, p2))

# 对数变换
# img = util.img_as_float(img)
log_img = np.zeros_like(img)
for i in range(3):
log_img[:, :, i] = exposure.adjust_log(img[:, :, i], 1.2, False)

# gamma变换
gamma_img = np.zeros_like(img)
for i in range(3):
gamma_img[:, :, i] = exposure.adjust_gamma(img[:, :, i], 0.7, 2)

# 彩色图直方图均衡化
equa_img = np.zeros_like(img, dtype=np.float64)  # 注意直方图均衡化输出值为float类型的
for i in range(3):
equa_img[:, :, i] = exposure.equalize_hist(img[:, :, i])

# 对比度自适应直方图均衡化
clahe_img = np.zeros_like(img, dtype=np.float64)
for i in range(3):
clahe_img[:, :, i] = exposure.equalize_adapthist(img[:, :, i])

# 局部直方图均衡化 效果不好就不放了
selem = morphology.rectangle(50, 50)
loc_img = np.zeros_like(img)
for i in range(3):
loc_img[:, :, i] = filters.rank.equalize(util.img_as_ubyte(img[:, :, i]), footprint=selem)

# Display results
titles = ['img', 'rescale', 'log', 'gamma', 'equalizeHist', 'CLAHE']
images = [img, rescale_img, log_img, gamma_img, equa_img, clahe_img]

plot_all(images, titles, 3)



THE END