在一个IPython Notebook单元中显示多个图像?


72

如果我有多个图像(作为NumPy数组加载),如何在一个IPython Notebook单元中显示?

我知道我可以plt.imshow(ima)用来显示一张图像……但是我想一次显示多个图像。

我试过了:

 for ima in images:
     display(Image(ima))

但是我只是得到了一个损坏的图像链接:

在此处输入图片说明


如果使用imshow选项,为什么不结合使用它subplots来创建图像数组?图像尺寸是否有很大差异?
2013年

我可以使用子图…但是当我只是在实验时,这变得很奇怪:我需要设置行和列的数量,然后如果行和列太多,则需要增加图形大小以确保它们分别大小合理,并且我需要等待整个图形渲染后才能看到单个图像(而不是生成图像时显示它们)
David Wolever 2013年

您是否使用python 3.3?并且有什么东西写到控制台了吗?
雅各布

不-这是Py2.7。你是什​​么意思,“是写东西到控制台了吗?” 你是说我去的时候display(Image(…))吗?在这种情况下,图像看起来像一样src="data:np.array([…])"
David Wolever,2013年

Answers:


104

简短答案:

plt.figure()如果要在一个单元格中添加多个图形,请致电以创建新图形:

for ima in images:
    plt.figure()
    plt.imshow(ima)

但为了澄清与以下内容的混淆Image

IPython.display.Image用于显示图像文件,而不是数组数据。如果要使用Image显示numpy数组,则必须先将其转换为文件格式(使用PIL最简单):

from io import BytesIO
import PIL
from IPython.display import display, Image

def display_img_array(ima):
    im = PIL.Image.fromarray(ima)
    bio = BytesIO()
    im.save(bio, format='png')
    display(Image(bio.getvalue(), format='png'))

for ima in images:
    display_img_array(ima)

说明这两种方法的笔记本


2
链接的笔记本的细微之处:%matplotlib inline如果要显示图像,则需要这样做。
布伦特·布拉德本

3
是否有很好的解释说明为什么我必须plt.figure()在每个图像之前?
Selam Getachew

有没有办法避免将图像发送到磁盘?我有一堆被操纵多次在内存中的图像-在内存中
StephenBoesch

85

这更容易且有效:

from IPython.display import Image
from IPython.display import display
x = Image(filename='1.png') 
y = Image(filename='2.png') 
display(x, y)

2
正是我需要的-我没有使用numpy数组或实际图,我只显示了.png,这很完美。谢谢!
dwanderson

12
这应该是公认的答案。如果您有一系列图像,则可以使用:display(*images)
Claude

我喜欢这个,但是它显示的图像比更大plt.imshow()似乎无法控制大小
汤姆·黑尔

71

水平布局

水平布局演示

简短答案

plt.figure(figsize=(20,10))
columns = 5
for i, image in enumerate(images):
    plt.subplot(len(images) / columns + 1, columns, i + 1)
    plt.imshow(image)

长答案

import glob
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline

images = []
for img_path in glob.glob('images/*.jpg'):
    images.append(mpimg.imread(img_path))

plt.figure(figsize=(20,10))
columns = 5
for i, image in enumerate(images):
    plt.subplot(len(images) / columns + 1, columns, i + 1)
    plt.imshow(image)

5
这是一个很棒且更有用的答案!
carlossierra

2
这是枚举多个数字的好方法
Gang Su

16

您可以使用显示和HTML函数在一个IPython Notebook单元中显示多个图像。您需要按如下所示将一组html img标签创建为字符串

from IPython.display import Image, HTML, display
from glob import glob
imagesList=''.join( ["<img style='width: 120px; margin: 0px; float: left; border: 1px solid black;' src='%s' />" % str(s) 
                 for s in sorted(glob('yourimage*.png')) ])
display(HTML(imagesList))

请参阅http://nbviewer.ipython.org/github/PBrockmann/Dodecahedron中的使用示例

如果从前一个单元格中更改了新图像,则可能需要刷新浏览器(Shift +加载)以查看新图像。


