source

정확한 크기(픽셀)로 그림 지정 및 저장

manysource 2022. 11. 3. 21:58

정확한 크기(픽셀)로 그림 지정 및 저장

3841 x 7195 픽셀 크기의 이미지가 있다고 가정합니다.그림 내용을 디스크에 저장하여 픽셀 단위로 지정한 정확한 크기의 이미지를 만들고 싶습니다.

축도 제목도 없습니다.이미지만.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기타 이미지 저장 라이브러리에는 적용되지 않습니다.

Matplotlib은 픽셀에서 직접 동작하는 것이 아니라 물리적 크기와 DPI에서 동작합니다.특정 픽셀 크기로 수치를 표시하려면 모니터의 DPI를 알아야 합니다.를 들어 링크는 이를 검출합니다.

이미지가 3841x7195픽셀인 경우 모니터 크기가 그리 크지 않을 수 있으므로 해당 크기의 수치를 화면에 표시할 수 없습니다(매트플로리브는 크기가 너무 크면 화면 크기로 축소됩니다).예를 들면, 800 x 800 픽셀의 이미지가 필요한 경우를 가정해 보겠습니다. x x 800 픽셀)를 하는 방법은 .my_dpi=96

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

즉, 기본적으로 치수를 DPI로 나눕니다.

