简介
本实验将演示如何在 Matplotlib 中使用 RangeSlider 小部件来控制图像的阈值处理。阈值处理的目的是将灰度图像转换为二值图像,其中像素要么是黑色,要么是白色。这对于图像分割很有用,我们希望从图像中提取某些特征。
虚拟机提示
虚拟机启动完成后,点击左上角切换到笔记本标签,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,可以随时向 Labby 提问。课程结束后提供反馈,我们会及时为你解决问题。
生成一张虚拟图像
首先,我们将使用 NumPy 的随机模块生成一张虚拟灰度图像。我们将设置种子以确保结果可重现。
np.random.seed(19680801)
N = 128
img = np.random.randn(N, N)
显示图像及其直方图
接下来,我们将使用 Matplotlib 的imshow函数显示图像,并使用hist显示其直方图。我们将创建一个包含两个子图的图形,一个用于显示图像,另一个用于显示直方图。
fig, axs = plt.subplots(1, 2, figsize=(10, 5))
fig.subplots_adjust(bottom=0.25)
im = axs[0].imshow(img)
axs[1].hist(img.flatten(), bins='auto')
axs[1].set_title('Histogram of pixel intensities')
创建范围滑块
现在我们将创建范围滑块(RangeSlider)小部件,它将允许我们调整图像的阈值。我们将为滑块创建一个新的轴,并将其添加到图形中。
slider_ax = fig.add_axes([0.20, 0.1, 0.60, 0.03])
slider = RangeSlider(slider_ax, "Threshold", img.min(), img.max())
在直方图中添加垂直线
为了更便于观察阈值处理的效果,我们将在直方图中添加垂直线,以指示当前的阈值。我们将分别为下限和上限阈值创建两条线。
lower_limit_line = axs[1].axvline(slider.val[0], color='k')
upper_limit_line = axs[1].axvline(slider.val[1], color='k')
为滑块创建一个回调函数
我们将创建一个回调函数,每当用户使用滑块更改阈值时,该函数就会被调用。该函数将更新图像的颜色映射以及直方图上垂直线的位置。
def update(val):
## 由 RangeSlider 传递给回调的 val
## 将是一个 (min, max) 元组
## 更新图像的颜色映射
im.norm.vmin = val[0]
im.norm.vmax = val[1]
## 更新垂直线的位置
lower_limit_line.set_xdata([val[0], val[0]])
upper_limit_line.set_xdata([val[1], val[1]])
## 重绘图形以确保更新
fig.canvas.draw_idle()
slider.on_changed(update)
显示图形
最后,我们将显示包含图像和滑块的图形。
plt.show()
总结
在本实验中,我们展示了如何在 Matplotlib 中使用范围滑块(RangeSlider)小部件来控制图像的阈值处理。我们展示了如何创建一个伪灰度图像、显示该图像及其直方图、创建一个滑块来调整阈值,并根据滑块值更新图像和直方图。此技术可用于图像分割以及其他需要从图像中提取特定特征的应用。