是否可以某种方式将此渲染保存到文件?
Abhijat Biswas's

7

您可以使用IPyPlot真正快速轻松地做到这一点

import ipyplot

ipyplot.plot_images(images_array, max_images=20, img_width=150)

您将获得类似于以下内容的图:
在此处输入图片说明

它正在使用中IPython.displayHTML可以采用以下格式拍摄图像:

  • string 文件路径
  • PIL.Image 对象
  • numpy.ndarray 代表图像的对象

显示numpy array500张图像仅需几秒钟


3

如果您不介意其他依赖项,则可以使用scikit-image来实现两个衬里:

from skimage.util import montage
plt.imshow(montage(np.array(images), multichannel=True))

设置multichannel=True为彩色图像和multichannel=False灰度图像。


2

以某种方式与此问题相关(并且由于在尝试解决该问题时将我定向到该答案),因此我可以通过在调用时简单地键入完整的文件路径来解决类似的问题Image()。就我而言,我必须从列表中存储的不同文件夹路径中选择一个随机图像your_folder并显示它们。

import random, os 
for i in range(len(your_folder)):
   ra1 = "../"+your_folder[i]+"/"+random.choice(os.listdir(your_folder[i]))
   image = Image(ra1)
   display(image)

1
您应该以与操作系统无关的方式使用os.path.joinpathlib.Path组装路径。
时髦的未来,

2

在此处输入图片说明

from matplotlib.pyplot import figure, imshow, axis
from matplotlib.image import imread

mypath='.'
hSize = 5
wSize = 5
col = 4

def showImagesMatrix(list_of_files, col=10):
    fig = figure( figsize=(wSize, hSize))
    number_of_files = len(list_of_files)
    row = number_of_files/col
    if (number_of_files%col != 0):
        row += 1
    for i in range(number_of_files):
        a=fig.add_subplot(row,col,i+1)
        image = imread(mypath+'/'+list_of_files[i])
        imshow(image,cmap='Greys_r')
        axis('off')

showImagesMatrix(listOfImages,col)

根据@Michael回答


0

基于@ChaosPredictor答案

from matplotlib.pyplot import figure, imshow, axis
from matplotlib.image import imread

def showImagesMatrix(list_of_files, col=10, wSize=5, hSize=5, mypath='.'):
    fig = figure(figsize=(wSize, hSize))
    number_of_files = len(list_of_files)
    row = number_of_files / col
    if (number_of_files % col != 0):
        row += 1
    for i in range(number_of_files):
        a=fig.add_subplot(row, col, i + 1)
        image = imread(mypath + '/' + list_of_files[i])
        imshow(image, cmap='Greys_r')
        axis('off')

然后

from pathlib import Path
p = Path('.')
num_images = 30
list_of_image_paths = [str(x) for x in list(p.glob('../input/train/images/*'))[:num_images]]

showImagesMatrix(list_of_image_paths)

# or with named args
showImagesMatrix(list_of_image_paths, wSize=20, hSize=10, col=5)

matplotlib图像网格


0

该线程中的答案对我有所帮助:使用Python水平合并多个图像

使用matplotlib的问题是所显示图像的定义确实不好。我根据自己的需要调整了答案之一:

以下代码显示在jupyter笔记本中水平并置的图像。请注意带有注释的代码行,以保存图像(如果需要)。

import numpy as np
import PIL
from IPython.display import display

list_im = ['Test1.jpg', 'Test2.jpg', 'Test3.jpg']
imgs    = [ PIL.Image.open(i) for i in list_im ]
# pick the image which is the smallest, and resize the others to match it (can be arbitrary image shape here)
min_shape = sorted( [(np.sum(i.size), i.size ) for i in imgs])[0][1]
imgs_comb = np.hstack( (np.asarray( i.resize(min_shape) ) for i in imgs ) )

# save that beautiful picture
imgs_comb = PIL.Image.fromarray( imgs_comb)
#imgs_comb.save( 'combo.jpg' )    

display(imgs_comb)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.