I want to crop image in the way by removing first 30 rows and last 30 rows from the given image. I have searched but did not get the exact solution. Does somebody have some suggestions?
The Python Imaging Library uses a Cartesian pixel coordinate system, with (0,0) in the upper left corner. Note that the coordinates refer to the implied pixel corners; the centre of a pixel addressed as (0, 0) actually lies at (0.5, 0.5).
Coordinates are usually passed to the library as 2-tuples (x, y). Rectangles are represented as 4-tuples, with the upper left corner given first. For example, a rectangle covering all of an 800×600 pixel image is written as (0, 0, 800, 600).
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/tk.h:78:11: fatal error:'X11/Xlib.h' file not found
# include <X11/Xlib.h>^1 error generated.
error: command 'cc' failed with exit status 1
I’ve just updated my Mac OS to 10.9 and I discovered that some (all?) of my Python modules are not here anymore, especially the Image one.
So I try to execute sudo pip install pil, but I get this error:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/tk.h:78:11: fatal error: 'X11/Xlib.h' file not found
# include <X11/Xlib.h>
^
1 error generated.
error: command 'cc' failed with exit status 1
My Xcode is up-to-date and I don’t have any idea. Is it possible that PIL is not yet 10.9 compatible ?
pip install pillow
PIL SETUP SUMMARY
--------------------------------------------------------------------
version Pillow2.2.1
platform darwin 2.7.5(default,Aug252013,00:04:04)[GCC 4.2.1CompatibleApple LLVM 5.0(clang-500.0.68)]----------------------------------------------------------------------- TKINTER support available
--- JPEG support available
--- ZLIB (PNG/ZIP) support available
--- TIFF G3/G4 (experimental) support available
--- FREETYPE2 support available
--- LITTLECMS support available
--- WEBP support available
--- WEBPMUX support available
--------------------------------------------------------------------
pip install pillow
PIL SETUP SUMMARY
--------------------------------------------------------------------
version Pillow 2.2.1
platform darwin 2.7.5 (default, Aug 25 2013, 00:04:04)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]
--------------------------------------------------------------------
--- TKINTER support available
--- JPEG support available
--- ZLIB (PNG/ZIP) support available
--- TIFF G3/G4 (experimental) support available
--- FREETYPE2 support available
--- LITTLECMS support available
--- WEBP support available
--- WEBPMUX support available
--------------------------------------------------------------------
回答 3
适用于我(OS X Yosemite 10.10.2-Python 2.7.9):
xcode-select --install
sudo pip install pillow
尝试检查一下:
from PIL importImage
image =Image.open("file.jpg")
image.show()
Here is what I did, some steps may not be necessary just for PIL but I needed libpng and others anyways:
1) Run xcode install, use this command or download updates from the app store:
xcode-select --install
1b) Add the Command Line Tools optional tool, in Mountain Lion this was an option on the xcode Download page, but now you have to register with your apple id and download from: https://developer.apple.com/downloads/
Look for Command Line Tools (OS X Mavericks) for Xcode
2) Install everything needed for python (using brew), I believe you can use port as well:
UPDATE (OLD) : The same thing applies when installing Pillow (PIL fork) and should be mentioned as its quickly becoming a replacement in most cases of PIL. Instead of installing pip in step 4, run this instead:
clang: error: unknown argument:'-mno-fused-madd'[-Wunused-command-line-argument-hard-error-in-future]
clang: note: this will be a hard error (cannot be downgraded to a warning)in the future
error: command 'cc' failed with exit status 1
clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
clang: note: this will be a hard error (cannot be downgraded to a warning) in the future
error: command 'cc' failed with exit status 1
So I found a work around with the following solution:
我有一个类似的问题:安装枕头失败clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future],安装枕头失败Can't install the software because it is not currently available from the Software Update server.,并且,即使手动安装了命令行工具,PIL的编译也失败了。
I had a similar problem: Installing pillow failed with clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future], installing command line tools failed with Can't install the software because it is not currently available from the Software Update server., and even after installing the command line tools manually, the compilation of PIL failed.
This happens cause clang under the newest version of xcode doesn’t warn on unknown compiler flags, but rather stop the compilation with a hard error.
To fix this, just run export ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future" on the terminal before trying to compile (installing pil).
building 'PIL._imagingft' extension
_imagingft.c:62:10: fatal error:'freetype/fterrors.h' file not found
#include <freetype/fterrors.h>^1 error generated.
error: command 'cc' failed with exit status 1
building 'PIL._imagingft' extension
_imagingft.c:62:10: fatal error: 'freetype/fterrors.h' file not found
#include <freetype/fterrors.h>
^
1 error generated.
error: command 'cc' failed with exit status 1
The solution to this was to symlink freetype2 to freetype and this solved the problem.
I didn’t want to install XCode (I don’t use it) and I’m loath to fiddle with Application directory. I’ve cribbed from the many answers in this post and the following two steps work for me with 10.9.5:
sudo easy_install pip
sudo pip install pillow
It did appear to me strange that I had to use easy_install to install pip. But pip didn’t want to work for me before that (re-)install.
A more complete solution requires the installation of the Xquartz X11 subsystem that has been built outside of Apple for several years now. Here are the steps I used to get it all working
因为公认的答案是正确的答案,xcode-select --install但有些人(包括我)可能会遇到Can't install the software because it is not currently available from the Software Update server
如果您使用的是Beta版软件(因为我现在使用的是优胜美地并且遇到相同的问题),则您需要单独购买CLT,因为它不包含在其中。 XCode(甚至xcode beta)也可以转到developers.apple.com并为您的OS获取CLT工具;)
As the accepted answer is the right one with xcode-select --install but some people (including me) may encounter Can't install the software because it is not currently available from the Software Update server
If you are using beta software (as I am using Yosemite now and had the same problem) you NEED to get the CLT separately since it is NOT included in XCode (even xcode beta)
Head over to developers.apple.com and get CLT tools for your OS ;)
P.S. You don’t need XQuartz for PIL or Pillow to work
Installing PIL (Imaging.1.1.7) on Mac OSC 10.10 Yosemite. I tried numerous fixes recommended here but ran into trouble with each one. I finally solved this problem by editing the setup.py file such that:
TCL_ROOT = “/opt/X11/include”
which passes the appropriate include path for X11 in the compilation of _imagingtk.c, which was causing the problem for me. Worked immediately after change.
I have a simple problem, but I cannot find a good solution to it.
I want to take a NumPy 2D array which represents a grayscale image, and convert it to an RGB PIL image while applying some of the matplotlib colormaps.
I can get a reasonable PNG output by using the pyplot.figure.figimage command:
Although I could adapt this to get what I want (probably using StringIO do get the PIL image), I wonder if there is not a simpler way to do that, since it seems to be a very natural problem of image visualization. Let’s say, something like this:
colored_PIL_image = magic_function(array, cmap)
回答 0
一行代码很忙,但是这里是:
首先,请确保您的NumPy数组myarray使用处的最大值进行了规范化1.0。
将颜色表直接应用于myarray。
重新调整0-255范围。
使用转换为整数np.uint8()。
使用Image.fromarray()。
这样就完成了:
from PIL importImagefrom matplotlib import cm
im =Image.fromarray(np.uint8(cm.gist_earth(myarray)*255))
First ensure your NumPy array, myarray, is normalised with the max value at 1.0.
Apply the colormap directly to myarray.
Rescale to the 0-255 range.
Convert to integers, using np.uint8().
Use Image.fromarray().
And you’re done:
from PIL import Image
from matplotlib import cm
im = Image.fromarray(np.uint8(cm.gist_earth(myarray)*255))
with plt.savefig():
with im.save():
回答 1
输入= numpy_image
np.unit8->转换为整数
convert(’RGB’)->转换为RGB
Image.fromarray->返回图像对象
from PIL importImageimport numpy as np
PIL_image =Image.fromarray(np.uint8(numpy_image)).convert('RGB')
PIL_image =Image.fromarray(numpy_image.astype('uint8'),'RGB')
The method described in the accepted answer didn’t work for me even after applying changes mentioned in its comments. But the below simple code worked:
import matplotlib.pyplot as plt
plt.imsave(filename, np_array, cmap='Greys')
np_array could be either a 2D array with values from 0..1 floats o2 0..255 uint8, and in that case it needs cmap. For 3D arrays, cmap will be ignored.
This should give you a dictionary indexed by EXIF numeric tags. If you want the dictionary indexed by the actual EXIF tag name strings, try something like:
import PIL.ExifTags
exif = {
PIL.ExifTags.TAGS[k]: v
for k, v in img._getexif().items()
if k in PIL.ExifTags.TAGS
}
import os,sys
from PIL import Image
from PIL.ExifTags import TAGS
for (k,v) in Image.open(sys.argv[1])._getexif().items():
print('%s = %s' % (TAGS.get(k), v))
or to get a specific field:
def get_field (exif,field) :
for (k,v) in exif.items():
if TAGS.get(k) == field:
return v
exif = image._getexif()
print get_field(exif,'ExposureTime')
For Python3.x and starting Pillow==6.0.0, Image objects now provide a getexif() method that returns <class 'PIL.Image.Exif'> or None if the image has no EXIF data.
getexif() has been added, which returns an Exif instance. Values can
be retrieved and set like a dictionary. When saving JPEG, PNG or WEBP,
the instance can be passed as an exif argument to include any changes
in the output image.
As stated, the Exif output can simply be casted to a dict with the EXIF data accessible as regular key-value pairs. The keys are 16-bit integers that can be mapped to their string names using the ExifTags.TAGS module.
from PIL import Image, ExifTags
img = Image.open("sample.jpg")
img_exif = img.getexif()
print(type(img_exif))
# <class 'PIL.Image.Exif'>
if img_exif is None:
print("Sorry, image has no exif data.")
else:
img_exif_dict = dict(img_exif)
print(img_exif_dict)
# { ... 42035: 'FUJIFILM', 42036: 'XF23mmF2 R WR', 42037: '75A14188' ... }
for key, val in img_exif_dict.items():
if key in ExifTags.TAGS:
print(f"{ExifTags.TAGS[key]}:{repr(val)}")
# ExifVersion:b'0230'
# ...
# FocalLength:(2300, 100)
# ColorSpace:1
# FocalLengthIn35mmFilm:35
# ...
# Model:'X-T2'
# Make:'FUJIFILM'
# ...
# DateTime:'2019:12:01 21:30:07'
# ...
Tested with Python 3.6.8 and Pillow==6.0.0.
回答 4
import sys
import PIL
import PIL.ImageasPILimagefrom PIL importImageDraw,ImageFont,ImageEnhancefrom PIL.ExifTagsimport TAGS, GPSTAGS
classWorker(object):def __init__(self, img):
self.img = img
self.exif_data = self.get_exif_data()
self.lat = self.get_lat()
self.lon = self.get_lon()
self.date =self.get_date_time()
super(Worker, self).__init__()@staticmethoddef get_if_exist(data, key):if key in data:return data[key]returnNone@staticmethoddef convert_to_degress(value):"""Helper function to convert the GPS coordinates
stored in the EXIF to degress in float format"""
d0 = value[0][0]
d1 = value[0][1]
d = float(d0)/ float(d1)
m0 = value[1][0]
m1 = value[1][1]
m = float(m0)/ float(m1)
s0 = value[2][0]
s1 = value[2][1]
s = float(s0)/ float(s1)return d +(m /60.0)+(s /3600.0)def get_exif_data(self):"""Returns a dictionary from the exif data of an PIL Image item. Also
converts the GPS Tags"""
exif_data ={}
info = self.img._getexif()if info:for tag, value in info.items():
decoded = TAGS.get(tag, tag)if decoded =="GPSInfo":
gps_data ={}for t in value:
sub_decoded = GPSTAGS.get(t, t)
gps_data[sub_decoded]= value[t]
exif_data[decoded]= gps_data
else:
exif_data[decoded]= value
return exif_data
def get_lat(self):"""Returns the latitude and longitude, if available, from the
provided exif_data (obtained through get_exif_data above)"""# print(exif_data)if'GPSInfo'in self.exif_data:
gps_info = self.exif_data["GPSInfo"]
gps_latitude = self.get_if_exist(gps_info,"GPSLatitude")
gps_latitude_ref = self.get_if_exist(gps_info,'GPSLatitudeRef')if gps_latitude and gps_latitude_ref:
lat = self.convert_to_degress(gps_latitude)if gps_latitude_ref !="N":
lat =0- lat
lat = str(f"{lat:.{5}f}")return lat
else:returnNonedef get_lon(self):"""Returns the latitude and longitude, if available, from the
provided exif_data (obtained through get_exif_data above)"""# print(exif_data)if'GPSInfo'in self.exif_data:
gps_info = self.exif_data["GPSInfo"]
gps_longitude = self.get_if_exist(gps_info,'GPSLongitude')
gps_longitude_ref = self.get_if_exist(gps_info,'GPSLongitudeRef')if gps_longitude and gps_longitude_ref:
lon = self.convert_to_degress(gps_longitude)if gps_longitude_ref !="E":
lon =0- lon
lon = str(f"{lon:.{5}f}")return lon
else:returnNonedef get_date_time(self):if'DateTime'in self.exif_data:
date_and_time = self.exif_data['DateTime']return date_and_time
if __name__ =='__main__':try:
img =PILimage.open(sys.argv[1])
image =Worker(img)
lat = image.lat
lon = image.lon
date = image.date
print(date, lat, lon)exceptExceptionas e:print(e)
import sys
import PIL
import PIL.Image as PILimage
from PIL import ImageDraw, ImageFont, ImageEnhance
from PIL.ExifTags import TAGS, GPSTAGS
class Worker(object):
def __init__(self, img):
self.img = img
self.exif_data = self.get_exif_data()
self.lat = self.get_lat()
self.lon = self.get_lon()
self.date =self.get_date_time()
super(Worker, self).__init__()
@staticmethod
def get_if_exist(data, key):
if key in data:
return data[key]
return None
@staticmethod
def convert_to_degress(value):
"""Helper function to convert the GPS coordinates
stored in the EXIF to degress in float format"""
d0 = value[0][0]
d1 = value[0][1]
d = float(d0) / float(d1)
m0 = value[1][0]
m1 = value[1][1]
m = float(m0) / float(m1)
s0 = value[2][0]
s1 = value[2][1]
s = float(s0) / float(s1)
return d + (m / 60.0) + (s / 3600.0)
def get_exif_data(self):
"""Returns a dictionary from the exif data of an PIL Image item. Also
converts the GPS Tags"""
exif_data = {}
info = self.img._getexif()
if info:
for tag, value in info.items():
decoded = TAGS.get(tag, tag)
if decoded == "GPSInfo":
gps_data = {}
for t in value:
sub_decoded = GPSTAGS.get(t, t)
gps_data[sub_decoded] = value[t]
exif_data[decoded] = gps_data
else:
exif_data[decoded] = value
return exif_data
def get_lat(self):
"""Returns the latitude and longitude, if available, from the
provided exif_data (obtained through get_exif_data above)"""
# print(exif_data)
if 'GPSInfo' in self.exif_data:
gps_info = self.exif_data["GPSInfo"]
gps_latitude = self.get_if_exist(gps_info, "GPSLatitude")
gps_latitude_ref = self.get_if_exist(gps_info, 'GPSLatitudeRef')
if gps_latitude and gps_latitude_ref:
lat = self.convert_to_degress(gps_latitude)
if gps_latitude_ref != "N":
lat = 0 - lat
lat = str(f"{lat:.{5}f}")
return lat
else:
return None
def get_lon(self):
"""Returns the latitude and longitude, if available, from the
provided exif_data (obtained through get_exif_data above)"""
# print(exif_data)
if 'GPSInfo' in self.exif_data:
gps_info = self.exif_data["GPSInfo"]
gps_longitude = self.get_if_exist(gps_info, 'GPSLongitude')
gps_longitude_ref = self.get_if_exist(gps_info, 'GPSLongitudeRef')
if gps_longitude and gps_longitude_ref:
lon = self.convert_to_degress(gps_longitude)
if gps_longitude_ref != "E":
lon = 0 - lon
lon = str(f"{lon:.{5}f}")
return lon
else:
return None
def get_date_time(self):
if 'DateTime' in self.exif_data:
date_and_time = self.exif_data['DateTime']
return date_and_time
if __name__ == '__main__':
try:
img = PILimage.open(sys.argv[1])
image = Worker(img)
lat = image.lat
lon = image.lon
date = image.date
print(date, lat, lon)
except Exception as e:
print(e)
I have found that using ._getexif doesn’t work in higher python versions, moreover, it is a protected class and one should avoid using it if possible.
After digging around the debugger this is what I found to be the best way to get the EXIF data for an image:
from PIL import Image
def get_exif(path):
return Image.open(path).info['parsed_exif']
This returns a dictionary of all the EXIF data of an image.
Note: For Python3.x use Pillow instead of PIL
回答 6
这是一个可能更容易阅读的内容。希望这会有所帮助。
from PIL importImagefrom PIL importExifTags
exifData ={}
img =Image.open(picture.jpg)
exifDataRaw = img._getexif()for tag, value in exifDataRaw.items():
decodedTag =ExifTags.TAGS.get(tag, tag)
exifData[decodedTag]= value
Here’s the one that may be little easier to read. Hope this is helpful.
from PIL import Image
from PIL import ExifTags
exifData = {}
img = Image.open(picture.jpg)
exifDataRaw = img._getexif()
for tag, value in exifDataRaw.items():
decodedTag = ExifTags.TAGS.get(tag, tag)
exifData[decodedTag] = value
imread is deprecated in SciPy 1.0.0, and will be removed in 1.2.0.
Use imageio.imread instead.
import imageio
im = imageio.imread('astronaut.png')
im.shape # im is a numpy array
(512, 512, 3)
imageio.imwrite('imageio:astronaut-gray.jpg', im[:, :, 0])
You need the Python Imaging Library (PIL) but alas! the PIL project seems to have been abandoned. In particular, it hasn’t been ported to Python 3. So if you want PIL functionality in Python 3, you’ll do well do use Pillow, which is the semi-official fork of PIL and appears to be actively developed. Actually, if you need a modern PIL implementation at all I’d recommend Pillow. It’s as simple as pip install pillow. As it uses the same namespace as PIL it’s essentially a drop-in replacement.
How “semi-official” is this fork? you may ask. The About page of the Pillow docs say this:
As more time passes since the last PIL release, the likelihood of a
new PIL release decreases. However, we’ve yet to hear an official “PIL
is dead” announcement. So if you still want to support PIL, please
report issues here first, then open corresponding Pillow tickets here.
Please provide a link to the first ticket so we can track the issue(s)
upstream.
However, the most recent PIL release on the official PIL site is dated November 15, 2009. I think we can safely proclaim Pillow as the successor of PIL after (as of this writing) nearly eight years of no new releases. So even if you don’t need Python 3 support, I suggest you eschew the ancient PIL 1.1.6 distribution available in PyPI and just install fresh, up-to-date, compatible Pillow.
Note, the selected answer has been outdated. See the docs of
SciPy
Note that Pillow (https://python-pillow.org/) is not a dependency of SciPy, but the image manipulation functions indicated in the list below are not available without it.
Running the following in a Jupyter Notebook, I had a similar error message:
from skimage import data
photo_data = misc.imread('C:/Users/ers.jpg')
type(photo_data)
‘error’ msg:
D:\Program Files (x86)\Microsoft Visual
Studio\Shared\Anaconda3_64\lib\site-packages\ipykernel_launcher.py:3:
DeprecationWarning: imread is deprecated! imread is deprecated in
SciPy 1.0.0, and will be removed in 1.2.0. Use imageio.imread
instead. This is separate from the ipykernel package so we can avoid
doing imports until
from PIL importImageimport numpy as np
i =Image.open("C:/Users/User/Desktop/mesh.bmp")
i = i.convert("L")
a = np.asarray(i)
b = np.abs(np.fft.rfft2(a))
j =Image.fromarray(b)
j.save("C:/Users/User/Desktop/mesh_trans",".bmp")
I have just done some image processing using the Python image library (PIL) using a post I found earlier to perform fourier transforms of images and I can’t get the save function to work. The whole code works fine but it just wont save the resulting image:
from PIL import Image
import numpy as np
i = Image.open("C:/Users/User/Desktop/mesh.bmp")
i = i.convert("L")
a = np.asarray(i)
b = np.abs(np.fft.rfft2(a))
j = Image.fromarray(b)
j.save("C:/Users/User/Desktop/mesh_trans",".bmp")
The error I get is the following:
save_handler = SAVE[string.upper(format)] # unknown format
KeyError: '.BMP'
The error regarding the file extension has been handled, you either use BMP (without the dot) or pass the output name with the extension already. Now to handle the error you need to properly modify your data in the frequency domain to be saved as an integer image, PIL is telling you that it doesn’t accept float data to save as BMP.
Here is a suggestion (with other minor modifications, like using fftshift and numpy.array instead of numpy.asarray) for doing the conversion for proper visualization:
Try removing the . before the .bmp (it isn’t matching BMP as expected). As you can see from the error, the save_handler is upper-casing the format you provided and then looking for a match in SAVE. However the corresponding key in that object is BMP (instead of .BMP).
I don’t know a great deal about PIL, but from some quick searching around it seems that it is a problem with the mode of the image. Changing the definition of j to:
j = Image.fromarray(b, mode='RGB')
Seemed to work for me (however note that I have very little knowledge of PIL, so I would suggest using @mmgp’s solution as s/he clearly knows what they are doing :) ). For the types of mode, I used this page – hopefully one of the choices there will work for you.
importImageimport numpy as npdef alpha_to_color(image, color=(255,255,255)):"""Set all fully transparent pixels of an RGBA image to the specified color.
This is a very simple solution that might leave over some ugly edges, due
to semi-transparent areas. You should use alpha_composite_with color instead.
Source: http://stackoverflow.com/a/9166671/284318
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
x = np.array(image)
r, g, b, a = np.rollaxis(x, axis=-1)
r[a ==0]= color[0]
g[a ==0]= color[1]
b[a ==0]= color[2]
x = np.dstack([r, g, b, a])returnImage.fromarray(x,'RGBA')def alpha_composite(front, back):"""Alpha composite two RGBA images.
Source: http://stackoverflow.com/a/9166671/284318
Keyword Arguments:
front -- PIL RGBA Image object
back -- PIL RGBA Image object
"""
front = np.asarray(front)
back = np.asarray(back)
result = np.empty(front.shape, dtype='float')
alpha = np.index_exp[:,:,3:]
rgb = np.index_exp[:,:,:3]
falpha = front[alpha]/255.0
balpha = back[alpha]/255.0
result[alpha]= falpha + balpha *(1- falpha)
old_setting = np.seterr(invalid='ignore')
result[rgb]=(front[rgb]* falpha + back[rgb]* balpha *(1- falpha))/ result[alpha]
np.seterr(**old_setting)
result[alpha]*=255
np.clip(result,0,255)# astype('uint8') maps np.nan and np.inf to 0
result = result.astype('uint8')
result =Image.fromarray(result,'RGBA')return resultdef alpha_composite_with_color(image, color=(255,255,255)):"""Alpha composite an RGBA image with a single color image of the
specified color and the same size as the original image.
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
back =Image.new('RGBA', size=image.size, color=color +(255,))return alpha_composite(image, back)def pure_pil_alpha_to_color_v1(image, color=(255,255,255)):"""Alpha composite an RGBA Image with a specified color.
NOTE: This version is much slower than the
alpha_composite_with_color solution. Use it only if
numpy is not available.
Source: http://stackoverflow.com/a/9168169/284318
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""def blend_value(back, front, a):return(front * a + back *(255- a))/255def blend_rgba(back, front):
result =[blend_value(back[i], front[i], front[3])for i in(0,1,2)]return tuple(result +[255])
im = image.copy()# don't edit the reference directly
p = im.load()# load pixel arrayfor y in range(im.size[1]):for x in range(im.size[0]):
p[x, y]= blend_rgba(color +(255,), p[x, y])return imdef pure_pil_alpha_to_color_v2(image, color=(255,255,255)):"""Alpha composite an RGBA Image with a specified color.
Simpler, faster version than the solutions above.
Source: http://stackoverflow.com/a/9459208/284318
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
image.load()# needed for split()
background =Image.new('RGB', image.size, color)
background.paste(image, mask=image.split()[3])# 3 is the alpha channelreturn background
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.alpha_to_color(i)"10 loops, best of 3:4.67 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.alpha_composite_with_color(i)"10 loops, best of 3:8.93 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.pure_pil_alpha_to_color(i)"10 loops, best of 3:79.6 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.pure_pil_alpha_to_color_v2(i)"10 loops, best of 3:1.1 msec per loop
Is there a way to fix this? I’d like to have white background where the transparent background used to be.
Solution
Thanks to the great answers, I’ve come up with the following function collection:
import Image
import numpy as np
def alpha_to_color(image, color=(255, 255, 255)):
"""Set all fully transparent pixels of an RGBA image to the specified color.
This is a very simple solution that might leave over some ugly edges, due
to semi-transparent areas. You should use alpha_composite_with color instead.
Source: http://stackoverflow.com/a/9166671/284318
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
x = np.array(image)
r, g, b, a = np.rollaxis(x, axis=-1)
r[a == 0] = color[0]
g[a == 0] = color[1]
b[a == 0] = color[2]
x = np.dstack([r, g, b, a])
return Image.fromarray(x, 'RGBA')
def alpha_composite(front, back):
"""Alpha composite two RGBA images.
Source: http://stackoverflow.com/a/9166671/284318
Keyword Arguments:
front -- PIL RGBA Image object
back -- PIL RGBA Image object
"""
front = np.asarray(front)
back = np.asarray(back)
result = np.empty(front.shape, dtype='float')
alpha = np.index_exp[:, :, 3:]
rgb = np.index_exp[:, :, :3]
falpha = front[alpha] / 255.0
balpha = back[alpha] / 255.0
result[alpha] = falpha + balpha * (1 - falpha)
old_setting = np.seterr(invalid='ignore')
result[rgb] = (front[rgb] * falpha + back[rgb] * balpha * (1 - falpha)) / result[alpha]
np.seterr(**old_setting)
result[alpha] *= 255
np.clip(result, 0, 255)
# astype('uint8') maps np.nan and np.inf to 0
result = result.astype('uint8')
result = Image.fromarray(result, 'RGBA')
return result
def alpha_composite_with_color(image, color=(255, 255, 255)):
"""Alpha composite an RGBA image with a single color image of the
specified color and the same size as the original image.
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
back = Image.new('RGBA', size=image.size, color=color + (255,))
return alpha_composite(image, back)
def pure_pil_alpha_to_color_v1(image, color=(255, 255, 255)):
"""Alpha composite an RGBA Image with a specified color.
NOTE: This version is much slower than the
alpha_composite_with_color solution. Use it only if
numpy is not available.
Source: http://stackoverflow.com/a/9168169/284318
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
def blend_value(back, front, a):
return (front * a + back * (255 - a)) / 255
def blend_rgba(back, front):
result = [blend_value(back[i], front[i], front[3]) for i in (0, 1, 2)]
return tuple(result + [255])
im = image.copy() # don't edit the reference directly
p = im.load() # load pixel array
for y in range(im.size[1]):
for x in range(im.size[0]):
p[x, y] = blend_rgba(color + (255,), p[x, y])
return im
def pure_pil_alpha_to_color_v2(image, color=(255, 255, 255)):
"""Alpha composite an RGBA Image with a specified color.
Simpler, faster version than the solutions above.
Source: http://stackoverflow.com/a/9459208/284318
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
image.load() # needed for split()
background = Image.new('RGB', image.size, color)
background.paste(image, mask=image.split()[3]) # 3 is the alpha channel
return background
Performance
The simple non-compositing alpha_to_color function is the fastest solution, but leaves behind ugly borders because it does not handle semi transparent areas.
Both the pure PIL and the numpy compositing solutions give great results, but alpha_composite_with_color is much faster (8.93 msec) than pure_pil_alpha_to_color (79.6 msec). If numpy is available on your system, that’s the way to go. (Update: The new pure PIL version is the fastest of all mentioned solutions.)
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.alpha_to_color(i)"
10 loops, best of 3: 4.67 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.alpha_composite_with_color(i)"
10 loops, best of 3: 8.93 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.pure_pil_alpha_to_color(i)"
10 loops, best of 3: 79.6 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.pure_pil_alpha_to_color_v2(i)"
10 loops, best of 3: 1.1 msec per loop
Here’s a version that’s much simpler – not sure how performant it is. Heavily based on some django snippet I found while building RGBA -> JPG + BG support for sorl thumbnails.
from PIL import Image
png = Image.open(object.logo.path)
png.load() # required for png.split()
background = Image.new("RGB", png.size, (255, 255, 255))
background.paste(png, mask=png.split()[3]) # 3 is the alpha channel
background.save('foo.jpg', 'JPEG', quality=80)
Result @80%
Result @ 50%
回答 1
通过使用Image.alpha_composite,Yuji’Tomita’Tomita的解决方案变得更简单。tuple index out of range如果png没有alpha通道,则此代码可以避免错误。
By using Image.alpha_composite, the solution by Yuji ‘Tomita’ Tomita become simpler. This code can avoid a tuple index out of range error if png has no alpha channel.
Note that the logo also has some semi-transparent pixels used to smooth the edges around the words and icon. Saving to jpeg ignores the semi-transparency, making the resultant jpeg look quite jagged.
A better quality result could be made using imagemagick’s convert command:
convert logo.png -background white -flatten /tmp/out.jpg
To make a nicer quality blend using numpy, you could use alpha compositing:
import Image
import numpy as np
def alpha_composite(src, dst):
'''
Return the alpha composite of src and dst.
Parameters:
src -- PIL RGBA Image object
dst -- PIL RGBA Image object
The algorithm comes from http://en.wikipedia.org/wiki/Alpha_compositing
'''
# http://stackoverflow.com/a/3375291/190597
# http://stackoverflow.com/a/9166671/190597
src = np.asarray(src)
dst = np.asarray(dst)
out = np.empty(src.shape, dtype = 'float')
alpha = np.index_exp[:, :, 3:]
rgb = np.index_exp[:, :, :3]
src_a = src[alpha]/255.0
dst_a = dst[alpha]/255.0
out[alpha] = src_a+dst_a*(1-src_a)
old_setting = np.seterr(invalid = 'ignore')
out[rgb] = (src[rgb]*src_a + dst[rgb]*dst_a*(1-src_a))/out[alpha]
np.seterr(**old_setting)
out[alpha] *= 255
np.clip(out,0,255)
# astype('uint8') maps np.nan (and np.inf) to 0
out = out.astype('uint8')
out = Image.fromarray(out, 'RGBA')
return out
FNAME = 'logo.png'
img = Image.open(FNAME).convert('RGBA')
white = Image.new('RGBA', size = img.size, color = (255, 255, 255, 255))
img = alpha_composite(img, white)
img.save('/tmp/out.jpg')
回答 3
这是纯PIL解决方案。
def blend_value(under, over, a):return(over*a + under*(255-a))/255def blend_rgba(under, over):return tuple([blend_value(under[i], over[i], over[3])for i in(0,1,2)]+[255])
white =(255,255,255,255)
im =Image.open(object.logo.path)
p = im.load()for y in range(im.size[1]):for x in range(im.size[0]):
p[x,y]= blend_rgba(white, p[x,y])
im.save('/tmp/output.png')
def blend_value(under, over, a):
return (over*a + under*(255-a)) / 255
def blend_rgba(under, over):
return tuple([blend_value(under[i], over[i], over[3]) for i in (0,1,2)] + [255])
white = (255, 255, 255, 255)
im = Image.open(object.logo.path)
p = im.load()
for y in range(im.size[1]):
for x in range(im.size[0]):
p[x,y] = blend_rgba(white, p[x,y])
im.save('/tmp/output.png')
It’s not broken. It’s doing exactly what you told it to; those pixels are black with full transparency. You will need to iterate across all pixels and convert ones with full transparency to white.
回答 5
import numpy as np
import PIL
def convert_image(image_file):
image =Image.open(image_file)# this could be a 4D array PNG (RGBA)
original_width, original_height = image.size
np_image = np.array(image)
new_image = np.zeros((np_image.shape[0], np_image.shape[1],3))# create 3D arrayfor each_channel in range(3):
new_image[:,:,each_channel]= np_image[:,:,each_channel]# only copy first 3 channels.# flushing
np_image =[]return new_image
# Get the RGBA buffer from the figure
w,h = fig.canvas.get_width_height()
buf = np.fromstring ( fig.canvas.tostring_argb(), dtype=np.uint8 )
buf.shape =( w, h,4)# canvas.tostring_argb give pixmap in ARGB mode. Roll the ALPHA channel to have it in RGBA mode
buf = np.roll ( buf,3, axis =2)return buf
def fig2img ( fig ):
“””
@brief Convert a Matplotlib figure to a PIL Image in RGBA format and return it
@param fig a matplotlib figure
@return a Python Imaging Library ( PIL ) image
“””
# put the figure pixmap into a numpy array
buf = fig2data ( fig )
w, h, d = buf.shape
return Image.frombytes( “RGBA”, ( w ,h ), buf.tostring( ) )
def fig2data ( fig ):
“””
@brief Convert a Matplotlib figure to a 4D numpy array with RGBA channels and return it
@param fig a matplotlib figure
@return a numpy 3D array of RGBA values
“””
# draw the renderer
fig.canvas.draw ( )
# Get the RGBA buffer from the figure
w,h = fig.canvas.get_width_height()
buf = np.fromstring ( fig.canvas.tostring_argb(), dtype=np.uint8 )
buf.shape = ( w, h, 4 )
# canvas.tostring_argb give pixmap in ARGB mode. Roll the ALPHA channel to have it in RGBA mode
buf = np.roll ( buf, 3, axis = 2 )
return buf
def rgba2rgb(img, c=(0, 0, 0), path=’foo.jpg’, is_already_saved=False, if_load=True):
if not is_already_saved:
background = Image.new(“RGB”, img.size, c)
background.paste(img, mask=img.split()[3]) # 3 is the alpha channel
background.save(path, 'JPEG', quality=100)
is_already_saved = True
if if_load:
if is_already_saved:
im = Image.open(path)
return np.array(im)
else:
raise ValueError('No image to load.')
from matplotlib.pyplot import imshow
import numpy as np
from PIL importImage%matplotlib inline
pil_im =Image.open('data/empire.jpg','r')
imshow(np.asarray(pil_im))
Use IPython display to render PIL images in a notebook.
from PIL import Image # to load images
from IPython.display import display # to display images
pil_im = Image.open('path/to/image.jpg')
display(pil_im)
回答 2
我发现这有效
# source: http://nbviewer.ipython.org/gist/deeplook/5162445from io importBytesIOfromIPythonimport display
from PIL importImagedef display_pil_image(im):"""Displayhook function for PIL Images, rendered as PNG."""
b =BytesIO()
im.save(b, format='png')
data = b.getvalue()
ip_img = display.Image(data=data, format='png', embed=True)return ip_img._repr_png_()# register display func with PNG formatter:
png_formatter = get_ipython().display_formatter.formatters['image/png']
dpi = png_formatter.for_type(Image.Image, display_pil_image)
# source: http://nbviewer.ipython.org/gist/deeplook/5162445
from io import BytesIO
from IPython import display
from PIL import Image
def display_pil_image(im):
"""Displayhook function for PIL Images, rendered as PNG."""
b = BytesIO()
im.save(b, format='png')
data = b.getvalue()
ip_img = display.Image(data=data, format='png', embed=True)
return ip_img._repr_png_()
# register display func with PNG formatter:
png_formatter = get_ipython().display_formatter.formatters['image/png']
dpi = png_formatter.for_type(Image.Image, display_pil_image)
After this I can just do:
pil_im
But this must be last line in cell, with no print after it
回答 3
案例python3
from PIL importImagefromIPython.display import HTML
from io importBytesIOfrom base64 import b64encode
pil_im =Image.open('data/empire.jpg')
b =BytesIO()
pil_im.save(b, format='png')
HTML("<img src='data:image/png;base64,{0}'/>".format(b64encode(b.getvalue()).decode('utf-8')))
from PIL import Image
from IPython.display import HTML
from io import BytesIO
from base64 import b64encode
pil_im = Image.open('data/empire.jpg')
b = BytesIO()
pil_im.save(b, format='png')
HTML("<img src='data:image/png;base64,{0}'/>".format(b64encode(b.getvalue()).decode('utf-8')))
回答 4
使用枕头在jupyter中简单得多。
from PIL importImage
image0=Image.open('image.png')
image0
from PIL import Image
image0=Image.open('image.png')
image0
回答 5
您可以使用PIL包中的Image类打开图像,并直接使用plt.imshow显示它。
# First import libraries.from PIL importImageimport matplotlib.pyplot as plt
# The folliwing line is useful in Jupyter notebook%matplotlib inline
# Open your file image using the path
img =Image.open(<path_to_image>)# Since plt knows how to handle instance of the Image class, just input your loaded image to imshow method
plt.imshow(img)
You can open an image using the Image class from the package PIL and display it with plt.imshow directly.
# First import libraries.
from PIL import Image
import matplotlib.pyplot as plt
# The folliwing line is useful in Jupyter notebook
%matplotlib inline
# Open your file image using the path
img = Image.open(<path_to_image>)
# Since plt knows how to handle instance of the Image class, just input your loaded image to imshow method
plt.imshow(img)
Based on other answers and my tries, best experience would be first installing, pillow and scipy, then using the following starting code on your jupyter notebook:
%matplotlib inline
from matplotlib.pyplot import imshow
from scipy.misc import imread
imshow(imread('image.jpg', 1))
import matplotlib.pyplot as plt
from PIL importImageimport numpy as np
pil_im =Image.open('image.jpg')## Uncomment to open from URL#import requests#r = requests.get('https://www.vegvesen.no/public/webkamera/kamera?id=131206')#pil_im = Image.open(BytesIO(r.content))
im_array = np.asarray(pil_im)
plt.imshow(im_array)
plt.show()
But I think the image is not getting converted to CV format. The Window shows me a large brown image.
Where am I going wrong in Converting image from PIL to CV format?
Also , why do i need to type cv.cv to access functions?
You can use the BytesIO class to get a wrapper around strings that behaves like a file. The BytesIO object provides the same interface as a file, but saves the contents just in memory:
import io
with io.BytesIO() as output:
image.save(output, format="GIF")
contents = output.getvalue()
You have to explicitly specify the output format with the format parameter, otherwise PIL will raise an error when trying to automatically detect it.
If you loaded the image from a file it has a format parameter that contains the original file format, so in this case you can use format=image.format.
In old Python 2 versions before introduction of the io module you would have used the StringIO module instead.
回答 1
对于Python3,需要使用BytesIO:
from io importBytesIOfrom PIL importImage,ImageDraw
image =Image.new("RGB",(300,50))
draw =ImageDraw.Draw(image)
draw.text((0,0),"This text is drawn on image")
byte_io =BytesIO()
image.save(byte_io,'PNG')
importStringIO
output =StringIO.StringIO()
format ='PNG'# or 'JPEG' or whatever you want
image.save(output, format)
contents = output.getvalue()
output.close()
With modern (as of mid-2017 Python 3.5 and Pillow 4.0):
StringIO no longer seems to work as it used to. The BytesIO class is the proper way to handle this. Pillow’s save function expects a string as the first argument, and surprisingly doesn’t see StringIO as such. The following is similar to older StringIO solutions, but with BytesIO in its place.
from io import BytesIO
from PIL import Image
image = Image.open("a_file.png")
faux_file = BytesIO()
image.save(faux_file, 'png')