특정 크기의 그림을 저장하려면 다른 문제입니다.화면 DPI는 더 이상 중요하지 않습니다(화면에 맞지 않는 수치를 요구하지 않는 한).x같은 x 800 픽셀의 해상도를 할 수 .dpi '''savefig. 를 화면과 동일한 해상도로 저장하려면 동일한 dpi를 사용합니다.

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

8000x8000픽셀 이미지로 저장하려면 dpi를 10배 크게 사용합니다.

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)

를 사용하여 했습니다.dpi=1000필요한 해결 방법을 얻습니다.시스템에서 3840x7190픽셀의 png이 생성됩니다.저장된 DPI는 항상 선택한 값보다 0.02픽셀/인치 작기 때문에 큰 이미지 사이즈에 (작은) 영향을 줍니다.여기서 이것에 대해 좀 더 논의해 봅시다.

이것은 당신의 코드를 기반으로 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 버전을 사용하고 있습니다.

도움이 됐으면 좋겠네요!

OP는 1:1 픽셀 데이터를 보존하려고 합니다.과학 이미지로 작업하는 천문학자로서 이미지 데이터의 보간은 알려지지 않은 예측 불가능한 노이즈나 오류를 발생시키기 때문에 허용할 수 없습니다.예를 들어 pyplot.savefig()를 통해 저장된480x480 이미지의 일부를 나타냅니다.matplotlib가 약 2x2로 재샘플링된 픽셀의 상세.단, 1x2 픽셀의 컬럼에 주목해 주세요.

대부분의 픽셀은 단순히 두 배(1x1 픽셀은 2x2가 됩니다)이지만 일부 열과 행은 픽셀당 1x2 또는 2x1이 됩니다.이것은 원래 과학 데이터가 변경되었음을 의미합니다.

Alka가 암시한 바와 같이, plt.imsave()는 OP가 요구하는 바를 달성합니다.이미지 배열 im에 저장된 이미지 데이터가 있다고 가정하면 다음과 같은 작업을 수행할 수 있습니다.

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

이 예에서는 파일 이름에 "png" 확장자가 붙습니다(단, 포맷은 포맷='png'로 지정해야 합니다). 이미지 배열은 arr이며 반전 그레이스케일 "colormap"을 선택했습니다.일반적으로 vmin 및 vmax를 추가하여 동적 범위를 지정하지만 이러한 범위는 선택 사항입니다.

최종 결과는 im 배열과 정확히 동일한 픽셀 치수의 png 파일입니다.

주의: OP는 축 등을 지정하지 않았습니다.이것은 이 솔루션이 정확히 하고 있는 것입니다.축, 눈금 등을 추가하고 싶은 경우 별도의 플롯에서 투명=으로 저장하는 것이 좋습니다.True(PNG 또는 PDF)를 선택한 다음 후 후자를 이미지에 오버레이합니다.이렇게 하면 원래 픽셀이 그대로 유지됩니다.

tiago가 받아들인 응답에 기초하여 numpy 어레이를 어레이와 같은 해상도의 이미지로 내보내는 작은 범용 함수를 다음에 나타냅니다.

import matplotlib.pyplot as plt
import numpy as np

def export_figure_matplotlib(arr, f_name, dpi=200, resize_fact=1, plt_show=False):
    """
    Export array as figure in original resolution
    :param arr: array of image to save in original resolution
    :param f_name: name of file where to save figure
    :param resize_fact: resize facter wrt shape of arr, in (0, np.infty)
    :param dpi: dpi of your screen
    :param plt_show: show plot or not
    """
    fig = plt.figure(frameon=False)
    fig.set_size_inches(arr.shape[1]/dpi, arr.shape[0]/dpi)
    ax = plt.Axes(fig, [0., 0., 1., 1.])
    ax.set_axis_off()
    fig.add_axes(ax)
    ax.imshow(arr)
    plt.savefig(f_name, dpi=(dpi * resize_fact))
    if plt_show:
        plt.show()
    else:
        plt.close()

tiago의 이전 답변에서 설명한 바와 같이 화면 DPI를 먼저 찾아야 합니다.예를 들어 http://dpi.lv에서 할 수 있습니다.

가 또 resize_fact예를 들어, 이미지를 원래 해상도의 50%(0.5)로 내보낼 수 있는 기능입니다.

다양한 접근법 비교

다음은 제가 시도한 접근법 중 몇 가지와 그 결과를 보여주는 이미지를 간략하게 비교한 것입니다.

이미지 치수를 설정하지 않고 베이스라인 예

비교 포인트:

base.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

fig, ax = plt.subplots()
print('fig.dpi = {}'.format(fig.dpi))
print('fig.get_size_inches() = ' + str(fig.get_size_inches())
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig('base.png', format='png')

실행:

./base.py
identify base.png

출력:

fig.dpi = 100.0
fig.get_size_inches() = [6.4 4.8]
base.png PNG 640x480 640x480+0+0 8-bit sRGB 13064B 0.000u 0:00.000

여기에 이미지 설명 입력

나의 : 금지의 my my my my my my my my my :plt.savefig(dpi=h/fig.get_size_inches()[1] 전용

심플하고 확장성이 뛰어나기 때문에 대부분의 경우 다음과 같이 생각하고 있습니다.

get_size를 선택합니다.화이

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

height = int(sys.argv[1])
fig, ax = plt.subplots()
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'get_size.png',
    format='png',
    dpi=height/fig.get_size_inches()[1]
)

실행:

./get_size.py 431

출력:

get_size.png PNG 574x431 574x431+0+0 8-bit sRGB 10058B 0.000u 0:00.000

여기에 이미지 설명 입력

그리고.

./get_size.py 1293

출력:

main.png PNG 1724x1293 1724x1293+0+0 8-bit sRGB 46709B 0.000u 0:00.000

여기에 이미지 설명 입력

보통 텍스트 중간에 이미지가 차지하는 세로 공간이 얼마나 될까가 가장 걱정되기 때문에 높이만 설정하는 경향이 있습니다.

plt.savefig(bbox_inches='tight' size " " changes

에, 주위에 여백이 너무 많이 을 합니다.bbox_inches='tight'시작: matplotlib에서 저장된 이미지 주위의 공백 제거

다만, 이미지를 잘라내는 것으로, 원하는 사이즈를 얻을 수 없습니다.

대신, 같은 질문에서 제안된 다른 접근법이 잘 작동하는 것 같습니다.

plt.tight_layout(pad=1)
plt.savefig(...

그러면 높이가 431인 정확한 높이를 알 수 있습니다.

여기에 이미지 설명 입력

높이, 고정 높이, 고정 높이,set_aspect 여백, 「」

set_aspect plt.tight_layout...

질문: 고정 높이(픽셀 단위), 고정 데이터 x/y 석면비를 얻고 Matplotlib에서 수평 여백을 자동으로 제거하는 방법

plt.savefig(dpi=h/fig.get_size_inches()[1]폭 + 폭 컨트롤

높이와 더불어 특정 폭이 필요한 경우 다음과 같이 문제없이 작동합니다.

width.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

h = int(sys.argv[1])
w = int(sys.argv[2])
fig, ax = plt.subplots()
wi, hi = fig.get_size_inches()
fig.set_size_inches(hi*(w/h), hi)
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'width.png',
    format='png',
    dpi=h/hi
)

실행:

./width.py 431 869

출력:

width.png PNG 869x431 869x431+0+0 8-bit sRGB 10965B 0.000u 0:00.000

여기에 이미지 설명 입력

폭이 작은 경우:

./width.py 431 869

출력:

width.png PNG 211x431 211x431+0+0 8-bit sRGB 6949B 0.000u 0:00.000

여기에 이미지 설명 입력

되고 있는 것 만, 작은 라벨이 잘리는 등 매우 작은 너비에 문제가 있을 뿐입니다.100왼쪽 상단에 있습니다.

matplotlib에 저장된 이미지 주변의 공백을 제거하는 작업을 수행할 수 있었습니다.

plt.tight_layout(pad=1)

그 결과, 다음과 같습니다.

width.png PNG 211x431 211x431+0+0 8-bit sRGB 7134B 0.000u 0:00.000

여기에 이미지 설명 입력

보면 '도 알 수 요'라는 것을 알 수 있어요.tight_layout이미지 상단의 빈 공간을 많이 없애기 때문에 항상 사용하고 있습니다.

높이, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★,dpifig.set_size_inches ★★★★★★★★★★★★★★★★★」plt.savefig(dpi=

이것은, https://stackoverflow.com/a/13714720/895245 에서 언급되고 있는 어프로치와 동등합니다.

magic.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

magic_height = 300
w = int(sys.argv[1])
h = int(sys.argv[2])
dpi = 80
fig, ax = plt.subplots(dpi=dpi)
fig.set_size_inches(magic_height*w/(h*dpi), magic_height/dpi)
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'magic.png',
    format='png',
    dpi=h/magic_height*dpi,
)

실행:

./magic.py 431 231

출력:

magic.png PNG 431x231 431x231+0+0 8-bit sRGB 7923B 0.000u 0:00.000

여기에 이미지 설명 입력

확장성이 뛰어난지 확인합니다.

./magic.py 1291 693

출력:

magic.png PNG 1291x693 1291x693+0+0 8-bit sRGB 25013B 0.000u 0:00.000

여기에 이미지 설명 입력

따라서 이 접근법도 효과적입니다.한가 있다면, 이 설정을 입니다.magic_height파라미터 또는 동등한 것.

DPI + 정 d DPI +set_size_inches

이 방법에서는 픽셀 크기가 약간 잘못되어 모든 것을 매끄럽게 확장하기가 어렵습니다.

set_size_module을 클릭합니다.화이

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

w = int(sys.argv[1])
h = int(sys.argv[2])
fig, ax = plt.subplots()
fig.set_size_inches(w/fig.dpi, h/fig.dpi)
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(
    0,
    60.,
    'Hello',
    # Keep font size fixed independently of DPI.
    # https://stackoverflow.com/questions/39395616/matplotlib-change-figsize-but-keep-fontsize-constant
    fontdict=dict(size=10*h/fig.dpi),
)
plt.savefig(
    'set_size_inches.png',
    format='png',
)

실행:

./set_size_inches.py 431 231

출력:

set_size_inches.png PNG 430x231 430x231+0+0 8-bit sRGB 8078B 0.000u 0:00.000

높이가 약간 떨어져 있고 이미지는 다음과 같이 표시됩니다.

여기에 이미지 설명 입력

픽셀 사이즈는, 3배로 크게 해도 올바른 크기입니다.

./set_size_inches.py 1291 693

출력:

set_size_inches.png PNG 1291x693 1291x693+0+0 8-bit sRGB 19798B 0.000u 0:00.000

여기에 이미지 설명 입력

그러나 이 접근방식을 적절하게 확장하려면 모든 DPI 의존 설정을 인치 단위로 비례시켜야 한다는 것을 알 수 있습니다.

이전 예에서는 "Hello" 텍스트는 비례적으로만 작성되었으며 예상대로 60에서 80 사이의 높이를 유지했습니다.하지만 우리가 그렇게 하지 않은 모든 것은 아주 작아 보입니다.

  • 축의 선폭
  • 체크 라벨
  • 포인트 마커

SVG

SVG 이미지에 대해 설정하는 방법을 찾을 수 없었습니다. 내 접근 방식은 PNG에서만 작동했습니다. 예:

get_size_sizeg.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

height = int(sys.argv[1])
fig, ax = plt.subplots()
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'get_size_svg.svg',
    format='svg',
    dpi=height/fig.get_size_inches()[1]
)

실행:

./get_size_svg.py 431

생성되는 출력은 다음과 같습니다.

<svg height="345.6pt" version="1.1" viewBox="0 0 460.8 345.6" width="460.8pt"

다음 내용을 확인합니다.

get_size_svg.svg SVG 614x461 614x461+0+0 8-bit sRGB 17094B 0.000u 0:00.000

Cromium 86에서 열면 브라우저 디버깅툴 마우스 이미지가 460.79로 표시됩니다.

물론 SVG는 벡터 형식이기 때문에 이론적으로 모든 것이 확장되어야 하므로 해상도 손실 없이 고정 크기 형식으로 변환할 수 있습니다.

inkscape -h 431 get_size_svg.svg -b FFF -e get_size_svg.png

는 정확한 높이를 제공합니다.

TODO가 이미지를 재생성해서 업로드가 엉망이 됐어요

Imagemagick 대신 를 사용합니다.convert서, 「이러다」를 가 있기 에, 「이러다」를 사용해 주세요.-densityImageMagick SVG の 을mag 。

설정 ★★<img height=""이치노

matplotlib==3.2.2에서 테스트했습니다.

저도 같은 문제가 있었어요.PIL 이미지를 사용하여 이미지를 로드하고 Numpy 배열로 변환한 후 matplotlib를 사용하여 직사각형에 패치를 적용했습니다.jpg 이미지였기 때문에 PIL img.info ['dpi']에서 dpi를 얻을 방법이 없었기 때문에 수용된 솔루션이 작동하지 않았습니다.하지만 약간의 손질을 한 후 오리지널과 같은 크기로 피규어를 저장할 방법을 알아냈습니다.

저와 같은 문제를 안고 있던 분에게 도움이 될 것 같아서 다음과 같은 해결책을 추가합니다.

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np

img = Image.open('my_image.jpg') #loading the image
image = np.array(img) #converting it to ndarray
dpi = plt.rcParams['figure.dpi'] #get the default dpi value
fig_size = (img.size[0]/dpi, img.size[1]/dpi) #saving the figure size
fig, ax = plt.subplots(1, figsize=fig_size) #applying figure size
#do whatver you want to do with the figure
fig.tight_layout() #just to be sure
fig.savefig('my_updated_image.jpg') #saving the image

그러면 원래 이미지와 동일한 해상도로 이미지가 저장됩니다.

주피터 노트북을 사용하지 않는 경우.dpi는 다음과 같은 방법으로 얻을 수 있습니다.

figure = plt.figure()
dpi = figure.dpi

이 솔루션은 matplotlib 버전 3.0.1, 3.0.3 및 3.2.1에서 작동합니다.

def save_inp_as_output(_img, c_name, dpi=100):
    h, w, _ = _img.shape
    fig, axes = plt.subplots(figsize=(h/dpi, w/dpi))
    fig.subplots_adjust(top=1.0, bottom=0, right=1.0, left=0, hspace=0, wspace=0) 
    axes.imshow(_img)
    axes.axis('off')
    plt.savefig(c_name, dpi=dpi, format='jpeg') 

subplots_adjust 설정에서는 축이 그림을 채우므로 bbox_sublots='tight'를 지정할 필요가 없습니다.이 경우 공백 패딩이 실제로 생성되기 때문입니다.이 솔루션은 하위구가 두 개 이상 있는 경우에도 작동합니다.

matplotlib? matplotlib? matplotlib?
이미지가 형상(3841, 7195, 3)을 가진 numpy 어레이이고 데이터 타입이 numpy.uint8이고 rbg 값 범위가 0 ~255인 경우 matplotlib를 사용하지 않고 이 어레이를 이미지로 저장할 수 있습니다.

from PIL import Image
im = Image.fromarray(A)
im.save("your_file.jpeg")

다른 게시물에서 이 코드를 찾았습니다.

matplotlib 참조에는 그림 크기를 다른 단위로 설정하기 위한 han에 대한 예가 있습니다.픽셀의 경우:

px = 1/plt.rcParams['figure.dpi']  # pixel in inches
plt.subplots(figsize=(600*px, 200*px))
plt.text(0.5, 0.5, '600px x 200px', **text_kwargs)
plt.show()

https://matplotlib.org/stable/gallery/subplots_axes_and_figures/figure_size_units.html#

plt.imsave는 나에게 효과가 있었다.매뉴얼은 https://matplotlib.org/3.2.1/api/_as_gen/matplotlib.pyplot.imsave.html 에서 찾을 수 있습니다.

#file_path = directory address where the image will be stored along with file name and extension
#array = variable where the image is stored. I think for the original post this variable is im_np
plt.imsave(file_path, array)

언급URL : https://stackoverflow.com/questions/13714454/specifying-and-saving-a-figure-with-exact-size-in-pixels