本文共 10898 字,大约阅读时间需要 36 分钟。
這個錯誤是在使用PIL及matplotlib來讀圖(.jpg檔)的時候發生的。
以下是讀圖時所使用的指令:
from PIL import ImageImage.open('xxx.jpg')
及:
import matplotlib.pyplot as pltplt.imread('xxx.jpg')
這個錯誤只有在讀某個特定的圖檔時才會發生。
但是後來去檢查圖片,卻發現可以用一般的圖片瀏覽器打開,並且看不出什麼問題。使用PIL讀圖時報的錯:
OSErrorTraceback (most recent call last)
<ipython-input-4-ac0decf8a181> in <module>() ----> 1 Image.open(’./images/aireplane/21.jpg’) /usr/local/lib/python3.5/dist-packages/PIL/Image.py in open(fp, mode) 2517 fp.close() 2518 raise IOError(“cannot identify image file %r” -> 2519 % (filename if filename else fp)) 2520 2521 # OSError: cannot identify image file ‘./images/aireplane/21.jpg’
使用matplotlib讀圖時報的錯:
OSErrorTraceback (most recent call last)
<ipython-input-3-62fde97010d1> in <module>() ----> 1 im=plt.imread(’./images/aireplane/21.jpg’)/usr/local/lib/python3.5/dist-packages/matplotlib/pyplot.py in imread(*args, **kwargs)
2312 @docstring.copy_dedent(_imread) 2313 def imread(*args, **kwargs): -> 2314 return _imread(*args, **kwargs) 2315 2316/usr/local/lib/python3.5/dist-packages/matplotlib/image.py in imread(fname, format)
1276 1277 if ext not in handlers: -> 1278 im = pilread(fname) 1279 if im is None: 1280 raise ValueError('Only know how to handle extensions: %s; ’/usr/local/lib/python3.5/dist-packages/matplotlib/image.py in pilread(fname)
1254 except ImportError: 1255 return None -> 1256 with Image.open(fname) as image: 1257 return pil_to_array(image) 1258/usr/local/lib/python3.5/dist-packages/PIL/Image.py in open(fp, mode)
2517 fp.close() 2518 raise IOError(“cannot identify image file %r” -> 2519 % (filename if filename else fp)) 2520 2521 #OSError: cannot identify image file ‘./images/aireplane/21.jpg’
問題的解決方法是筆者不經意發現的。
因為PIL跟matplotlib都無法讀圖,所以想安裝其它的包試試看。
一開始試了opencv-python,安裝完成後,發現使用:import cv2cv2.imread('xxx.jpg')
可以成功讀圖。
後來試了scikit-image,安裝完成後,使用:
import skimageskimage.io.imread('xxx.jpg')
也可以成功讀圖。
skimage安裝完成後,筆者嘗試使用PIL跟matplotlib再次讀圖,發現竟然都成功了!
後來回去看skimage安裝的log:
Collecting scikit-image
Downloading (25.2MB) 100% |################################| 25.2MB 67kB/s eta 0:00:011 15% |#### | 3.9MB 842kB/s eta 0:00:26 Requirement already satisfied: matplotlib>=2.0.0 in /usr/local/lib/python3.5/dist-packages (from scikit-image) Collecting PyWavelets>=0.4.0 (from scikit-image) Downloading (4.4MB) 100% |################################| 4.4MB 268kB/s ta 0:00:011 Collecting pillow>=4.3.0 (from scikit-image) Downloading (2.0MB) 100% |################################| 2.0MB 392kB/s ta 0:00:011 Requirement already satisfied: scipy>=0.17.0 in /usr/local/lib/python3.5/dist-packages (from scikit-image) Collecting cloudpickle>=0.2.1 (from scikit-image) Downloading Collecting dask[array]>=0.9.0 (from scikit-image) Downloading (685kB) 100% |################################| 686kB 612kB/s ta 0:00:011 26% |######## | 184kB 576kB/s eta 0:00:01 Collecting networkx>=1.8 (from scikit-image) Downloading (1.7MB) 100% |################################| 1.7MB 391kB/s ta 0:00:011 47% |############### | 808kB 31.1MB/s eta 0:00:01 Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.5/dist-packages (from scikit-image) Requirement already satisfied: pytz in /usr/local/lib/python3.5/dist-packages (from matplotlib>=2.0.0->scikit-image) Requirement already satisfied: numpy>=1.7.1 in /usr/local/lib/python3.5/dist-packages (from matplotlib>=2.0.0->scikit-image) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.5/dist-packages (from matplotlib>=2.0.0->scikit-image) Requirement already satisfied: pyparsing!=2.0.0,!=2.0.4,!=2.1.2,!=2.1.6,>=1.5.6 in /usr/local/lib/python3.5/dist-packages (from matplotlib>=2.0.0->scikit-image) Requirement already satisfied: python-dateutil in /usr/local/lib/python3.5/dist-packages (from matplotlib>=2.0.0->scikit-image) Collecting toolz>=0.7.3; extra == “array” (from dask[array]>=0.9.0->scikit-image) Downloading (45kB) 100% |################################| 51kB 618kB/s ta 0:00:011 Collecting decorator>=4.3.0 (from networkx>=1.8->scikit-image) Downloading Building wheels for collected packages: networkx, toolz Running bdist_wheel for networkx … done Stored in directory: /root/.cache/pip/wheels/68/f8/29/b53346a112a07d30a5a84d53f19aeadaa1a474897c0423af91 Running bdist_wheel for toolz … done Stored in directory: /root/.cache/pip/wheels/f4/0c/f6/ce6b2d1aa459ee97cc3c0f82236302bd62d89c86c700219463 Successfully built networkx toolz Installing collected packages: PyWavelets, pillow, cloudpickle, toolz, dask, decorator, networkx, scikit-image Found existing installation: Pillow 4.2.1 Uninstalling Pillow-4.2.1: Successfully uninstalled Pillow-4.2.1 Found existing installation: decorator 4.1.2 Uninstalling decorator-4.1.2: Successfully uninstalled decorator-4.1.2 Successfully installed PyWavelets-1.0.1 cloudpickle-0.6.1 dask-1.0.0 decorator-4.3.0 networkx-2.2 pillow-5.3.0 scikit-image-0.14.1 toolz-0.9.0 You are using pip version 9.0.1, however version 18.1 is available. You should consider upgrading via the ‘pip install --upgrade pip’ command.
發現它卸載了4.2.1版的Pillow並重新安裝了5.3.0版。
因此我們可以猜測,問題就是出在Pillow的版本上。後來筆者做個實驗,重新使用:
pip install Pillow==4.2.0
來將Pillow還原成舊版。這時問題果然又出現了!
所以問題確定是出在Pillow的版本上!
既然知道了問題是出在Pillow的版本上,那麼使用以下其中一個指令來升級Pillow就可以解決問題:
pip install Pillow==5.3.0pip install --upgrade Pillow
這個問題的解決辦法是升級Pillow,但是為何升級個Pillow就改變了PIL及matplotlib的行為呢?
筆者後來去查了PIL跟Pillow的關係及matplotlib讀圖的方式,將之記錄於下。去查看:
Pillow is the friendly PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lundh and Contributors.
去查看PIL的訊息:
As more time passes since the last PIL release (1.1.7 in 2009), the likelihood of a new PIL release decreases. However, we’ve yet to hear an official “PIL is dead” announcement.
總結一下:PIL自2009年以來就沒有再推出新的版本,而Pillow則是PIL的fork。
這又衍生出一個問題:既然Pillow
是用pip install Pillow
來安裝,但是為何在python裡卻是下import PIL
來調用呢?
首先在python裡查看包的路徑:
import PILPIL
<module ‘PIL’ from ‘/usr/local/lib/python3.5/dist-packages/PIL/init.py’>
發現目錄名稱確實是PIL。
再去下載whl
檔做驗證:
wget https://files.pythonhosted.org/packages/bc/cc/b6e47b0075ca4267855d77850af7ea4194d2fc591664f1d70e5151b50637/Pillow-5.3.0-cp35-cp35m-manylinux1_x86_64.whl
接著查看whl
檔的內容,發現Pillow的whl
檔確實是有PIL的。
unzip Pillow-5.3.0-cp35-cp35m-manylinux1_x86_64.whl
Archive: Pillow-5.3.0-cp35-cp35m-manylinux1_x86_64.whl
inflating: Pillow-5.3.0.dist-info/WHEEL inflating: Pillow-5.3.0.dist-info/top_level.txt inflating: Pillow-5.3.0.dist-info/zip-safe inflating: Pillow-5.3.0.dist-info/LICENSE inflating: Pillow-5.3.0.dist-info/METADATA inflating: Pillow-5.3.0.dist-info/RECORD inflating: PIL/GimpGradientFile.py inflating: PIL/PcfFontFile.py inflating: PIL/FliImagePlugin.py inflating: PIL/ImageCms.py inflating: PIL/ImageFont.py inflating: PIL/FtexImagePlugin.py inflating: PIL/BmpImagePlugin.py inflating: PIL/ImageFile.py inflating: PIL/TarIO.py inflating: PIL/PixarImagePlugin.py inflating: PIL/XbmImagePlugin.py inflating: PIL/IcnsImagePlugin.py inflating: PIL/features.py inflating: PIL/MpoImagePlugin.py inflating: PIL/BufrStubImagePlugin.py inflating: PIL/ExifTags.py inflating: PIL/_tkinter_finder.py inflating: PIL/_binary.py inflating: PIL/DcxImagePlugin.py inflating: PIL/McIdasImagePlugin.py inflating: PIL/ContainerIO.py inflating: PIL/GribStubImagePlugin.py inflating: PIL/ImageMorph.py inflating: PIL/GifImagePlugin.py inflating: PIL/ImageWin.py inflating: PIL/SunImagePlugin.py inflating: PIL/ImtImagePlugin.py inflating: PIL/PcxImagePlugin.py inflating: PIL/ImagePath.py inflating: PIL/ImageFilter.py inflating: PIL/IptcImagePlugin.py inflating: PIL/init.py inflating: PIL/_imagingmorph.cpython-35m-x86_64-linux-gnu.so inflating: PIL/Image.py inflating: PIL/XVThumbImagePlugin.py inflating: PIL/PdfParser.py inflating: PIL/WmfImagePlugin.py inflating: PIL/ImageDraw.py inflating: PIL/MicImagePlugin.py inflating: PIL/_imagingtk.cpython-35m-x86_64-linux-gnu.so inflating: PIL/FitsStubImagePlugin.py inflating: PIL/SpiderImagePlugin.py inflating: PIL/PpmImagePlugin.py inflating: PIL/GimpPaletteFile.py inflating: PIL/BlpImagePlugin.py inflating: PIL/ImageMode.py inflating: PIL/ImageColor.py inflating: PIL/ImageShow.py inflating: PIL/EpsImagePlugin.py inflating: PIL/PalmImagePlugin.py inflating: PIL/MpegImagePlugin.py inflating: PIL/SgiImagePlugin.py inflating: PIL/Hdf5StubImagePlugin.py inflating: PIL/Jpeg2KImagePlugin.py inflating: PIL/BdfFontFile.py inflating: PIL/WalImageFile.py inflating: PIL/DdsImagePlugin.py inflating: PIL/TgaImagePlugin.py inflating: PIL/XpmImagePlugin.py inflating: PIL/JpegPresets.py inflating: PIL/ImagePalette.py inflating: PIL/_version.py inflating: PIL/_imagingmath.cpython-35m-x86_64-linux-gnu.so inflating: PIL/ImageDraw2.py inflating: PIL/ImImagePlugin.py inflating: PIL/ImageTransform.py inflating: PIL/PaletteFile.py inflating: PIL/ImageStat.py inflating: PIL/_util.py inflating: PIL/MspImagePlugin.py inflating: PIL/GdImageFile.py inflating: PIL/ImageOps.py inflating: PIL/ImageGrab.py inflating: PIL/TiffTags.py inflating: PIL/PdfImagePlugin.py inflating: PIL/ImageChops.py inflating: PIL/GbrImagePlugin.py inflating: PIL/ImageEnhance.py inflating: PIL/PSDraw.py inflating: PIL/FontFile.py inflating: PIL/ImageMath.py inflating: PIL/ImageSequence.py inflating: PIL/PsdImagePlugin.py inflating: PIL/_imaging.cpython-35m-x86_64-linux-gnu.so inflating: PIL/IcoImagePlugin.py inflating: PIL/TiffImagePlugin.py inflating: PIL/OleFileIO.py inflating: PIL/JpegImagePlugin.py inflating: PIL/CurImagePlugin.py inflating: PIL/PngImagePlugin.py inflating: PIL/_webp.cpython-35m-x86_64-linux-gnu.so inflating: PIL/WebPImagePlugin.py inflating: PIL/_imagingft.cpython-35m-x86_64-linux-gnu.so inflating: PIL/ImageTk.py inflating: PIL/_imagingcms.cpython-35m-x86_64-linux-gnu.so inflating: PIL/FpxImagePlugin.py inflating: PIL/ImageQt.py inflating: PIL/PyAccess.py inflating: PIL/PcdImagePlugin.py inflating: PIL/.libs/libopenjp2-e366d6b0.so.2.1.0 inflating: PIL/.libs/libwebpdemux-eba3dc32.so.2.0.4 inflating: PIL/.libs/liblcms2-a6801db4.so.2.0.8 inflating: PIL/.libs/liblzma-6cd627ed.so.5.2.4 inflating: PIL/.libs/libpng16-898afbbd.so.16.35.0 inflating: PIL/.libs/libtiff-8a6d997d.so.5.3.0 inflating: PIL/.libs/libjpeg-3fe7dfc0.so.9.3.0 inflating: PIL/.libs/libwebp-8ccd29fd.so.7.0.2 inflating: PIL/.libs/libz-a147dcb0.so.1.2.3 inflating: PIL/.libs/libfreetype-7ce95de6.so.6.16.1 inflating: PIL/.libs/libwebpmux-1c63fe99.so.3.0.2
所以我們可以發現,雖然pip包的名字是Pillow,但是因為安裝後文件夾的名稱是PIL,所以必須用import PIL
。
而我們升級Pillow後,PIL文件夾的內容會被改變。我們重啟python後再用import PIL
時就會得到新版的Pillow。
為何重新安裝Pillow,matplotlib讀圖時發生的問題就一併解決了呢?
首先去的頁面查看:
Loading image data is supported by the Pillow library. Natively, matplotlib only supports PNG images. The commands shown below fall back on Pillow if the native read fails.
這句話說明了matplotlib的原生讀圖程式只能讀.png檔;如果是.png以外的檔案,matplotlib則會調用Pillow來讀圖。
這個錯誤是發生在讀.jpg檔時,這代表matplotlib實際上是透過Pillow來讀的。
這也就解釋了為何升級了Pillow,matplotlib的行為就跟著改變了。转载地址:http://qmtm.baihongyu.com/