3秒版本:
改成如下形式即可,去掉normed,改成density(布尔值),意思是开启概率分布(直方图面积为1).
plt.hist(hist_r, bins = 40, density=True,facecolor="red", edgecolor="black", alpha=0.7)
遇到的问题
今天在阅读《数字图像处理与python实现》一书中的图像直方图实验时,想绘制彩色图片三通道直方图,但是书中并没有给出源码。
只是给出了计算直方图的部分代码
# 计算直方图
hist_r = exposure.histogram(image[:, :, 0], nbins = 256)
hist_g = exposure.histogram(image[:, :, 1], nbins = 256)
hist_b = exposure.histogram(image[:, :, 2], nbins = 256)
然后在网上去搜寻三通道直方图的画法,还真找到了:python数字图像处理(9):直方图与均衡化
其中给出的方法是调用hist方法来绘制:
n, bins, patches = plt.hist(arr, bins=10, normed=0, facecolor='black',
edgecolor='black',alpha=1,histtype='bar')
然后就按照这种方式来做,结果就是报错:
AttributeError: 'Rectangle' object has no property 'normed'
尝试删除normed,可以运行,结果如下:得到并不是归一化的直方图,和书中给的可视化图形也并不一致。
用于测试的代码
from skimage import exposure, io, data
from matplotlib import pyplot as plt
import matplotlib
import numpy as np
# 设置matplotlib正常显示中文和负号
matplotlib.rcParams['font.sans-serif']=['SimHei'] # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus']=False # 正常显示负号
image = data.coffee()
# 计算直方图
hist_r = exposure.histogram(image[:, :, 0], nbins = 256)
hist_g = exposure.histogram(image[:, :, 1], nbins = 256)
hist_b = exposure.histogram(image[:, :, 2], nbins = 256)
plt.subplot(2, 2, 1)
plt.title("原图")
io.imshow(image)
# data = np.random.randn(10000)
plt.subplot(2, 2, 2)
plt.title("R通道颜色直方图")
plt.hist(hist_r, bins = 40, facecolor="red", edgecolor="black", alpha=0.7)
plt.subplot(2, 2, 3)
plt.title("G通道颜色直方图")
plt.hist(hist_g, bins = 40, facecolor="green", edgecolor="black", alpha=0.7)
plt.subplot(2, 2, 4)
plt.title("B通道颜色直方图")
plt.hist(hist_b, bins = 40, facecolor="blue", edgecolor="black", alpha=0.7)
plt.show()
解决方法
然后在stackoverflow和其他博文中翻阅了一下,最终还是打开了matplotlib 的开发文档
https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.hist.html#matplotlib.pyplot.hist
这个hist是在matplotlib.pyplot下的:
这是hist函数原型
matplotlib.pyplot.hist(x, bins=None, range=None, density=False, weights=None, cumulative=False, bottom=None, histtype=‘bar’, align=‘mid’, orientation=‘vertical’, rwidth=None, log=False, color=None, label=None, stacked=False, *, data=None, **kwargs)
其中关于density参数的解释
densitybool, default: False
If True, draw and return a probability density: each bin will display the bin’s raw count divided by the total number of counts and the bin width (density = counts / (sum(counts) * np.diff(bins))), so that the area under the histogram integrates to 1 (np.sum(density * np.diff(bins)) == 1).
If stacked is also True, the sum of the histograms is normalized to 1.
density是概率密度的开关,如果density=True,就是直方图归一化,面积加起来为1.
所以改成:
plt.hist(hist_r, bins = 40, density=True,facecolor="red", edgecolor="black", alpha=0.7)
代码
from skimage import data, io
import matplotlib
import matplotlib.pyplot as plt
# 设置matplotlib正常显示中文和负号
matplotlib.rcParams['font.sans-serif']=['SimHei'] # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus']=False # 正常显示负号
image=data.coffee()
# flatten 将矩阵降维一维
hist_r=image[:,:,0].flatten()
hist_g=image[:,:,1].flatten()
hist_b=image[:,:,2].flatten()
plt.subplot(2, 2, 1)
plt.title("原图")
io.imshow(image)
# data = np.random.randn(10000)
plt.subplot(2, 2, 2)
plt.title("R通道颜色直方图")
plt.hist(hist_r, bins = 40, density=True,facecolor="red", edgecolor="black", alpha=0.7)
plt.subplot(2, 2, 3)
plt.title("G通道颜色直方图")
plt.hist(hist_g, bins = 40, density=True,facecolor="green", edgecolor="black", alpha=0.7)
plt.subplot(2, 2, 4)
plt.title("B通道颜色直方图")
plt.hist(hist_b, bins = 40, density=True,facecolor="blue", edgecolor="black", alpha=0.7)
plt.show()
参考
[1]https://blog.csdn.net/qq_45069279/article/details/105636669
[2]https://blog.csdn.net/haoyu_xie/article/details/106814610
[3]https://matplotlib.org/stable/api/index.htmlmatplotlib参考API