使用 plt.plot v/s plt.hist [Python] 的彩色图像的直方图差异
Difference in histograms of a colored image using plt.plot v/s plt.hist [Python]
我使用下面的代码使用 2 种方法生成彩色图像的直方图:
方法一:-
- 使用cv2.calcHist()函数计算频率
- 使用plt.plot() 生成频率线图
方法二:-
- 使用plt.hist()函数计算生成直方图(我加了bin=250,这样2个直方图是一致的)
观察: 两个直方图大致相似。第一个直方图(使用 plt.plot)看起来很平滑。然而,第二个直方图(使用 plt.hist)有额外的尖峰和下降。
问题: 由于图像只有 int 值,因此不应该出现不一致的合并。 histogram-2 中出现这些额外尖峰和下降的原因是什么?
blue_bricks = cv2.imread('Computer-Vision-with-Python/DATA/bricks.jpg')
fig = plt.figure(figsize=(17,10))
color = ['b','g','r']
# Histogram Type-1
fig.add_subplot(2,2,1)
for i,c in enumerate(color):
hist = cv2.calcHist([blue_bricks], mask=None, channels=[i], histSize=[256], ranges=[0,256])
plt.plot(hist,color=c)
plt.title('Histogram-1')
# Histogram Type-2
fig.add_subplot(2,2,2)
for i,c in enumerate(color):
plt.hist(blue_bricks[:,:,i].flatten(),color=c, alpha=0.5, bins=250)
plt.title('Histogram-2')
bins=250
在最低值和最高值之间创建 251 个等距的 bin 边缘。这些与离散值不一致。当 highest 和 lowest 之间的差异大于 250 时,一些 bins 将是空的。当差异小于 250 时,一些 bin 将获得两个相邻数字的值,从而产生尖峰。此外,在叠加直方图时,所有直方图使用完全相同的 bin 边缘也很方便。
您需要 bin 恰好位于整数值之间,设置 bins=np.arange(-0.5, 256, 1)
即可实现。或者,您可以使用 seaborn 的 histplot(...., discrete=True)
.
下面是一些数字较小的代码来说明发生了什么。
import matplotlib.pyplot as plt
import numpy as np
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, figsize=(12, 3))
for ax in (ax1, ax2, ax3, ax4):
if ax in [ax1, ax3]:
x = np.arange(1, 10)
else:
x = np.arange(1, 12)
if ax in [ax1, ax2]:
bins = 10
else:
bins = np.arange(0.5, x.max() + 1, 1)
_, bin_edges, _ = ax.hist(x, bins=bins, ec='white', lw=2)
ax.vlines(bin_edges, 0, 2.5, color='crimson', ls='--')
ax.scatter(x, [2.2] * len(x), color='lime', s=50)
ax.set_title((f"{bins} bins" if type(bins) == int else "discrete bins") + f', {len(x)} values')
ax.set_xticks(x)
ax.set_yticks([0, 1, 2])
plt.tight_layout()
plt.show()
我使用下面的代码使用 2 种方法生成彩色图像的直方图:
方法一:-
- 使用cv2.calcHist()函数计算频率
- 使用plt.plot() 生成频率线图
方法二:-
- 使用plt.hist()函数计算生成直方图(我加了bin=250,这样2个直方图是一致的)
观察: 两个直方图大致相似。第一个直方图(使用 plt.plot)看起来很平滑。然而,第二个直方图(使用 plt.hist)有额外的尖峰和下降。
问题: 由于图像只有 int 值,因此不应该出现不一致的合并。 histogram-2 中出现这些额外尖峰和下降的原因是什么?
blue_bricks = cv2.imread('Computer-Vision-with-Python/DATA/bricks.jpg')
fig = plt.figure(figsize=(17,10))
color = ['b','g','r']
# Histogram Type-1
fig.add_subplot(2,2,1)
for i,c in enumerate(color):
hist = cv2.calcHist([blue_bricks], mask=None, channels=[i], histSize=[256], ranges=[0,256])
plt.plot(hist,color=c)
plt.title('Histogram-1')
# Histogram Type-2
fig.add_subplot(2,2,2)
for i,c in enumerate(color):
plt.hist(blue_bricks[:,:,i].flatten(),color=c, alpha=0.5, bins=250)
plt.title('Histogram-2')
bins=250
在最低值和最高值之间创建 251 个等距的 bin 边缘。这些与离散值不一致。当 highest 和 lowest 之间的差异大于 250 时,一些 bins 将是空的。当差异小于 250 时,一些 bin 将获得两个相邻数字的值,从而产生尖峰。此外,在叠加直方图时,所有直方图使用完全相同的 bin 边缘也很方便。
您需要 bin 恰好位于整数值之间,设置 bins=np.arange(-0.5, 256, 1)
即可实现。或者,您可以使用 seaborn 的 histplot(...., discrete=True)
.
下面是一些数字较小的代码来说明发生了什么。
import matplotlib.pyplot as plt
import numpy as np
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, figsize=(12, 3))
for ax in (ax1, ax2, ax3, ax4):
if ax in [ax1, ax3]:
x = np.arange(1, 10)
else:
x = np.arange(1, 12)
if ax in [ax1, ax2]:
bins = 10
else:
bins = np.arange(0.5, x.max() + 1, 1)
_, bin_edges, _ = ax.hist(x, bins=bins, ec='white', lw=2)
ax.vlines(bin_edges, 0, 2.5, color='crimson', ls='--')
ax.scatter(x, [2.2] * len(x), color='lime', s=50)
ax.set_title((f"{bins} bins" if type(bins) == int else "discrete bins") + f', {len(x)} values')
ax.set_xticks(x)
ax.set_yticks([0, 1, 2])
plt.tight_layout()
plt.show()