Matplotlib - 无法以与原始图像相同的分辨率保存图像

18

我无法在不保留白边且以初始分辨率(1037x627)保存该图像。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import pyplot, lines
import matplotlib.image as mpimg
from matplotlib.patches import Ellipse
x=[0,0,0,0,0]
y=[0,0,0,0,0]
a=10**1.3*15
inc=25
b=np.cos(np.radians(inc))*a
x[0],y[0]=516.667,313.021
x[1],y[1]=x[0]-a,y[0]
x[2],y[2]=x[0]+a,y[0]
x[3],y[3]=x[0],y[0]+b
x[4],y[4]=x[0],y[0]-b
for pa in range(0,10,5):
    fig, ax = plt.subplots()
    img=mpimg.imread('IC342.png')
    imgplot = plt.imshow(img)
    x[1],y[1]=x[0]-a/2*np.cos(np.radians(pa)),y[0]-a/2*np.sin(np.radians(pa))
    x[2],y[2]=x[0]+a/2*np.cos(np.radians(pa)),y[0]+a/2*np.sin(np.radians(pa))
    x[3],y[3]=x[0]+b/2*np.cos(np.radians(pa+90)),y[0]+b/2*np.sin(np.radians(pa+90))
    x[4],y[4]=x[0]-b/2*np.cos(np.radians(pa+90)),y[0]-b/2*np.sin(np.radians(pa+90))
    ell = Ellipse(xy=[516.667,313.021], width=a, height=b, angle=pa, edgecolor='b',lw=4, alpha=0.5, facecolor='none')
    name='plt'+str(pa)+'.png'
    leg='PA='+str(pa)
    #ax.text(10, 10, leg, fontsize=15,color='white')
    ax.add_artist(ell)
    xn=[x[1],x[2],x[0]]
    yn=[y[1],y[2],y[0]]
    xnw=[x[3],x[4],x[0]]
    ynw=[y[3],y[4],y[0]]
    line = lines.Line2D(xn, yn, linestyle='-.',lw=5., color='r', alpha=0.4)
    line1 = lines.Line2D(xnw, ynw, linestyle='-.',lw=5., color='g', alpha=0.4)
    ax.add_line(line)
    ax.add_line(line1)
    plt.axis('off')
    fig.savefig(name, transparent=True, bbox_inches='tight', pad_inches=0,dpi=150 )

初始图片

初始图片

结果

结果图片

同时,我需要白色文本PA=something显示在图片上,而不改变分辨率。据我所知,添加另一个类似文本的元素可能会自动更改分辨率。

感谢您的时间!

1个回答

39
这里有两个因素:
  1. Axes默认情况下不占据整个Figure
  2. matplotlib中,Figure的大小是固定的,内容被拉伸/压缩/插值以适应图形。您需要通过其内容定义Figure的大小。
要做到你想做的事情,需要三个步骤:
  1. 基于图像大小和设置的DPI创建一个图形
  2. 添加一个占据整个图形的subplot/axes
  3. 使用计算出的图形大小保存图形的DPI
我们使用来自NASA的随机哈勃图片http://www.nasa.gov/sites/default/files/thumbnails/image/hubble_friday_12102015.jpg。它是一张1280x1216像素的图片。
以下是一个详细注释的示例,帮助您完成:
import matplotlib.pyplot as plt

# On-screen, things will be displayed at 80dpi regardless of what we set here
# This is effectively the dpi for the saved figure. We need to specify it,
# otherwise `savefig` will pick a default dpi based on your local configuration
dpi = 80

im_data = plt.imread('hubble_friday_12102015.jpg')
height, width, nbands = im_data.shape

# What size does the figure need to be in inches to fit the image?
figsize = width / float(dpi), height / float(dpi)

# Create a figure of the right size with one axes that takes up the full figure
fig = plt.figure(figsize=figsize)
ax = fig.add_axes([0, 0, 1, 1])

# Hide spines, ticks, etc.
ax.axis('off')

# Display the image.
ax.imshow(im_data, interpolation='nearest')

# Add something...
ax.annotate('Look at This!', xy=(590, 650), xytext=(500, 500),
            color='cyan', size=24, ha='right',
            arrowprops=dict(arrowstyle='fancy', fc='cyan', ec='none'))

# Ensure we're displaying with square pixels and the right extent.
# This is optional if you haven't called `plot` or anything else that might
# change the limits/aspect.  We don't need this step in this case.
ax.set(xlim=[-0.5, width - 0.5], ylim=[height - 0.5, -0.5], aspect=1)

fig.savefig('test.jpg', dpi=dpi, transparent=True)
plt.show()

enter image description here

保存的test.jpg将会是精确的1280x1216像素。当然,由于我们使用了有损压缩格式来处理输入和输出,因此由于压缩失真,你不会得到完美的像素匹配。如果你使用无损输入和输出格式,那么就可以得到完美的匹配。


2
哦,我的天啊,非常感谢!!!这个解释正是我所需要的,仅仅修复问题是不够的,我真的想知道将来要避免什么。我以前从未使用过注释,只用了纯文本,这非常有用,我再次感激不尽! - Tigs
2
@Tigs - 很高兴能帮忙! - Joe Kington
他们在这里说https://dev59.com/NF4b5IYBdhLWcg3wrzbY#53816322,它从80dpi变为100dpi,因此请使用`dpi = matplotlib.rcParams ['figure.dpi']`而不是固定数字。 - Brambor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接