【问题标题】:Display multiple images in one IPython Notebook cell?在一个 IPython Notebook 单元格中显示多个图像?
【发布时间】:2013-10-28 14:30:59
【问题描述】:

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

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

我试过了:

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

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

【问题讨论】:

  • 如果使用imshow 是一种选择,为什么不将它与subplots 结合使用来创建图像数组?图片大小变化很大吗?
  • 我可以使用子图……但是当我只是在试验时,这会变得很繁琐:我需要设置行数和列数,然后如果行数和列数太多,我需要增加数字大小以确保它们每个都具有合理的大小,并且我需要等待整个图形渲染才能看到各个图像(而不是在生成时显示它们)
  • 你使用python 3.3吗?是否有东西写入控制台?
  • 不 - 这是 Py2.7。你是什​​么意思,“是写到控制台的东西”?你的意思是当我去display(Image(…)) 的时候?在这种情况下,图像看起来像src="data:np.array([…])"

标签: ipython ipython-notebook


【解决方案1】:

简答:

如果您想在一个单元格中创建多个图形,请致电 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)

notebook 说明了这两种方法。

【讨论】:

  • 链接笔记本的微妙之处:如果你想显示图像,你需要做%matplotlib inline
  • 有什么好的解释为什么我必须在每张图片之前plt.figure()
  • 有没有办法避免将图像发送到磁盘?我确实有一堆被多次操作的内存图像 - 在内存中
【解决方案2】:

这更容易且有效:

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

【讨论】:

  • 正是我所需要的——我没有使用 numpy 数组或实际绘图,我只是要显示 .pngs,这非常完美。谢谢!
  • 这应该是公认的答案。如果您有一组图像,则可以使用:display(*images)
  • 我喜欢这个,但它显示的图像比plt.imshow() 大得多。 It does't seem possible to control the size.
【解决方案3】:

水平布局

简答

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)

【讨论】:

  • 这是一个很棒且更有用的答案!
  • 这是枚举多个数字的好方法
【解决方案4】:

您可以使用 display 和 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 + load)才能看到新的图片 从上一个单元格更改。

【讨论】:

  • 能否以某种方式将此渲染保存到文件中?
【解决方案5】:

您可以使用IPyPlot 快速轻松地完成它:

import ipyplot

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

你会得到一个类似这样的情节:

它在后台使用IPython.displayHTML,它可以拍摄以下格式的图像:

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

显示 500 张图片的 numpy array 只需几秒钟

【讨论】:

    【解决方案6】:

    如果您不介意额外的依赖,这里有一个使用scikit-image 的两行代码:

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

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

    【讨论】:

      【解决方案7】:

      不知何故与这个问题有关(因为当我试图解决这个问题时,我被引导到这个答案),我能够通过在调用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)
      

      【讨论】:

      • 您应该使用os.path.joinpathlib.Path 以与操作系统无关的方式组装路径。
      【解决方案8】:

      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 的回答

      【讨论】:

        【解决方案9】:

        这个问题被问到现在已经有几年了,但很遗憾这个功能还没有进入 jupyter notebooks 的核心。

        我希望imshow 函数足够简单

        • 接受单个或多个图像作为输入
        • 即使有 100 张图片,也可以为我整齐地布置它们

        看起来像:

        imshow(img)
        imshow(img1, img2)
        imshow(*imgs[:100])
        

        一些不错的可选参数:

        • 标题
        • 尺寸
        • 行和/或列
        • cmap

        不幸的是,该功能不属于笔记本的一部分。希望将来会在那里。现在,我在imshowtools 包中实现了确切的函数imshow。它在后台使用 matplotlib。

        假设您已使用 MNIST 和 imshow 加载

        from imshowtools import imshow
        import tensorflow as tf
        
        (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
        

        那么你可以简单地使用

        imshow(x_train[0])
        imshow(x_train[0], x_train[1], x_train[2])
        imshow(*x_train[:20], cmap='binary')
        imshow(*x_train[:100], cmap='binary', size=(10, 10))
        

        有时,您希望它们在一行或一列中:

        imshow(*x_train[:15], cmap='Purples', rows=1)
        imshow(*x_train[:24], cmap='Greens', columns=4)
        

        【讨论】:

          【解决方案10】:

          基于@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)
          

          【讨论】:

            【解决方案11】:

            这个帖子中的答案帮助了我:Combine several images horizontally with 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)
            

            【讨论】:

              【解决方案12】:

              今天,我在 google Colab 和 jupyter notebook 中遇到了这个问题,我将在 MNIST 数据集上分享一个简单的解决方案:

              for index in range(1,6):
                  plt.imshow(train_set.dataset[index], cmap='gray')
              

              输出只显示最后一张图片:

              因为两个 IDE 中的单元格只显示最后一个图像。因此我添加了plt.show() 来解决这个问题:

              for index in range(1,6):
                  plt.imshow(train_set.dataset[index], cmap='gray')
                  plt.show()
              

              输出:

              最后评论:我喜欢这种方式,因为我可以在循环中一起添加input() and plot() functions,这与我尝试过的其他方法不同。

              【讨论】:

                猜你喜欢
                • 2013-04-29
                • 2016-03-27
                • 1970-01-01
                • 2012-10-16
                • 1970-01-01
                • 2020-01-17
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多