在 Jupyter Notebook 里“代码能跑、图片却不出来”,多数时候不是 Notebook 本身有问题,而是显示方式和图像来源没对应上。下面按最常见的几种场景拆开讲:什么时候直接用 IPython.display.Image,什么时候该用 plt.imshow,以及图片不显示时该怎样快速判断是不是路径和权限问题。
直接显示图片文件:优先用 IPython.display.Image
如果你的目标只是把本地图片或网络图片显示在代码单元输出区,IPython.display.Image 通常是最省事也最稳定的办法。它不依赖额外图像处理流程,也不会走 matplotlib 的绘图逻辑,而是直接读取图片内容,转成 base64 后交给前端渲染。
这类方式适合两种情况:一是你手里已经有本地图片文件;二是你拿到的是可以直接访问的图片地址。出现问题时,常见表现通常是单元格里空白、报 FileNotFoundError,或者只显示一个损坏的图片图标。
- 路径应以当前 notebook 文件所在目录为参照,而不是简单按
os.getcwd()去猜。两者经常并不一致。 - 文件名里如果带中文、空格或特殊符号,例如
(1)、#,更容易导致加载失败,稳妥做法是改成英文和下划线命名。 - 使用
filename=时,文件必须真实存在且当前进程有读取权限;使用url=时,链接也必须可直连,某些需要登录或处于内网的地址无法正常渲染。 - 它支持
width和height调整尺寸,但不支持 CSS 样式。如果你还想加圆角、边框之类效果,就该换成%%html这类方式。
示例:
from IPython.display import Image Image(filename="data/cat.jpg", width=400)
已经拿到图像数据时,用 matplotlib.pyplot.imshow
如果你不是单纯展示文件,而是已经通过 cv2.imread、PIL.Image.open 或 np.array 把图像读进内存,那么更适合用 matplotlib.pyplot.imshow。这种方式尤其常见于图像预处理、数据分析和可视化调试流程里,因为你可以直接查看数组、PIL 对象或处理中间结果。

这时最常见的报错并不是“显示不出来”,而是“显示出来但颜色不对”。比如画面发紫、发绿、全黑、整片偏白,或者坐标轴把版面挤乱,多张图里最后只看到一张。
- OpenCV 读进来的默认是 BGR,而
plt.imshow按 RGB 解释颜色,所以需要先转换:cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB)。 - 灰度图只有单通道时,最好显式写上
cmap='gray',否则会套用默认伪彩色映射,结果和原图差很多。 - 如果只是看图,不看坐标,记得加上
plt.axis('off'),这样版面更干净,也不会浪费输出区域。 - 连续显示多张图时,每次都要配合
plt.show(),否则多个plt.imshow可能叠在同一个 figure 里,最后只渲染出最后一次结果。
示例:
import matplotlib.pyplot as plt
from PIL import Image
img = Image.open("data/dog.png")
plt.imshow(img)
plt.axis('off')
plt.show()
为什么不该用 img.show()
不少人第一次在 Notebook 里处理图片,会下意识调用 img.show()。这个方法在普通脚本里看起来很自然,但它并不会把图片嵌进 Jupyter 输出区域。
PIL.Image.show() 的实际行为,是调用操作系统默认的图片查看器,比如 macOS 的预览或 Windows 的照片应用。也就是说,它和 Jupyter 页面本身没有直接关系。你在 notebook 里运行后,可能会弹出一个系统窗口,也可能因为环境限制、权限、防火墙或无图形界面而静默失败。
如果代码执行没报错,但浏览器里什么都没看到,首先就该检查自己是不是误用了这个方法。
- 把所有
.show()调用去掉,换成display(img)或plt.imshow(...); plt.show()。 display()是 IPython 的通用输出函数,确实可以识别 PIL 图像对象。- 不过从表达清晰度来说,如果你本来就是展示图片文件,直接用
IPython.display.Image会更明确。 - 同时要注意,
display()不是 Python 内置函数,使用前需要先导入:from IPython.display import display。
图片不显示时,先排查路径和权限
实际排障里,最常见的问题并不是 API 选错,而是路径不对、文件不存在,或者当前环境没有读取权限。很多“方法失效”的反馈,最后都能归到这里。

与其反复改代码,不如先跑三行诊断,把最基本的事实确认清楚:
import os
path = "data/photo.jpg"
print("文件存在?", os.path.exists(path))
print("有读权限?", os.access(path, os.R_OK))
print("绝对路径是:", os.path.abspath(path))
这段输出可以快速告诉你三件事:文件到底在不在、当前进程能不能读,以及你写下的相对路径最终解析到了哪里。
如果第一行结果是 False,就不用继续怀疑显示函数了,说明路径本身就错了。此时应该回到 notebook 当前所在目录去核对,再确认图片是否真的放在对应的 data/ 子目录下。
还有几个细节也值得顺手检查:
- 不要默认认为
~或./会像命令行里那样自动展开,Jupyter 环境下这类写法不一定按你预期工作。 - 在 Windows 场景里,跨磁盘路径也容易出问题,比如从 D: 环境去访问 C: 上的文件时,路径判断往往更容易出错。
- 如果文件名本身混入了中文、空格或特殊字符,即便路径看起来没错,也可能在读取阶段失败。
该怎么选:按场景判断就够了
把几种方式放到一起看,其实判断标准很简单:
- 只是想把一张本地或网络图片稳稳显示出来,优先选
IPython.display.Image。 - 你手里已经是数组、OpenCV 结果或 PIL 对象,或者还要继续做图像分析,优先选
plt.imshow。 - 不要指望
img.show()在 Notebook 输出区生效,它调用的是系统查看器,不是 Jupyter 的渲染机制。 - 一旦图片没出来,先查路径、权限和文件名,再怀疑显示方法本身。
对大多数 Notebook 使用者来说,只要把这几个边界分清,图片显示问题基本都能在几分钟内定位清楚。









