203

サイズが 3841 x 7195 ピクセルの画像があるとします。Figure の内容をディスクに保存して、ピクセルで指定した正確なサイズの画像を作成したいと思います。

軸なし、タイトルなし。ちょうどイメージ。個人的には DPI については気にしません。画面で画像が取るサイズをピクセル単位で指定したいだけです。

私は他の スレッドを読みましたが、それらはすべてインチへの変換を行ってから、フィギュアの寸法をインチで指定し、何らかの方法でdpiを調整しているようです。ピクセルからインチへの変換に起因する可能性のある精度の潜在的な損失に対処したくありません。

私は試してみました:

w = 7195
h = 3841
fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(im_np, aspect='normal')
fig.savefig(some_path, dpi=1)

運が悪い(Pythonは、幅と高さがそれぞれ32768未満でなければならないと文句を言う(?))

私が見たすべてからmatplotlib、図のサイズを と で指定する必要がありますがinches、図がディスクで取るピクセルdpiにのみ関心があります。これどうやってするの?

matplotlib明確にするために:他の画像保存ライブラリではなく、でこれを行う方法を探しています。

4

9 に答える 9

229

Matplotlib はピクセルを直接操作するのではなく、物理サイズと DPI を操作します。特定のピクセル サイズで Figure を表示する場合は、モニターの DPI を知る必要があります。たとえば、このリンクはそれを検出します。

3841x7195 ピクセルの画像がある場合、モニターがそれほど大きくなる可能性は低いため、そのサイズの図を表示することはできません (サイズを要求する場合、matplotlib では画面に収まる図が必要です)大きすぎると画面サイズに縮小されます)。例として、800x800 ピクセルの画像が必要だとしましょう。モニターに 800x800 ピクセルの画像を表示する方法は次のとおりです ( my_dpi=96)。

plt.figure(figsize=(800/my_dpi, 800/my_dpi), dpi=my_dpi)

したがって、基本的には、インチ単位の寸法を DPI で割るだけです。

特定のサイズの図を保存したい場合は、別の問題です。画面の DPI はもはやそれほど重要ではありません (画面に収まらない数値を要求しない限り)。800x800 ピクセルの図の同じ例を使用すると、dpiキーワード ofを使用してさまざまな解像度で保存できますsavefig。画面と同じ解像度で保存するには、同じ dpi を使用します。

plt.savefig('my_fig.png', dpi=my_dpi)

8000x8000 ピクセルの画像として保存するには、10 倍の dpi を使用します。

plt.savefig('my_fig.png', dpi=my_dpi * 10)

DPI の設定は、すべてのバックエンドでサポートされているわけではないことに注意してください。ここでは、PNG バックエンドが使用されていますが、pdf および ps バックエンドではサイズの実装が異なります。また、DPI とサイズを変更すると、フォントサイズなどにも影響します。DPI を大きくすると、フォントと要素の相対的なサイズは同じに保たれますが、図を大きくするためにフォントを小さくしたい場合は、DPI ではなく物理的なサイズを大きくする必要があります。

例に戻って、3841 x 7195 ピクセルの画像を保存する場合は、次のようにします。

plt.figure(figsize=(3.841, 7.195), dpi=100)
( your code ...)
plt.savefig('myfig.png', dpi=1000)

ほとんどの画面に収まるように 100 の数値 dpi を使用しましたがdpi=1000、必要な解像度を達成するために で保存したことに注意してください。私のシステムでは、これにより 3840x7190 ピクセルの png が生成されます。保存される DPI は、選択した値より常に 0.02 ピクセル/インチ小さいようです。これは、大きな画像サイズに (小さな) 影響を与えます。ここでこれについてさらに議論します。

于 2012-12-05T01:04:51.907 に答える
22

あなたのコードに基づいて、これは私にとってはうまくいき、カラーノイズと目的の寸法を持つ93Mbのpng画像を生成しました:

import matplotlib.pyplot as plt
import numpy

w = 7195
h = 3841

im_np = numpy.random.rand(h, w)

fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(im_np, aspect='normal')
fig.savefig('figure.png', dpi=1)

Linux Mint 13 で Python 2.7 ライブラリの最新の PIP バージョンを使用しています。

それが役立つことを願っています!

于 2012-12-05T01:26:23.507 に答える
11

OP は 1:1 のピクセル データを保持したいと考えています。科学画像を扱う天文学者として、未知の予測不可能なノイズやエラーが発生するため、画像データの補間を許可することはできません。たとえば、pyplot.savefig() で保存された 480x480 の画像のスニペットは次のとおりです

ほとんどのピクセルは単純に 2 倍になっている (1x1 ピクセルが 2x2 になる) ことがわかりますが、一部の列と行はピクセルあたり 1x2 または 2x1 になり、元の科学データが変更されたことを意味します。

アルカが示唆しているように、OPが求めているものを達成する plt.imsave() 。画像データが画像配列 im に格納されているとします。次のようなことができます。

plt.imsave(fname='my_image.png', arr=im, cmap='gray_r', format='png')

この例では、ファイル名の拡張子は「png」です (ただし、私が知る限り、とにかく format='png' で形式を指定する必要があります)、画像配列は arr で、反転グレースケール「gray_r」を選択しました。カラーマップとして。通常、動的範囲を指定するために vmin と vmax を追加しますが、これらはオプションです。

最終結果は、im 配列とまったく同じピクセル寸法の png ファイルです。

注:OPは軸などを指定していません。これは、このソリューションが正確に行うことです。軸、目盛りなどを追加したい場合、私の好ましいアプローチは、別のプロットでそれを行い、transparent=True (PNG または PDF) で保存してから、後者を画像に重ねることです。これにより、元のピクセルがそのまま保持されていることが保証されます。

于 2020-07-25T18:03:08.440 に答える