欢迎关注 “小白玩转Python”,发现更多 “有趣”
引言
在昨天的文章中我们介绍了基于灰度图像的直方图处理,也简单的提到了彩色图像的直方图处理,但是没有讨论最好的方法。
让我们从导入所有需要的库开始吧!
-
import numpy
as np
-
import matplotlib.pyplot
as plt
-
from skimage.io
import imread, imshow
-
import matplotlib.pyplot
as plt
-
from skimage.exposure
import histogram, cumulative_distribution
-
from scipy.stats
import norm
现在让我们载入图像。
-
dark_image = imread('dark_books.png');
-
plt.figure(num=None, figsize=(8, 6), dpi=80)
-
imshow(dark_image);
为了帮助我们更好地了解此图像中的 RGB 图层,让我们隔离每个单独的通道。
-
def rgb_splitter(image):
-
rgb_list = [
'Reds',
'Greens',
'Blues']
-
fig, ax = plt.subplots(
1,
3, figsize=(
17,
7), sharey =
True)
-
for i
in range(
3):
-
ax[i].imshow(image[:,:,i], cmap = rgb_list[i])
-
ax[i].set_title(rgb_list[i], fontsize =
22)
-
ax[i].axis(
'off')
-
fig.tight_layout()
-
rgb_splitter(dark_image)
现在我们已经对单个颜色通道有了大致的了解,现在查看它们的CDF。
-
def df_plotter(image):
-
freq_bins = [cumulative_distribution(image[:,:,i])
for i
in
-
range(
3)]
-
target_bins = np.arange(
255)
-
target_freq = np.linspace(
0,
1, len(target_bins))
-
names = [
'Red',
'Green',
'Blue']
-
line_color = [
'red',
'green',
'blue']
-
f_size =
20
-
-
fig, ax = plt.subplots(
1,
3, figsize=(
17,
5))
-
for n, ax
in enumerate(ax.flatten()):
-
ax.set_title(
f'{names[n]}', fontsize = f_size)
-
ax.step(freq_bins[n][
1], freq_bins[n][
0], c=line_color[n],
-
label=
'Actual CDF')
-
ax.plot(target_bins,
-
target_freq,
-
c=
'gray',
-
label=
'Target CDF',
-
linestyle =
'--')
-
df_plotter(dark_image)
正如我们所看到的,这三个通道都离理想化的直线相当远。为了解决这个问题,让我们简单地对其CDF进行插值。
-
def rgb_adjuster_lin(image):
-
-
target_bins = np.arange(
255)
-
target_freq = np.linspace(
0,
1, len(target_bins))
-
freq_bins = [cumulative_distribution(image[
:,
:,i])
for i
in
-
range(
3)]
-
names = [
'Reds',
'Blues',
'Greens']
-
line_color = [
'red',
'green',
'blue']
-
adjusted_figures = []
-
f_size =
20
-
-
fig, ax = plt.subplots(
1,
3, figsize=[
15,
5])
-
for n, ax
in enumerate(ax.flatten()):
-
interpolation = np.interp(freq_bins[n][
0], target_freq,
-
target_bins)
-
adjusted_image = img_as_ubyte(interpolation[image[
:,
:,
-
n]].astype(int))
-
ax.set_title(f
'{names[n]}', fontsize = f_size)
-
ax.imshow(adjusted_image, cmap = names[n])
-
adjusted_figures.append([adjusted_image])
-
fig.tight_layout()
-
fig, ax = plt.subplots(
1,
3, figsize=[
15,
5])
-
for n, ax
in enumerate(ax.flatten()):
-
interpolation = np.interp(freq_bins[n][
0], target_freq,
-
target_bins)
-
adjusted_image = img_as_ubyte(interpolation[image[
:,
:,
-
n]].astype(int))
-
freq_adj, bins_adj = cumulative_distribution(adjusted_image)
-
-
ax.set_title(f
'{names[n]}', fontsize = f_size)
-
ax.step(bins_adj, freq_adj, c=line_color[n], label=
'Actual
-
CDF')
-
ax.plot(target_bins,
-
target_freq,
-
c=
'gray',
-
label=
'Target CDF',
-
linestyle =
'--')
-
fig.tight_layout()
-
return adjusted_figures
-
channel_figures =
return adjusted_figures
我们看到每个颜色通道都有显着改善。
此外,请注意上面的函数是如何将所有这些值作为列表返回。这将为我们的最后一步提供很好的帮助,将所有这些重新组合成一张图片。为了让我们更好地了解如何做到这一点,让我们检查一下我们的列表。
-
print(channel_figures)
-
print(
f'Total Inner Lists : {len(channel_figures)}')
我们看到在变量channel_figures中有三个列表。这些列表代表RGB通道的值。在下面,我们可以将所有这些值重新组合在一起。
-
plt.figure(num=None, figsize=(10, 8), dpi=80)
-
imshow(np.dstack((channel
_figures[0][0],
-
channel_figures[
1][
0],
-
channel_figures[2][0])));
-
请注意图像处理前后这种差异是多么显著。图像不仅明亮了许多,黄色的阴影也被移除了。让我们在不同的图像上进行同样的处理试试。
-
dark_street = imread('dark_street.png');
-
plt.figure(num=None, figsize=(8, 6), dpi=80)
-
imshow(dark_street);
现在我们已经加载了新的图片,让我们简单地通过函数来处理。
channel_figures_street = adjusted_image_data = rgb_adjuster_lin(dark_street)
-
plt.figure(num=None, figsize=(10, 8), dpi=80)
-
imshow(np.dstack((channel
_figures_street [
0][
0],
-
channel_figures_street [1][0],
-
channel_figures_street [2][0])));
-
我们可以看到惊人的变化。不可否认,这张照片曝光有点过度。这可能是因为后面有明显的霓虹灯。在以后的文章中,我们将学习如何微调我们的方法,以使我们的函数更加通用。
总结
在本文中,我们学习了如何调整每个RGB通道以保留图像的颜色信息。这种技术是对以前的灰度调整方法的重大改进。
· END ·
HAPPY LIFE
转载:https://blog.csdn.net/weixin_38739735/article/details/111829448
查看评论