在情节上添加透明图片

时间:2018-08-12 12:52:26

标签: python image matplotlib matplotlib-basemap

下面的我的python脚本在使用Basemap模块生成的地图上添加了图片(在此简单示例中为生成的矩形)和GPS轨迹。
现在,我想使两个轨道都成为透明的矩形。通过alpha kwarg播放的曲目没有问题,但我无法确定图片的处理方法。

import matplotlib.pyplot as plt
from PIL import Image
from matplotlib.offsetbox import AnnotationBbox, OffsetImage
from mpl_toolkits.basemap import Basemap

lats = [ 45, 15  ]
lons = [ 0 , 100 ]

fig = plt.figure( dpi = 300 )
ax  = plt.subplot(111)

myBaseMap = Basemap( projection='ortho', lat_0=lats[-1], lon_0=lons[-1] )
myBaseMap.bluemarble()

planeImg = Image.new('RGB', (600, 300), color = 'red')
planeXY  = myBaseMap( lons[-1], lats[-1] )
x,y      = myBaseMap( lons, lats )

plt.plot( x, y, color='r', alpha=0.5, linewidth=3  )

imagebox = OffsetImage( planeImg , zoom=.4 )

ab = AnnotationBbox( imagebox, myBaseMap( lons[-1], lats[-1] ), xybox=( 0., 0. ), xycoords='data', boxcoords='offset points', frameon=False )
ax.add_artist(ab)
plt.show()

此代码将产生以下带有透明线的图片。 现在,我想以相同的方式使红色矩形透明。

我试图在注解框和斧头上使用set_alpha方法,但是没有用。
有任何想法吗 ?

谢谢。

2 个答案:

答案 0 :(得分:1)

如果您在创建图像OffsetImage之前 为图像设置了alpha值,则结果将按预期显示。 this answer中说明了如何设置枕头图像的alpha值。请注意,alpha值必须介于0到255之间,而不是0到1之间。简而言之,您只需在代码中添加一行(请注意,我更改了图像分辨率):

import matplotlib.pyplot as plt
from PIL import Image
from matplotlib.offsetbox import AnnotationBbox, OffsetImage
from mpl_toolkits.basemap import Basemap

lats = [ 45, 15  ]
lons = [ 0 , 100 ]

fig = plt.figure( dpi = 100 )
ax  = plt.subplot(111)

myBaseMap = Basemap( projection='ortho', lat_0=lats[-1], lon_0=lons[-1] )
myBaseMap.bluemarble()

planeImg = Image.new('RGB', (600, 300), color = 'red')
planeImg.putalpha(128)

planeXY  = myBaseMap( lons[-1], lats[-1] )
x,y      = myBaseMap( lons, lats )

plt.plot( x, y, color='r', alpha=0.5, linewidth=3  )

imagebox = OffsetImage( planeImg , zoom=.4 )

ab = AnnotationBbox( imagebox, myBaseMap( lons[-1], lats[-1] ), xybox=( 0., 0. ), xycoords='data', boxcoords='offset points', frameon=False )
ax.add_artist(ab)
plt.show()

获得以下图像:

result of the above code

答案 1 :(得分:1)

除了托马斯·库恩(ThomasKühn)的答案:如果我将他的代码用于真实图片(带有透明区域的png红色平面)而不是红色矩形:我得到下面的图片。

enter image description here

正如您所看到的,png透明区域被解释为黑色,因此,在地图上我不仅拥有透明的黑色正方形,而且还没有透明的平面。 在托马斯的链接的帮助下,我找到了一种摆脱这种情况的方法,请参见下面的代码(不要忘记在运行之前更改图片路径)。

import matplotlib.pyplot as plt
from PIL import Image
from matplotlib.offsetbox import AnnotationBbox, OffsetImage
from mpl_toolkits.basemap import Basemap

lats = [ 45, 15  ]
lons = [ 0 , 100 ]

fig = plt.figure( dpi = 100 )
ax  = plt.subplot(111)

myBaseMap = Basemap( projection='ortho', lat_0=lats[-1], lon_0=lons[-1] )
myBaseMap.bluemarble()

# /!\ /!\ /!\ CHOOSE A PNG OF YOUR OWN TO RUN THE SCRIPT /!\ /!\ /!\
imgPath  = './avion.png'
planeImg = Image.open( imgPath )
data     = planeImg.getdata()
newData  = []
myAlpha  = 150
# loop through pixels in planeImg
for item in data:
    # item[3] is the current pixel alpha value. When 0: transparent area on png, leave it at 0
    # item[{0, 1, 2}] is pixel {R,G,B} value
    if item[3] == 0:
        newData.append( (item[0], item[1], item[2], 0) )
    # else the current pixel is a part of the plane: set alpha to desired value
    else:
        newData.append( (item[0], item[1], item[2], myAlpha) )
planeImg.putdata( newData )

planeXY  = myBaseMap( lons[-1], lats[-1] )
x,y      = myBaseMap( lons, lats )

plt.plot( x, y, color='r', alpha=0.5, linewidth=3  )

imagebox = OffsetImage( planeImg , zoom=.4 )

ab = AnnotationBbox( imagebox, myBaseMap( lons[-1], lats[-1] ), xybox=( 0., 0. ), xycoords='data', boxcoords='offset points', frameon=False )
ax.add_artist(ab)
plt.show()

这段代码产生下面的图片,这正是我想要的。 谢谢托马斯·库恩。

enter image description here